From 636b38438001a00b25f23e38747a91cb8428af29 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:30:57 -0500 Subject: [PATCH] Import 2.3.43 --- CREDITS | 7 + Documentation/Configure.help | 127 +++- arch/i386/defconfig | 2 +- arch/i386/kernel/Makefile | 8 - arch/i386/kernel/pci-pc.c | 14 + arch/ppc/kernel/feature.c | 1 + arch/ppc/kernel/galaxy_pci.c | 510 ------------- arch/ppc/kernel/open_pic.c | 1 + arch/ppc/kernel/walnut_setup.c | 1180 ----------------------------- arch/ppc/kernel/walnut_setup.h | 200 ----- arch/sparc/config.in | 16 +- arch/sparc/defconfig | 4 + arch/sparc64/config.in | 16 +- arch/sparc64/defconfig | 4 + drivers/block/hpt366.c | 1 + drivers/block/loop.c | 6 +- drivers/char/agp/agp.h | 25 +- drivers/char/agp/agpgart_be.c | 545 ++++++------- drivers/char/agp/agpgart_fe.c | 62 +- drivers/char/efirtc.c | 13 +- drivers/char/pc110pad.c | 231 +++++- drivers/char/wdt.c | 132 +++- drivers/net/3c501.c | 140 ++-- drivers/net/3c503.c | 1 - drivers/net/3c507.c | 47 +- drivers/net/3c509.c | 208 +++-- drivers/net/3c523.c | 263 +++---- drivers/net/3c527.c | 147 ++-- drivers/net/3c59x.c | 178 ++--- drivers/net/Config.in | 2 +- drivers/net/Makefile | 84 +- drivers/net/ac3200.c | 3 - drivers/net/acenic.c | 22 +- drivers/net/bmac.c | 25 +- drivers/net/de4x5.c | 29 +- drivers/net/dgrs.c | 54 +- drivers/net/dmfe.c | 40 +- drivers/net/eepro.c | 180 ++--- drivers/net/eepro100.c | 32 +- drivers/net/epic100.c | 204 ++--- drivers/net/gmac.c | 22 +- drivers/net/hp100.c | 61 +- drivers/net/ltpc.c | 16 +- drivers/net/mace.c | 31 +- drivers/net/myri_sbus.c | 23 +- drivers/net/ncr885e.c | 52 +- drivers/net/ne.c | 15 +- drivers/net/ne2k-pci.c | 17 +- drivers/net/ni5010.c | 2 +- drivers/net/ni65.c | 2 +- drivers/net/oaknet.c | 43 +- drivers/net/pcnet32.c | 89 +-- drivers/net/plip.c | 27 +- drivers/net/rcpci45.c | 65 +- drivers/net/setup.c | 143 ---- drivers/net/sis900.c | 77 +- drivers/net/sk98lin/skge.c | 57 +- drivers/net/sk_g16.c | 53 +- drivers/net/starfire.c | 83 +- drivers/net/sunbmac.c | 23 +- drivers/net/sunhme.c | 22 +- drivers/net/sunlance.c | 29 +- drivers/net/sunqe.c | 23 +- drivers/net/tlan.c | 54 +- drivers/net/tokenring/smctr.c | 8 +- drivers/net/tulip.c | 90 +-- drivers/net/via-rhine.c | 199 ++--- drivers/net/yellowfin.c | 117 +-- drivers/pci/pci.c | 4 +- drivers/sbus/char/flash.c | 8 +- drivers/scsi/hosts.h | 1 + drivers/scsi/sg.c | 1 + drivers/sound/ac97_codec.h | 3 +- drivers/sound/dev_table.c | 14 +- drivers/sound/dev_table.h | 3 + drivers/sound/dmasound.c | 13 +- drivers/sound/soundcard.c | 4 + drivers/usb/keybdev.c | 2 +- drivers/video/atyfb.c | 2 +- fs/adfs/dir.c | 21 - fs/adfs/file.c | 47 +- fs/adfs/inode.c | 31 +- fs/affs/dir.c | 8 - fs/affs/file.c | 37 +- fs/affs/inode.c | 12 +- fs/affs/namei.c | 9 +- fs/affs/symlink.c | 4 +- fs/autofs/dir.c | 15 - fs/autofs/init.c | 4 +- fs/autofs/root.c | 10 - fs/bad_inode.c | 3 - fs/bfs/dir.c | 9 +- fs/bfs/file.c | 48 +- fs/bfs/inode.c | 1 + fs/buffer.c | 386 ++++++---- fs/coda/cnode.c | 119 +-- fs/coda/coda_linux.c | 2 - fs/coda/dir.c | 60 +- fs/coda/file.c | 127 +--- fs/coda/inode.c | 21 +- fs/coda/pioctl.c | 4 - fs/coda/psdev.c | 20 +- fs/coda/symlink.c | 4 +- fs/coda/sysctl.c | 7 +- fs/coda/upcall.c | 65 +- fs/cramfs/inode.c | 117 +-- fs/devpts/root.c | 15 - fs/efs/dir.c | 17 - fs/efs/file.c | 17 - fs/efs/inode.c | 18 +- fs/efs/symlink.c | 4 +- fs/ext2/dir.c | 8 - fs/ext2/file.c | 63 +- fs/ext2/inode.c | 44 +- fs/ext2/namei.c | 4 +- fs/ext2/symlink.c | 10 +- fs/fat/cache.c | 2 +- fs/fat/file.c | 38 +- fs/fat/inode.c | 34 +- fs/fat/misc.c | 2 +- fs/hfs/dir_cap.c | 38 - fs/hfs/dir_dbl.c | 8 - fs/hfs/dir_nat.c | 16 - fs/hfs/file.c | 6 - fs/hfs/file_cap.c | 5 - fs/hfs/file_hdr.c | 6 - fs/hfs/hfs.h | 3 + fs/hfs/inode.c | 31 + fs/hpfs/dir.c | 2 + fs/hpfs/file.c | 62 +- fs/hpfs/hpfs_fn.h | 2 + fs/hpfs/inode.c | 23 +- fs/hpfs/namei.c | 11 +- fs/inode.c | 15 +- fs/ioctl.c | 15 +- fs/isofs/Makefile | 2 +- fs/isofs/dir.c | 15 - fs/isofs/file.c | 17 - fs/isofs/inode.c | 25 +- fs/isofs/rock.c | 6 +- fs/isofs/symlink.c | 27 - fs/lockd/svc.c | 14 +- fs/minix/Makefile | 2 +- fs/minix/dir.c | 8 - fs/minix/file.c | 37 +- fs/minix/inode.c | 50 +- fs/minix/namei.c | 4 +- fs/minix/symlink.c | 22 - fs/msdos/namei.c | 8 - fs/namei.c | 9 +- fs/ncpfs/dir.c | 3 - fs/ncpfs/file.c | 3 - fs/ncpfs/inode.c | 5 +- fs/ncpfs/symlink.c | 4 +- fs/nfs/dir.c | 3 - fs/nfs/file.c | 29 +- fs/nfs/inode.c | 5 +- fs/nfs/write.c | 2 +- fs/nfsd/nfsctl.c | 8 - fs/nfsd/vfs.c | 2 - fs/ntfs/fs.c | 83 +- fs/open.c | 15 +- fs/openpromfs/inode.c | 13 - fs/proc/array.c | 3 +- fs/proc/base.c | 20 +- fs/qnx4/Makefile | 3 +- fs/qnx4/file.c | 129 +--- fs/qnx4/inode.c | 40 +- fs/qnx4/symlinks.c | 26 - fs/romfs/inode.c | 46 +- fs/smbfs/dir.c | 3 - fs/smbfs/file.c | 30 +- fs/smbfs/inode.c | 5 +- fs/sysv/Makefile | 3 +- fs/sysv/dir.c | 8 - fs/sysv/file.c | 39 +- fs/sysv/fsync.c | 3 +- fs/sysv/inode.c | 38 +- fs/sysv/namei.c | 4 +- fs/sysv/symlink.c | 26 - fs/udf/dir.c | 8 - fs/udf/file.c | 201 ++--- fs/udf/fsync.c | 10 - fs/udf/inode.c | 155 ++-- fs/udf/namei.c | 6 +- fs/udf/symlink.c | 21 +- fs/udf/truncate.c | 19 +- fs/udf/udfdecl.h | 9 +- fs/ufs/dir.c | 3 - fs/ufs/file.c | 72 +- fs/ufs/inode.c | 44 +- fs/ufs/namei.c | 4 +- fs/ufs/symlink.c | 10 +- fs/umsdos/Makefile | 3 +- fs/umsdos/dir.c | 8 - fs/umsdos/inode.c | 3 +- fs/umsdos/rdir.c | 8 - fs/umsdos/symlink.c | 22 - fs/vfat/namei.c | 8 - include/asm-i386/io.h | 20 +- include/asm-ia64/atomic.h | 1 - include/linux/adfs_fs_i.h | 1 + include/linux/affs_fs.h | 6 +- include/linux/affs_fs_i.h | 1 + include/linux/agp_backend.h | 1 + include/linux/bfs_fs.h | 1 + include/linux/coda.h | 38 +- include/linux/coda_fs_i.h | 2 + include/linux/coda_linux.h | 4 +- include/linux/coda_psdev.h | 1 + include/linux/efs_fs.h | 2 +- include/linux/ext2_fs.h | 7 +- include/linux/fs.h | 59 +- include/linux/hfs_fs_i.h | 1 + include/linux/hpfs_fs_i.h | 1 + include/linux/iso_fs.h | 6 +- include/linux/minix_fs.h | 5 +- include/linux/msdos_fs.h | 5 - include/linux/msdos_fs_i.h | 2 +- include/linux/nfs_fs.h | 1 + include/linux/ntfs_fs_i.h | 1 + include/linux/pagemap.h | 2 +- include/linux/pci.h | 13 + include/linux/qnx4_fs.h | 1 - include/linux/qnx4_fs_i.h | 1 + include/linux/sched.h | 1 - include/linux/smb_fs.h | 1 + include/linux/sysv_fs.h | 4 +- include/linux/ufs_fs.h | 4 +- include/linux/umsdos_fs.h | 1 - kernel/Makefile | 8 + kernel/exec_domain.c | 5 +- kernel/ksyms.c | 10 +- {arch/i386/kernel => kernel}/pm.c | 0 kernel/sched.c | 4 +- kernel/sysctl.c | 3 - kernel/timer.c | 3 +- mm/filemap.c | 88 ++- net/khttpd/datasending.c | 3 +- net/sunrpc/svcsock.c | 71 +- net/sunrpc/sysctl.c | 5 - net/sunrpc/xprt.c | 37 - net/wanrouter/wanproc.c | 6 - 243 files changed, 3414 insertions(+), 6456 deletions(-) delete mode 100644 fs/isofs/symlink.c delete mode 100644 fs/minix/symlink.c delete mode 100644 fs/qnx4/symlinks.c delete mode 100644 fs/sysv/symlink.c delete mode 100644 fs/umsdos/symlink.c rename {arch/i386/kernel => kernel}/pm.c (100%) diff --git a/CREDITS b/CREDITS index 6aafceed18a9..ad3f5c3ffb07 100644 --- a/CREDITS +++ b/CREDITS @@ -2621,6 +2621,13 @@ D: CMI8330 support is sb_card.c D: ISAPnP fixes in sb_card.c S: Italy +N: Alessandro Zummo +E: azummo@ita.flashnet.it +W: http://freepage.logicom.it/azummo/ +D: CMI8330 support is sb_card.c +D: ISAPnP fixes in sb_card.c +S: Italy + N: Marc Zyngier E: maz@wild-wind.fr.eu.org D: MD driver diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 765e248f8fd9..7a6d81a443f7 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -2347,6 +2347,14 @@ CONFIG_FB_VESA You will get a boot time penguin logo at no additional cost. Please read Documentation/fb/vesafb.txt. If unsure, say Y. +VGA 16-color planar support +CONFIG_FBCON_VGA_PLANES + This low level frame buffer console driver enable the kernel to use + the 16-color planar modes of the old VGA cards where the bits of each + pixel are separated into 4 plans. + Only answer Y here if you have an (very old) VGA card that isn't + VESA 2 compatible. + VGA 16-color graphics console CONFIG_FB_VGA16 This is the frame buffer device driver for VGA 16 color graphic @@ -2357,6 +2365,25 @@ CONFIG_FB_VGA16 running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called vga16fb.o. +VGA 8x16 font +CONFIG_FONT_8x16 + This is the "high resolution" font for the VGA frame buffer (the one + provided by the text console 80x25 mode. + +Support only 8 pixels wide fonts +CONFIG_FBCON_FONTWIDTH8_ONLY + Answer Y here will make the kernel provide only the 8x8 fonts (these + are the less readable). + +VGA 8x8 font +CONFIG_FONT_8x8 + This is the "high resolution" font for the VGA frame buffer (the one + provided by the text console 80x50 (and higher) modes. + Note this is a poor quality font. The VGA 8x16 font is quite a lot + more readable. + Given the resolution provided by the frame buffer device, anwser N + here is safe. + Backward compatibility mode for Xpmac CONFIG_FB_COMPAT_XPMAC If you use the Xpmac X server (common with mklinux), you'll need to @@ -2650,6 +2677,12 @@ CONFIG_PARPORT_AX Ultra/AX machines. This code is also available as a module (say M), called parport_ax.o. If in doubt, saying N is the safe plan. +Support IEEE1284 status readback +CONFIG_PRINTER_READBACK + If you have a device on your parrallel port that support this protocol, + this option'll enable it to report its status. + It is safe to say Y. + IEEE1284 transfer modes CONFIG_PARPORT_1284 If you have a printer that supports status readback or device ID, or @@ -7362,7 +7395,7 @@ CONFIG_DE4X5 Documentation/networking/net-modules.txt. DECchip Tulip (dc21x4x) PCI support -CONFIG_DEC_ELCP +CONFIG_TULIP This driver is developed for the SMC EtherPower series Ethernet cards and also works with cards based on the DECchip 21040/21041/21140 (Tulip series) chips. Some LinkSys PCI cards are @@ -9495,9 +9528,9 @@ CONFIG_NLS_ISO8859_14 from the Microsoft fat filesystem family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 8 character - set, which adds the last accented vowels for Welsh (and Manx Gaelic) - that were missing in Latin 1. http://linux.speech.cymru.org/ - has further information. + set, which adds the last accented vowels for Welsh (aka Cymraeg) + (and Manx Gaelic) hat were missing in Latin 1. + http://linux.speech.cymru.org/ has further information. nls iso8859-15 CONFIG_NLS_ISO8859_15 @@ -10454,6 +10487,11 @@ CONFIG_APPLICOM If unsure, say N. +Enter S1 for sleep (EXPERIMENTAL) +CONFIG_ACPI_S1_SLEEP + This enable ACPI compliant devices to enter level 1 of ACPI saving + power levels. Basically, this will let them entering in sleep mode. + Advanced Power Management CONFIG_APM APM is a BIOS specification for saving power using several different @@ -13055,7 +13093,84 @@ CONFIG_PHONE_IXJ If you do not have any Quicknet telephony cards, you can safely ignore this option. - + +/dev/agpgart (AGP Support) (EXPERIMENTAL) +CONFIG_AGP + The agpgart kernel module is necessary to use the AGP features + of your 3D rendering video card. It acts as a sort of "AGP + driver" for the motherboard's chipset. + Loading this module into the kernel will allow the glx module to + program the GART (graphics aperture relocation table) registers + with appropriate values to transfer commands to the card. + + If you need more texture memory than you can get with the AGP GART + (theoretically up to 256 megs, but in practice usually 64 or 128 + megs due to kernel allocation issues), you could use PCI accesses + and have up to a couple gigs of texture space. + + Note that this is the only meas to have get XFree4/GLX use + write-combining with MTRR support on AGP bus. Without, OpenGL + direct rendering will be a lot slower but still faster than PIO. + + For the moment, most people should say no, unless you want to + test the GLX component which can be downloaded from + http://glx.on.openprojects.net/ + + or need to use the 810 Xserver in XFree 3.3.6 + +Intel 440LX/BX/GX support +CONFIG_AGP_INTEL + This option give you AGP support for the GLX component of the + "soon to be released" XFree86-4 on Intel 440LX/BX/GX chipsets. + + For the moment, most people should say no, unless you want to + test the GLX component which can be downloaded from + http://glx.on.openprojects.net/ + +Intel I810/I810 DC100/I810e support +CONFIG_AGP_I810 + This option give you AGP support for the Xserver for the intel + 810 chipset boards. This is required to do any useful video + modes. + +VIA VP3/MVP3/Apollo Pro support +CONFIG_AGP_VIA + This option give you AGP support for the GLX component of the + "soon to be released" XFree86-4 on VIA MPV3/Apollo Pro chipsets. + + For the moment, most people should say no, unless you want to + test the GLX component which can be downloaded from + http://glx.on.openprojects.net/ + +AMD Irongate support +CONFIG_AGP_AMD + This option give you AGP support for the GLX component of the + "soon to be released" XFree86-4 on Intel AMD Irongate chipset. + + For the moment, most people should say no, unless you want to + test the GLX component which can be downloaded from + http://glx.on.openprojects.net/ + +Generic SiS support +CONFIG_AGP_SIS + This option give you AGP support for the GLX component of the + "soon to be released" XFree86-4 on Silicon Integrated Systems [SiS] + chipsets. + + Note than 5591/5592 AGP chipsets are NOT supported. + + For the moment, most people should say no, unless you want to + test the GLX component which can be downloaded from + http://glx.on.openprojects.net/ + +ALI M1541 support +CONFIG_AGP_ALI + This option give you AGP support for the GLX component of the + "soon to be released" XFree86-4 on ALI M1541 chipset. + + For the moment, most people should say no, unless you want to + test the GLX component which can be downloaded from + http://glx.on.openprojects.net/ # # ARM options @@ -13584,7 +13699,6 @@ CONFIG_KHTTPD The kHTTPd is experimental. Be careful when using it on a production machine. Also note that kHTTPd doesn't support virtual servers yet. -# I2C support CONFIG_I2C I2C (pronounce: I-square-C) is a slow bus protocol developed by @@ -13637,6 +13751,7 @@ CONFIG_I2C_CHARDEV files, usually found in the /dev directory on your system. They make it possible to have user-space programs use the I2C bus. +# # A couple of things I keep forgetting: # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, # Intel, IRQ, Linux, MSDOS, NetWare, NetWinder, NFS, diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 75e1be547bd1..fcc962a11fd6 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -275,7 +275,7 @@ CONFIG_NET_EISA=y # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set # CONFIG_DE4X5 is not set -# CONFIG_DEC_ELCP is not set +# CONFIG_TULIP is not set # CONFIG_DGRS is not set CONFIG_EEXPRESS_PRO100=y # CONFIG_NE2K_PCI is not set diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 504a907af519..96be4dff61dc 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -40,14 +40,6 @@ else endif endif -ifdef CONFIG_ACPI -OX_OBJS += pm.o -else -ifdef CONFIG_APM -OX_OBJS += pm.o -endif -endif - ifeq ($(CONFIG_ACPI),y) O_OBJS += acpi.o else diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c index 8ff790de938e..590e01fd5d47 100644 --- a/arch/i386/kernel/pci-pc.c +++ b/arch/i386/kernel/pci-pc.c @@ -939,12 +939,26 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) } } +static void __init pci_fixup_ide_trash(struct pci_dev *d) +{ + int i; + + /* + * There exist PCI IDE controllers which have utter garbage + * in first four base registers. Ignore that. + */ + DBG("PCI: IDE base address trash cleared for %s\n", d->slot_name); + for(i=0; i<4; i++) + d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0; +} + struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_HE, pci_fixup_rcc }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_LE, pci_fixup_rcc }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_6010, pci_fixup_compaq }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash }, { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, { 0 } }; diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c index 1bd24a295c83..156eb187e32c 100644 --- a/arch/ppc/kernel/feature.c +++ b/arch/ppc/kernel/feature.c @@ -13,6 +13,7 @@ * responsibility of the caller). Added spinlocks. * */ +#include #include #include #include diff --git a/arch/ppc/kernel/galaxy_pci.c b/arch/ppc/kernel/galaxy_pci.c index cd33a10caf85..aeddd9a0e6b5 100644 --- a/arch/ppc/kernel/galaxy_pci.c +++ b/arch/ppc/kernel/galaxy_pci.c @@ -39,516 +39,6 @@ decl_config_access_method(galaxy); -void __init -galaxy_pcibios_fixup(void) -{ - -} - -void __init -galaxy_setup_pci_ptrs(void) -{ - set_config_access_method(galaxy); - - ppc_md.pcibios_fixup = galaxy_pcibios_fixup; -} - -int -galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - - return (PCIBIOS_SUCCESSFUL); -} -/* - * - * Copyright (c) 2000 Grant Erickson - * All rights reserved. - * - * Module name: galaxy_pci.c - * - * Description: - * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus - * interface. - * - * Why is this file called "galaxy_pci"? Because on the original - * IBM "Walnut" evaluation board schematic I have, the 405GP is - * is labeled "GALAXY". - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "pci.h" - - -/* Preprocessor Defines */ - -#define PCICFGADDR (volatile unsigned int *)(0xEEC00000) -#define PCICFGDATA (volatile unsigned int *)(0xEEC00004) - - -/* Function Prototypes */ - -decl_config_access_method(galaxy); - - -void __init -galaxy_pcibios_fixup(void) -{ - -} - -void __init -galaxy_setup_pci_ptrs(void) -{ - set_config_access_method(galaxy); - - ppc_md.pcibios_fixup = galaxy_pcibios_fixup; -} - -int -galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - - return (PCIBIOS_SUCCESSFUL); -} -/* - * - * Copyright (c) 2000 Grant Erickson - * All rights reserved. - * - * Module name: galaxy_pci.c - * - * Description: - * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus - * interface. - * - * Why is this file called "galaxy_pci"? Because on the original - * IBM "Walnut" evaluation board schematic I have, the 405GP is - * is labeled "GALAXY". - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "pci.h" - - -/* Preprocessor Defines */ - -#define PCICFGADDR (volatile unsigned int *)(0xEEC00000) -#define PCICFGDATA (volatile unsigned int *)(0xEEC00004) - - -/* Function Prototypes */ - -decl_config_access_method(galaxy); - - -void __init -galaxy_pcibios_fixup(void) -{ - -} - -void __init -galaxy_setup_pci_ptrs(void) -{ - set_config_access_method(galaxy); - - ppc_md.pcibios_fixup = galaxy_pcibios_fixup; -} - -int -galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - - return (PCIBIOS_SUCCESSFUL); -} -/* - * - * Copyright (c) 2000 Grant Erickson - * All rights reserved. - * - * Module name: galaxy_pci.c - * - * Description: - * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus - * interface. - * - * Why is this file called "galaxy_pci"? Because on the original - * IBM "Walnut" evaluation board schematic I have, the 405GP is - * is labeled "GALAXY". - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "pci.h" - - -/* Preprocessor Defines */ - -#define PCICFGADDR (volatile unsigned int *)(0xEEC00000) -#define PCICFGDATA (volatile unsigned int *)(0xEEC00004) - - -/* Function Prototypes */ - -decl_config_access_method(galaxy); - - -void __init -galaxy_pcibios_fixup(void) -{ - -} - -void __init -galaxy_setup_pci_ptrs(void) -{ - set_config_access_method(galaxy); - - ppc_md.pcibios_fixup = galaxy_pcibios_fixup; -} - -int -galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - - return (PCIBIOS_SUCCESSFUL); -} -/* - * - * Copyright (c) 2000 Grant Erickson - * All rights reserved. - * - * Module name: galaxy_pci.c - * - * Description: - * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus - * interface. - * - * Why is this file called "galaxy_pci"? Because on the original - * IBM "Walnut" evaluation board schematic I have, the 405GP is - * is labeled "GALAXY". - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "pci.h" - - -/* Preprocessor Defines */ - -#define PCICFGADDR (volatile unsigned int *)(0xEEC00000) -#define PCICFGDATA (volatile unsigned int *)(0xEEC00004) - - -/* Function Prototypes */ - -decl_config_access_method(galaxy); - - -void __init -galaxy_pcibios_fixup(void) -{ - -} - -void __init -galaxy_setup_pci_ptrs(void) -{ - set_config_access_method(galaxy); - - ppc_md.pcibios_fixup = galaxy_pcibios_fixup; -} - -int -galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - - return (PCIBIOS_SUCCESSFUL); -} - -int -galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - - return (PCIBIOS_SUCCESSFUL); -} -/* - * - * Copyright (c) 2000 Grant Erickson - * All rights reserved. - * - * Module name: galaxy_pci.c - * - * Description: - * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus - * interface. - * - * Why is this file called "galaxy_pci"? Because on the original - * IBM "Walnut" evaluation board schematic I have, the 405GP is - * is labeled "GALAXY". - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "pci.h" - - -/* Preprocessor Defines */ - -#define PCICFGADDR (volatile unsigned int *)(0xEEC00000) -#define PCICFGDATA (volatile unsigned int *)(0xEEC00004) - - -/* Function Prototypes */ - -decl_config_access_method(galaxy); - - void __init galaxy_pcibios_fixup(void) { diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c index 50046369bd91..d4dbe05e5cdf 100644 --- a/arch/ppc/kernel/open_pic.c +++ b/arch/ppc/kernel/open_pic.c @@ -8,6 +8,7 @@ * for more details. */ +#include #include #include #include diff --git a/arch/ppc/kernel/walnut_setup.c b/arch/ppc/kernel/walnut_setup.c index d01cb27fdbe4..284c732c1ec2 100644 --- a/arch/ppc/kernel/walnut_setup.c +++ b/arch/ppc/kernel/walnut_setup.c @@ -293,1183 +293,3 @@ walnut_calibrate_decr(void) mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); } -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: walnut_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "local_irq.h" -#include "ppc4xx_pic.h" -#include "time.h" -#include "walnut_setup.h" - - -/* Function Prototypes */ - -extern void abort(void); - -/* Global Variables */ - -unsigned char __res[sizeof(bd_t)]; - - -/* - * void __init walnut_init() - * - * Description: - * This routine... - * - * Input(s): - * r3 - Optional pointer to a board information structure. - * r4 - Optional pointer to the physical starting address of the init RAM - * disk. - * r5 - Optional pointer to the physical ending address of the init RAM - * disk. - * r6 - Optional pointer to the physical starting address of any kernel - * command-line parameters. - * r7 - Optional pointer to the physical ending address of any kernel - * command-line parameters. - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -walnut_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* - * If we were passed in a board information, copy it into the - * residual data area. - */ - if (r3) { - memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); - } - -#if defined(CONFIG_BLK_DEV_INITRD) - /* - * If the init RAM disk has been configured in, and there's a valid - * starting address for it, set it up. - */ - if (r4) { - initrd_start = r4 + KERNELBASE; - initrd_end = r5 + KERNELBASE; - } -#endif /* CONFIG_BLK_DEV_INITRD */ - - /* Copy the kernel command line arguments to a safe place. */ - - if (r6) { - *(char *)(r7 + KERNELBASE) = 0; - strcpy(cmd_line, (char *)(r6 + KERNELBASE)); - } - - /* Initialize machine-dependency vectors */ - - ppc_md.setup_arch = walnut_setup_arch; - ppc_md.setup_residual = walnut_setup_residual; - ppc_md.get_cpuinfo = NULL; - ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = walnut_init_IRQ; - ppc_md.get_irq = walnut_get_irq; - ppc_md.init = NULL; - - ppc_md.restart = walnut_restart; - ppc_md.power_off = walnut_power_off; - ppc_md.halt = walnut_halt; - - ppc_md.time_init = walnut_time_init; - ppc_md.set_rtc_time = walnut_set_rtc_time; - ppc_md.get_rtc_time = walnut_get_rtc_time; - ppc_md.calibrate_decr = walnut_calibrate_decr; - - ppc_md.kbd_setkeycode = NULL; - ppc_md.kbd_getkeycode = NULL; - ppc_md.kbd_translate = NULL; - ppc_md.kbd_unexpected_up = NULL; - ppc_md.kbd_leds = NULL; - ppc_md.kbd_init_hw = NULL; - -#if defined(CONFIG_MAGIC_SYSRQ) - ppc_md.ppc_kbd_sysrq_xlate = NULL; -#endif - - return; -} - -/* - * Document me. - */ -void __init -walnut_setup_arch(void) -{ - /* XXX - Implement me */ -} - -/* - * int walnut_setup_residual() - * - * Description: - * This routine pretty-prints the platform's internal CPU and bus clock - * frequencies into the buffer for usage in /proc/cpuinfo. - * - * Input(s): - * *buffer - Buffer into which CPU and bus clock frequencies are to be - * printed. - * - * Output(s): - * *buffer - Buffer with the CPU and bus clock frequencies. - * - * Returns: - * The number of bytes copied into 'buffer' if OK, otherwise zero or less - * on error. - */ -int -walnut_setup_residual(char *buffer) -{ - int len = 0; - bd_t *bp = (bd_t *)__res; - - len += sprintf(len + buffer, - "clock\t\t: %dMHz\n" - "bus clock\t\t: %dMHz\n", - bp->bi_intfreq / 1000000, - bp->bi_busfreq / 1000000); - - return (len); -} - -/* - * Document me. - */ -void __init -walnut_init_IRQ(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].handler = ppc4xx_pic; - } - - return; -} - -/* - * Document me. - */ -int -walnut_get_irq(struct pt_regs *regs) -{ - return (ppc4xx_pic_get_irq(regs)); -} - -/* - * Document me. - */ -void -walnut_restart(char *cmd) -{ - abort(); -} - -/* - * Document me. - */ -void -walnut_power_off(void) -{ - walnut_restart(NULL); -} - -/* - * Document me. - */ -void -walnut_halt(void) -{ - walnut_restart(NULL); -} - -/* - * Document me. - */ -void __init -walnut_time_init(void) -{ - /* XXX - Implement me */ -} - -/* - * Document me. - */ -int __init -walnut_set_rtc_time(unsigned long time) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * Document me. - */ -unsigned long __init -walnut_get_rtc_time(void) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * void __init walnut_calibrate_decr() - * - * Description: - * This routine retrieves the internal processor frequency from the board - * information structure, sets up the kernel timer decrementer based on - * that value, enables the 403 programmable interval timer (PIT) and sets - * it up for auto-reload. - * - * Input(s): - * N/A - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -walnut_calibrate_decr(void) -{ - unsigned int freq; - bd_t *bip = (bd_t *)__res; - - freq = bip->bi_intfreq; - - decrementer_count = freq / HZ; - count_period_num = 1; - count_period_den = freq; - - /* Enable the PIT and set auto-reload of its value */ - - mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); - - /* Clear any pending timer interrupts */ - - mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); -} -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: walnut_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "local_irq.h" -#include "ppc4xx_pic.h" -#include "time.h" -#include "walnut_setup.h" - - -/* Function Prototypes */ - -extern void abort(void); - -/* Global Variables */ - -unsigned char __res[sizeof(bd_t)]; - - -/* - * void __init walnut_init() - * - * Description: - * This routine... - * - * Input(s): - * r3 - Optional pointer to a board information structure. - * r4 - Optional pointer to the physical starting address of the init RAM - * disk. - * r5 - Optional pointer to the physical ending address of the init RAM - * disk. - * r6 - Optional pointer to the physical starting address of any kernel - * command-line parameters. - * r7 - Optional pointer to the physical ending address of any kernel - * command-line parameters. - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -walnut_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* - * If we were passed in a board information, copy it into the - * residual data area. - */ - if (r3) { - memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); - } - -#if defined(CONFIG_BLK_DEV_INITRD) - /* - * If the init RAM disk has been configured in, and there's a valid - * starting address for it, set it up. - */ - if (r4) { - initrd_start = r4 + KERNELBASE; - initrd_end = r5 + KERNELBASE; - } -#endif /* CONFIG_BLK_DEV_INITRD */ - - /* Copy the kernel command line arguments to a safe place. */ - - if (r6) { - *(char *)(r7 + KERNELBASE) = 0; - strcpy(cmd_line, (char *)(r6 + KERNELBASE)); - } - - /* Initialize machine-dependency vectors */ - - ppc_md.setup_arch = walnut_setup_arch; - ppc_md.setup_residual = walnut_setup_residual; - ppc_md.get_cpuinfo = NULL; - ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = walnut_init_IRQ; - ppc_md.get_irq = walnut_get_irq; - ppc_md.init = NULL; - - ppc_md.restart = walnut_restart; - ppc_md.power_off = walnut_power_off; - ppc_md.halt = walnut_halt; - - ppc_md.time_init = walnut_time_init; - ppc_md.set_rtc_time = walnut_set_rtc_time; - ppc_md.get_rtc_time = walnut_get_rtc_time; - ppc_md.calibrate_decr = walnut_calibrate_decr; - - ppc_md.kbd_setkeycode = NULL; - ppc_md.kbd_getkeycode = NULL; - ppc_md.kbd_translate = NULL; - ppc_md.kbd_unexpected_up = NULL; - ppc_md.kbd_leds = NULL; - ppc_md.kbd_init_hw = NULL; - -#if defined(CONFIG_MAGIC_SYSRQ) - ppc_md.ppc_kbd_sysrq_xlate = NULL; -#endif - - return; -} - -/* - * Document me. - */ -void __init -walnut_setup_arch(void) -{ - /* XXX - Implement me */ -} - -/* - * int walnut_setup_residual() - * - * Description: - * This routine pretty-prints the platform's internal CPU and bus clock - * frequencies into the buffer for usage in /proc/cpuinfo. - * - * Input(s): - * *buffer - Buffer into which CPU and bus clock frequencies are to be - * printed. - * - * Output(s): - * *buffer - Buffer with the CPU and bus clock frequencies. - * - * Returns: - * The number of bytes copied into 'buffer' if OK, otherwise zero or less - * on error. - */ -int -walnut_setup_residual(char *buffer) -{ - int len = 0; - bd_t *bp = (bd_t *)__res; - - len += sprintf(len + buffer, - "clock\t\t: %dMHz\n" - "bus clock\t\t: %dMHz\n", - bp->bi_intfreq / 1000000, - bp->bi_busfreq / 1000000); - - return (len); -} - -/* - * Document me. - */ -void __init -walnut_init_IRQ(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].handler = ppc4xx_pic; - } - - return; -} - -/* - * Document me. - */ -int -walnut_get_irq(struct pt_regs *regs) -{ - return (ppc4xx_pic_get_irq(regs)); -} - -/* - * Document me. - */ -void -walnut_restart(char *cmd) -{ - abort(); -} - -/* - * Document me. - */ -void -walnut_power_off(void) -{ - walnut_restart(NULL); -} - -/* - * Document me. - */ -void -walnut_halt(void) -{ - walnut_restart(NULL); -} - -/* - * Document me. - */ -void __init -walnut_time_init(void) -{ - /* XXX - Implement me */ -} - -/* - * Document me. - */ -int __init -walnut_set_rtc_time(unsigned long time) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * Document me. - */ -unsigned long __init -walnut_get_rtc_time(void) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * void __init walnut_calibrate_decr() - * - * Description: - * This routine retrieves the internal processor frequency from the board - * information structure, sets up the kernel timer decrementer based on - * that value, enables the 403 programmable interval timer (PIT) and sets - * it up for auto-reload. - * - * Input(s): - * N/A - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -walnut_calibrate_decr(void) -{ - unsigned int freq; - bd_t *bip = (bd_t *)__res; - - freq = bip->bi_intfreq; - - decrementer_count = freq / HZ; - count_period_num = 1; - count_period_den = freq; - - /* Enable the PIT and set auto-reload of its value */ - - mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); - - /* Clear any pending timer interrupts */ - - mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); -} -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: walnut_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "local_irq.h" -#include "ppc4xx_pic.h" -#include "time.h" -#include "walnut_setup.h" - - -/* Function Prototypes */ - -extern void abort(void); - -/* Global Variables */ - -unsigned char __res[sizeof(bd_t)]; - - -/* - * void __init walnut_init() - * - * Description: - * This routine... - * - * Input(s): - * r3 - Optional pointer to a board information structure. - * r4 - Optional pointer to the physical starting address of the init RAM - * disk. - * r5 - Optional pointer to the physical ending address of the init RAM - * disk. - * r6 - Optional pointer to the physical starting address of any kernel - * command-line parameters. - * r7 - Optional pointer to the physical ending address of any kernel - * command-line parameters. - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -walnut_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* - * If we were passed in a board information, copy it into the - * residual data area. - */ - if (r3) { - memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); - } - -#if defined(CONFIG_BLK_DEV_INITRD) - /* - * If the init RAM disk has been configured in, and there's a valid - * starting address for it, set it up. - */ - if (r4) { - initrd_start = r4 + KERNELBASE; - initrd_end = r5 + KERNELBASE; - } -#endif /* CONFIG_BLK_DEV_INITRD */ - - /* Copy the kernel command line arguments to a safe place. */ - - if (r6) { - *(char *)(r7 + KERNELBASE) = 0; - strcpy(cmd_line, (char *)(r6 + KERNELBASE)); - } - - /* Initialize machine-dependency vectors */ - - ppc_md.setup_arch = walnut_setup_arch; - ppc_md.setup_residual = walnut_setup_residual; - ppc_md.get_cpuinfo = NULL; - ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = walnut_init_IRQ; - ppc_md.get_irq = walnut_get_irq; - ppc_md.init = NULL; - - ppc_md.restart = walnut_restart; - ppc_md.power_off = walnut_power_off; - ppc_md.halt = walnut_halt; - - ppc_md.time_init = walnut_time_init; - ppc_md.set_rtc_time = walnut_set_rtc_time; - ppc_md.get_rtc_time = walnut_get_rtc_time; - ppc_md.calibrate_decr = walnut_calibrate_decr; - - ppc_md.kbd_setkeycode = NULL; - ppc_md.kbd_getkeycode = NULL; - ppc_md.kbd_translate = NULL; - ppc_md.kbd_unexpected_up = NULL; - ppc_md.kbd_leds = NULL; - ppc_md.kbd_init_hw = NULL; - -#if defined(CONFIG_MAGIC_SYSRQ) - ppc_md.ppc_kbd_sysrq_xlate = NULL; -#endif - - return; -} - -/* - * Document me. - */ -void __init -walnut_setup_arch(void) -{ - /* XXX - Implement me */ -} - -/* - * int walnut_setup_residual() - * - * Description: - * This routine pretty-prints the platform's internal CPU and bus clock - * frequencies into the buffer for usage in /proc/cpuinfo. - * - * Input(s): - * *buffer - Buffer into which CPU and bus clock frequencies are to be - * printed. - * - * Output(s): - * *buffer - Buffer with the CPU and bus clock frequencies. - * - * Returns: - * The number of bytes copied into 'buffer' if OK, otherwise zero or less - * on error. - */ -int -walnut_setup_residual(char *buffer) -{ - int len = 0; - bd_t *bp = (bd_t *)__res; - - len += sprintf(len + buffer, - "clock\t\t: %dMHz\n" - "bus clock\t\t: %dMHz\n", - bp->bi_intfreq / 1000000, - bp->bi_busfreq / 1000000); - - return (len); -} - -/* - * Document me. - */ -void __init -walnut_init_IRQ(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].handler = ppc4xx_pic; - } - - return; -} - -/* - * Document me. - */ -int -walnut_get_irq(struct pt_regs *regs) -{ - return (ppc4xx_pic_get_irq(regs)); -} - -/* - * Document me. - */ -void -walnut_restart(char *cmd) -{ - abort(); -} - -/* - * Document me. - */ -void -walnut_power_off(void) -{ - walnut_restart(NULL); -} - -/* - * Document me. - */ -void -walnut_halt(void) -{ - walnut_restart(NULL); -} - -/* - * Document me. - */ -void __init -walnut_time_init(void) -{ - /* XXX - Implement me */ -} - -/* - * Document me. - */ -int __init -walnut_set_rtc_time(unsigned long time) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * Document me. - */ -unsigned long __init -walnut_get_rtc_time(void) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * void __init walnut_calibrate_decr() - * - * Description: - * This routine retrieves the internal processor frequency from the board - * information structure, sets up the kernel timer decrementer based on - * that value, enables the 403 programmable interval timer (PIT) and sets - * it up for auto-reload. - * - * Input(s): - * N/A - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -walnut_calibrate_decr(void) -{ - unsigned int freq; - bd_t *bip = (bd_t *)__res; - - freq = bip->bi_intfreq; - - decrementer_count = freq / HZ; - count_period_num = 1; - count_period_den = freq; - - /* Enable the PIT and set auto-reload of its value */ - - mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); - - /* Clear any pending timer interrupts */ - - mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); -} -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: walnut_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "local_irq.h" -#include "ppc4xx_pic.h" -#include "time.h" -#include "walnut_setup.h" - - -/* Function Prototypes */ - -extern void abort(void); - -/* Global Variables */ - -unsigned char __res[sizeof(bd_t)]; - - -/* - * void __init walnut_init() - * - * Description: - * This routine... - * - * Input(s): - * r3 - Optional pointer to a board information structure. - * r4 - Optional pointer to the physical starting address of the init RAM - * disk. - * r5 - Optional pointer to the physical ending address of the init RAM - * disk. - * r6 - Optional pointer to the physical starting address of any kernel - * command-line parameters. - * r7 - Optional pointer to the physical ending address of any kernel - * command-line parameters. - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -walnut_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* - * If we were passed in a board information, copy it into the - * residual data area. - */ - if (r3) { - memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); - } - -#if defined(CONFIG_BLK_DEV_INITRD) - /* - * If the init RAM disk has been configured in, and there's a valid - * starting address for it, set it up. - */ - if (r4) { - initrd_start = r4 + KERNELBASE; - initrd_end = r5 + KERNELBASE; - } -#endif /* CONFIG_BLK_DEV_INITRD */ - - /* Copy the kernel command line arguments to a safe place. */ - - if (r6) { - *(char *)(r7 + KERNELBASE) = 0; - strcpy(cmd_line, (char *)(r6 + KERNELBASE)); - } - - /* Initialize machine-dependency vectors */ - - ppc_md.setup_arch = walnut_setup_arch; - ppc_md.setup_residual = walnut_setup_residual; - ppc_md.get_cpuinfo = NULL; - ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = walnut_init_IRQ; - ppc_md.get_irq = walnut_get_irq; - ppc_md.init = NULL; - - ppc_md.restart = walnut_restart; - ppc_md.power_off = walnut_power_off; - ppc_md.halt = walnut_halt; - - ppc_md.time_init = walnut_time_init; - ppc_md.set_rtc_time = walnut_set_rtc_time; - ppc_md.get_rtc_time = walnut_get_rtc_time; - ppc_md.calibrate_decr = walnut_calibrate_decr; - - ppc_md.kbd_setkeycode = NULL; - ppc_md.kbd_getkeycode = NULL; - ppc_md.kbd_translate = NULL; - ppc_md.kbd_unexpected_up = NULL; - ppc_md.kbd_leds = NULL; - ppc_md.kbd_init_hw = NULL; - -#if defined(CONFIG_MAGIC_SYSRQ) - ppc_md.ppc_kbd_sysrq_xlate = NULL; -#endif - - return; -} - -/* - * Document me. - */ -void __init -walnut_setup_arch(void) -{ - /* XXX - Implement me */ -} - -/* - * int walnut_setup_residual() - * - * Description: - * This routine pretty-prints the platform's internal CPU and bus clock - * frequencies into the buffer for usage in /proc/cpuinfo. - * - * Input(s): - * *buffer - Buffer into which CPU and bus clock frequencies are to be - * printed. - * - * Output(s): - * *buffer - Buffer with the CPU and bus clock frequencies. - * - * Returns: - * The number of bytes copied into 'buffer' if OK, otherwise zero or less - * on error. - */ -int -walnut_setup_residual(char *buffer) -{ - int len = 0; - bd_t *bp = (bd_t *)__res; - - len += sprintf(len + buffer, - "clock\t\t: %dMHz\n" - "bus clock\t\t: %dMHz\n", - bp->bi_intfreq / 1000000, - bp->bi_busfreq / 1000000); - - return (len); -} - -/* - * Document me. - */ -void __init -walnut_init_IRQ(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].handler = ppc4xx_pic; - } - - return; -} - -/* - * Document me. - */ -int -walnut_get_irq(struct pt_regs *regs) -{ - return (ppc4xx_pic_get_irq(regs)); -} - -/* - * Document me. - */ -void -walnut_restart(char *cmd) -{ - abort(); -} - -/* - * Document me. - */ -void -walnut_power_off(void) -{ - walnut_restart(NULL); -} - -/* - * Document me. - */ -void -walnut_halt(void) -{ - walnut_restart(NULL); -} - -/* - * Document me. - */ -void __init -walnut_time_init(void) -{ - /* XXX - Implement me */ -} - -/* - * Document me. - */ -int __init -walnut_set_rtc_time(unsigned long time) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * Document me. - */ -unsigned long __init -walnut_get_rtc_time(void) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * void __init walnut_calibrate_decr() - * - * Description: - * This routine retrieves the internal processor frequency from the board - * information structure, sets up the kernel timer decrementer based on - * that value, enables the 403 programmable interval timer (PIT) and sets - * it up for auto-reload. - * - * Input(s): - * N/A - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -walnut_calibrate_decr(void) -{ - unsigned int freq; - bd_t *bip = (bd_t *)__res; - - freq = bip->bi_intfreq; - - decrementer_count = freq / HZ; - count_period_num = 1; - count_period_den = freq; - - /* Enable the PIT and set auto-reload of its value */ - - mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); - - /* Clear any pending timer interrupts */ - - mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); -} diff --git a/arch/ppc/kernel/walnut_setup.h b/arch/ppc/kernel/walnut_setup.h index f11755c6d8b7..a6e905333cd7 100644 --- a/arch/ppc/kernel/walnut_setup.h +++ b/arch/ppc/kernel/walnut_setup.h @@ -43,206 +43,6 @@ extern unsigned long walnut_get_rtc_time(void); extern void walnut_calibrate_decr(void); -#ifdef __cplusplus -} -#endif - -#endif /* __WALNUT_SETUP_H__ */ -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: walnut_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#ifndef __WALNUT_SETUP_H__ -#define __WALNUT_SETUP_H__ - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -extern unsigned char __res[sizeof(bd_t)]; - -extern void walnut_init(unsigned long r3, - unsigned long ird_start, - unsigned long ird_end, - unsigned long cline_start, - unsigned long cline_end); -extern void walnut_setup_arch(void); -extern int walnut_setup_residual(char *buffer); -extern void walnut_init_IRQ(void); -extern int walnut_get_irq(struct pt_regs *regs); -extern void walnut_restart(char *cmd); -extern void walnut_power_off(void); -extern void walnut_halt(void); -extern void walnut_time_init(void); -extern int walnut_set_rtc_time(unsigned long now); -extern unsigned long walnut_get_rtc_time(void); -extern void walnut_calibrate_decr(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* __WALNUT_SETUP_H__ */ -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: walnut_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#ifndef __WALNUT_SETUP_H__ -#define __WALNUT_SETUP_H__ - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -extern unsigned char __res[sizeof(bd_t)]; - -extern void walnut_init(unsigned long r3, - unsigned long ird_start, - unsigned long ird_end, - unsigned long cline_start, - unsigned long cline_end); -extern void walnut_setup_arch(void); -extern int walnut_setup_residual(char *buffer); -extern void walnut_init_IRQ(void); -extern int walnut_get_irq(struct pt_regs *regs); -extern void walnut_restart(char *cmd); -extern void walnut_power_off(void); -extern void walnut_halt(void); -extern void walnut_time_init(void); -extern int walnut_set_rtc_time(unsigned long now); -extern unsigned long walnut_get_rtc_time(void); -extern void walnut_calibrate_decr(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* __WALNUT_SETUP_H__ */ -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: walnut_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#ifndef __WALNUT_SETUP_H__ -#define __WALNUT_SETUP_H__ - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -extern unsigned char __res[sizeof(bd_t)]; - -extern void walnut_init(unsigned long r3, - unsigned long ird_start, - unsigned long ird_end, - unsigned long cline_start, - unsigned long cline_end); -extern void walnut_setup_arch(void); -extern int walnut_setup_residual(char *buffer); -extern void walnut_init_IRQ(void); -extern int walnut_get_irq(struct pt_regs *regs); -extern void walnut_restart(char *cmd); -extern void walnut_power_off(void); -extern void walnut_halt(void); -extern void walnut_time_init(void); -extern int walnut_set_rtc_time(unsigned long now); -extern unsigned long walnut_get_rtc_time(void); -extern void walnut_calibrate_decr(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* __WALNUT_SETUP_H__ */ -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: walnut_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#ifndef __WALNUT_SETUP_H__ -#define __WALNUT_SETUP_H__ - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -extern unsigned char __res[sizeof(bd_t)]; - -extern void walnut_init(unsigned long r3, - unsigned long ird_start, - unsigned long ird_end, - unsigned long cline_start, - unsigned long cline_end); -extern void walnut_setup_arch(void); -extern int walnut_setup_residual(char *buffer); -extern void walnut_init_IRQ(void); -extern int walnut_get_irq(struct pt_regs *regs); -extern void walnut_restart(char *cmd); -extern void walnut_power_off(void); -extern void walnut_halt(void); -extern void walnut_time_init(void); -extern int walnut_set_rtc_time(unsigned long now); -extern unsigned long walnut_get_rtc_time(void); -extern void walnut_calibrate_decr(void); - - #ifdef __cplusplus } #endif diff --git a/arch/sparc/config.in b/arch/sparc/config.in index 86de319e6053..ebaa64806ca7 100644 --- a/arch/sparc/config.in +++ b/arch/sparc/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.85 2000/02/08 08:57:45 jj Exp $ +# $Id: config.in,v 1.86 2000/02/10 02:51:10 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -118,11 +118,24 @@ if [ "$CONFIG_SCSI" != "n" ]; then comment 'SCSI support type (disk, tape, CDrom)' dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI + + if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then + int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40 + fi + dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI + + if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then + int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2 + fi + dep_tristate ' SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI + if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR + int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2 fi + dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' @@ -130,6 +143,7 @@ if [ "$CONFIG_SCSI" != "n" ]; then bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS + bool ' SCSI logging facility' CONFIG_SCSI_LOGGING mainmenu_option next_comment comment 'SCSI low-level drivers' diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index 533ce12ebc11..6db0425638f4 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig @@ -175,9 +175,12 @@ CONFIG_SCSI=y # SCSI support type (disk, tape, CDrom) # CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y +CONFIG_ST_EXTRA_DEVS=2 CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=m # @@ -185,6 +188,7 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set # # SCSI low-level drivers diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index 67aacdb50afe..6aebbfcc848f 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.94 2000/02/08 08:57:50 jj Exp $ +# $Id: config.in,v 1.95 2000/02/10 02:51:12 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -130,11 +130,24 @@ if [ "$CONFIG_SCSI" != "n" ]; then comment 'SCSI support type (disk, tape, CDrom)' dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI + + if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then + int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40 + fi + dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI + + if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then + int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2 + fi + dep_tristate ' SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI + if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR + int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2 fi + dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' @@ -142,6 +155,7 @@ if [ "$CONFIG_SCSI" != "n" ]; then bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS + bool ' SCSI logging facility' CONFIG_SCSI_LOGGING mainmenu_option next_comment comment 'SCSI low-level drivers' diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 6007da94fd64..747ded255906 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -199,9 +199,12 @@ CONFIG_SCSI=y # SCSI support type (disk, tape, CDrom) # CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y +CONFIG_ST_EXTRA_DEVS=2 CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=m # @@ -209,6 +212,7 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set # # SCSI low-level drivers diff --git a/drivers/block/hpt366.c b/drivers/block/hpt366.c index 91ef9d0b4fbc..7328ea7b85c2 100644 --- a/drivers/block/hpt366.c +++ b/drivers/block/hpt366.c @@ -10,6 +10,7 @@ * development and support. */ +#include #include #include #include diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e5a65e1598cd..587156935548 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -386,7 +386,11 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg) a file structure */ lo->lo_backing_file = NULL; } else if (S_ISREG(inode->i_mode)) { - if (!inode->i_op->get_block) { + /* + * Total crap. We should just use pagecache instead of trying + * to redirect on block level. + */ + if (!inode->i_mapping->a_ops->bmap) { printk(KERN_ERR "loop: device has no block access/not implemented\n"); goto out_putf; } diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 538aa5fd4e6c..ca7f76aa3d51 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -112,26 +112,6 @@ struct agp_bridge_data { int (*remove_memory) (agp_memory *, off_t, int); agp_memory *(*alloc_by_type) (size_t, int); void (*free_by_type) (agp_memory *); - - /* Links to vendor/device specific setup functions */ -#ifdef CONFIG_AGP_INTEL - void (*intel_generic_setup) (void); -#endif -#ifdef CONFIG_AGP_I810 - void (*intel_i810_setup) (struct pci_dev *); -#endif -#ifdef CONFIG_AGP_VIA - void (*via_generic_setup) (void); -#endif -#ifdef CONFIG_AGP_SIS - void (*sis_generic_setup) (void); -#endif -#ifdef CONFIG_AGP_AMD - void (*amd_irongate_setup) (void); -#endif -#ifdef CONFIG_AGP_ALI - void (*ali_generic_setup) (void); -#endif }; #define OUTREG32(mmap, addr, val) __raw_writel((val), (mmap)+(addr)) @@ -157,6 +137,11 @@ struct agp_bridge_data { #define min(a,b) (((a)<(b))?(a):(b)) #endif +#define arraysize(x) (sizeof(x)/sizeof(*(x))) + +#define AGPGART_MODULE_NAME "agpgart" +#define PFX AGPGART_MODULE_NAME ": " + #define PGE_EMPTY(p) (!(p) || (p) == (unsigned long) agp_bridge.scratch_page) #ifndef PCI_DEVICE_ID_VIA_82C691_0 diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c index a83928a023d2..a21556a2bcd1 100644 --- a/drivers/char/agp/agpgart_be.c +++ b/drivers/char/agp/agpgart_be.c @@ -96,7 +96,7 @@ static void smp_flush_cache(void) { atomic_set(&cpus_waiting, smp_num_cpus - 1); if (smp_call_function(ipi_handler, NULL, 1, 0) != 0) - panic("agpgart: timed out waiting for the other CPUs!\n"); + panic(PFX "timed out waiting for the other CPUs!\n"); flush_cache(); while (atomic_read(&cpus_waiting) > 0) barrier(); @@ -811,7 +811,7 @@ static int intel_i810_fetch_size(void) values = A_SIZE_FIX(agp_bridge.aperture_sizes); if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { - printk("agpgart: i810 is disabled\n"); + printk(KERN_WARNING PFX "i810 is disabled\n"); return 0; } if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { @@ -846,8 +846,7 @@ static int intel_i810_configure(void) if ((INREG32(intel_i810_private.registers, I810_DRAM_CTL) & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { /* This will need to be dynamically assigned */ - printk(KERN_INFO - "agpgart: detected 4MB dedicated video ram.\n"); + printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n"); intel_i810_private.num_dcache_entries = 1024; } pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp); @@ -1024,7 +1023,7 @@ static unsigned long intel_i810_mask_memory(unsigned long addr, int type) return addr | agp_bridge.masks[type].mask; } -static void intel_i810_setup(struct pci_dev *i810_dev) +static int __init intel_i810_setup(struct pci_dev *i810_dev) { intel_i810_private.i810_dev = i810_dev; @@ -1048,9 +1047,11 @@ static void intel_i810_setup(struct pci_dev *i810_dev) agp_bridge.remove_memory = intel_i810_remove_entries; agp_bridge.alloc_by_type = intel_i810_alloc_by_type; agp_bridge.free_by_type = intel_i810_free_by_type; + + return 0; } -#endif +#endif /* CONFIG_AGP_I810 */ #ifdef CONFIG_AGP_INTEL @@ -1150,7 +1151,7 @@ static aper_size_info_16 intel_generic_sizes[7] = {4, 1024, 0, 63} }; -static void intel_generic_setup(void) +static int __init intel_generic_setup (struct pci_dev *pdev) { agp_bridge.masks = intel_generic_masks; agp_bridge.num_of_masks = 1; @@ -1172,9 +1173,13 @@ static void intel_generic_setup(void) agp_bridge.remove_memory = agp_generic_remove_memory; agp_bridge.alloc_by_type = agp_generic_alloc_by_type; agp_bridge.free_by_type = agp_generic_free_by_type; + + return 0; + + (void) pdev; /* unused */ } -#endif +#endif /* CONFIG_AGP_INTEL */ #ifdef CONFIG_AGP_VIA @@ -1259,7 +1264,7 @@ static gatt_mask via_generic_masks[] = {0x00000000, 0} }; -static void via_generic_setup(void) +static int __init via_generic_setup (struct pci_dev *pdev) { agp_bridge.masks = via_generic_masks; agp_bridge.num_of_masks = 1; @@ -1281,9 +1286,13 @@ static void via_generic_setup(void) agp_bridge.remove_memory = agp_generic_remove_memory; agp_bridge.alloc_by_type = agp_generic_alloc_by_type; agp_bridge.free_by_type = agp_generic_free_by_type; + + return 0; + + (void) pdev; /* unused */ } -#endif +#endif /* CONFIG_AGP_VIA */ #ifdef CONFIG_AGP_SIS @@ -1364,7 +1373,7 @@ static gatt_mask sis_generic_masks[] = {0x00000000, 0} }; -static void sis_generic_setup(void) +static int __init sis_generic_setup (struct pci_dev *pdev) { agp_bridge.masks = sis_generic_masks; agp_bridge.num_of_masks = 1; @@ -1386,9 +1395,13 @@ static void sis_generic_setup(void) agp_bridge.remove_memory = agp_generic_remove_memory; agp_bridge.alloc_by_type = agp_generic_alloc_by_type; agp_bridge.free_by_type = agp_generic_free_by_type; + + return 0; + + (void) pdev; /* unused */ } -#endif +#endif /* CONFIG_AGP_SIS */ #ifdef CONFIG_AGP_AMD @@ -1523,7 +1536,7 @@ static gatt_mask amd_irongate_masks[] = {0x00000001, 0} }; -static void amd_irongate_setup(void) +static int __init amd_irongate_setup (struct pci_dev *pdev) { agp_bridge.masks = amd_irongate_masks; agp_bridge.num_of_masks = 1; @@ -1545,9 +1558,13 @@ static void amd_irongate_setup(void) agp_bridge.remove_memory = agp_generic_remove_memory; agp_bridge.alloc_by_type = agp_generic_alloc_by_type; agp_bridge.free_by_type = agp_generic_free_by_type; + + return 0; + + (void) pdev; /* unused */ } -#endif +#endif /* CONFIG_AGP_AMD */ #ifdef CONFIG_AGP_ALI @@ -1645,7 +1662,7 @@ static aper_size_info_32 ali_generic_sizes[7] = {4, 1024, 0, 3} }; -static void ali_generic_setup(void) +static int __init ali_generic_setup (struct pci_dev *pdev) { agp_bridge.masks = ali_generic_masks; agp_bridge.num_of_masks = 1; @@ -1667,24 +1684,188 @@ static void ali_generic_setup(void) agp_bridge.remove_memory = agp_generic_remove_memory; agp_bridge.alloc_by_type = agp_generic_alloc_by_type; agp_bridge.free_by_type = agp_generic_free_by_type; + + return 0; + + (void) pdev; /* unused */ } -#endif +#endif /* CONFIG_AGP_ALI */ + + +/* per-chipset initialization data. + * note -- all chipsets for a single vendor MUST be grouped together + */ +static struct { + unsigned short device_id; /* first, to make table easier to read */ + unsigned short vendor_id; + enum chipset_type chipset; + const char *vendor_name; + const char *chipset_name; + int (*chipset_setup) (struct pci_dev *pdev); +} agp_bridge_info[] __initdata = { + +#ifdef CONFIG_AGP_ALI + { PCI_DEVICE_ID_AL_M1541_0, + PCI_VENDOR_ID_AL, + ALI_M1541, + "Ali", + "M1541", + ali_generic_setup }, + { 0, + PCI_VENDOR_ID_AL, + ALI_GENERIC, + "Ali", + "Generic", + ali_generic_setup }, +#endif /* CONFIG_AGP_ALI */ + +#ifdef CONFIG_AGP_AMD + { PCI_DEVICE_ID_AMD_IRONGATE_0, + PCI_VENDOR_ID_AMD, + AMD_IRONGATE, + "AMD", + "Irongate", + amd_irongate_setup }, + { 0, + PCI_VENDOR_ID_AMD, + AMD_GENERIC, + "AMD", + "Generic", + amd_irongate_setup }, +#endif /* CONFIG_AGP_AMD */ + +#ifdef CONFIG_AGP_INTEL + { PCI_DEVICE_ID_INTEL_82443LX_0, + PCI_VENDOR_ID_INTEL, + INTEL_LX, + "Intel", + "440LX", + intel_generic_setup }, + { PCI_DEVICE_ID_INTEL_82443BX_0, + PCI_VENDOR_ID_INTEL, + INTEL_BX, + "Intel", + "440BX", + intel_generic_setup }, + { PCI_DEVICE_ID_INTEL_82443GX_0, + PCI_VENDOR_ID_INTEL, + INTEL_GX, + "Intel", + "440GX", + intel_generic_setup }, + { 0, + PCI_VENDOR_ID_INTEL, + INTEL_GENERIC, + "Intel", + "Generic", + intel_generic_setup }, +#endif /* CONFIG_AGP_INTEL */ + +#ifdef CONFIG_AGP_SIS + { 0, + PCI_VENDOR_ID_SI, + SIS_GENERIC, + "SiS", + "Generic", + sis_generic_setup }, +#endif /* CONFIG_AGP_SIS */ + +#ifdef CONFIG_AGP_VIA + { PCI_DEVICE_ID_VIA_8501_0, + PCI_VENDOR_ID_VIA, + VIA_MVP4, + "Via", + "MVP4", + via_generic_setup }, + { PCI_DEVICE_ID_VIA_82C597_0, + PCI_VENDOR_ID_VIA, + VIA_VP3, + "Via", + "VP3", + via_generic_setup }, + { PCI_DEVICE_ID_VIA_82C598_0, + PCI_VENDOR_ID_VIA, + VIA_MVP3, + "Via", + "MVP3", + via_generic_setup }, + { PCI_DEVICE_ID_VIA_82C691_0, + PCI_VENDOR_ID_VIA, + VIA_APOLLO_PRO, + "Via", + "Apollo Pro", + via_generic_setup }, + { 0, + PCI_VENDOR_ID_VIA, + VIA_GENERIC, + "Via", + "Generic", + via_generic_setup }, +#endif /* CONFIG_AGP_VIA */ + + { 0, }, /* dummy final entry, always present */ +}; + + +/* scan table above for supported devices */ +static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +{ + int i; + + for (i = 0; i < arraysize (agp_bridge_info); i++) + if (pdev->vendor == agp_bridge_info[i].vendor_id) + break; + + if (i >= arraysize (agp_bridge_info)) { + printk (KERN_DEBUG PFX "unsupported bridge\n"); + return -ENODEV; + } + + while ((i < arraysize (agp_bridge_info)) && + (agp_bridge_info[i].vendor_id == pdev->vendor)) { + if (pdev->device == agp_bridge_info[i].device_id) { + printk (KERN_INFO PFX "Detected %s %s chipset\n", + agp_bridge_info[i].vendor_name, + agp_bridge_info[i].chipset_name); + agp_bridge.type = agp_bridge_info[i].chipset; + return agp_bridge_info[i].chipset_setup (pdev); + } + + i++; + } + + i--; /* point to vendor generic entry (device_id == 0) */ + + /* try init anyway, if user requests it AND + * there is a 'generic' bridge entry for this vendor */ + if (agp_try_unsupported && agp_bridge_info[i].device_id == 0) { + printk(KERN_WARNING PFX "Trying generic %s routines" + " for device id: %x\n", + agp_bridge_info[i].vendor_name, pdev->device); + agp_bridge.type = agp_bridge_info[i].chipset; + return agp_bridge_info[i].chipset_setup (pdev); + } + printk(KERN_ERR PFX "Unsupported %s chipset," + " you might want to try " + "agp_try_unsupported=1.\n", + agp_bridge_info[i].vendor_name); + return -ENODEV; +} /* Supported Device Scanning routine */ -static void agp_find_supported_device(void) +static int __init agp_find_supported_device(void) { struct pci_dev *dev = NULL; u8 cap_ptr = 0x00; u32 cap_id, scratch; - if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL) { - agp_bridge.type = NOT_SUPPORTED; - return; - } + if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL) + return -ENODEV; + agp_bridge.dev = dev; /* Need to test for I810 here */ @@ -1698,65 +1879,58 @@ static void agp_find_supported_device(void) PCI_DEVICE_ID_INTEL_810_1, NULL); if (i810_dev == NULL) { - printk("agpgart: Detected an Intel i810," + printk(KERN_ERR PFX "Detected an Intel i810," " but could not find the secondary" " device.\n"); - agp_bridge.type = NOT_SUPPORTED; - return; + return -ENODEV; } - printk(KERN_INFO "agpgart: Detected an Intel " + printk(KERN_INFO PFX "Detected an Intel " "i810 Chipset.\n"); agp_bridge.type = INTEL_I810; - agp_bridge.intel_i810_setup(i810_dev); - return; + return intel_i810_setup (i810_dev); case PCI_DEVICE_ID_INTEL_810_DC100_0: i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_810_DC100_1, NULL); if (i810_dev == NULL) { - printk("agpgart: Detected an Intel i810 " + printk(KERN_ERR PFX "Detected an Intel i810 " "DC100, but could not find the " "secondary device.\n"); - agp_bridge.type = NOT_SUPPORTED; - return; + return -ENODEV; } - printk(KERN_INFO "agpgart: Detected an Intel i810 " + printk(KERN_INFO PFX "Detected an Intel i810 " "DC100 Chipset.\n"); agp_bridge.type = INTEL_I810; - agp_bridge.intel_i810_setup(i810_dev); - return; + return intel_i810_setup(i810_dev); case PCI_DEVICE_ID_INTEL_810_E_0: i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_810_E_1, NULL); if (i810_dev == NULL) { - printk("agpgart: Detected an Intel i810 E" + printk(KERN_ERR PFX "Detected an Intel i810 E" ", but could not find the secondary " "device.\n"); - agp_bridge.type = NOT_SUPPORTED; - return; + return -ENODEV; } - printk(KERN_INFO "agpgart: Detected an Intel i810 E " + printk(KERN_INFO PFX "Detected an Intel i810 E " "Chipset.\n"); agp_bridge.type = INTEL_I810; - agp_bridge.intel_i810_setup(i810_dev); - return; + return intel_i810_setup(i810_dev); + default: break; } } -#endif +#endif /* CONFIG_AGP_I810 */ + /* find capndx */ pci_read_config_dword(dev, 0x04, &scratch); + if (!(scratch & 0x00100000)) + return -ENODEV; - if (!(scratch & 0x00100000)) { - agp_bridge.type = NOT_SUPPORTED; - return; - } pci_read_config_byte(dev, 0x34, &cap_ptr); - if (cap_ptr != 0x00) { do { pci_read_config_dword(dev, cap_ptr, &cap_id); @@ -1766,10 +1940,8 @@ static void agp_find_supported_device(void) } while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); } - if (cap_ptr == 0x00) { - agp_bridge.type = NOT_SUPPORTED; - return; - } + if (cap_ptr == 0x00) + return -ENODEV; agp_bridge.capndx = cap_ptr; /* Fill in the mode register */ @@ -1777,175 +1949,8 @@ static void agp_find_supported_device(void) agp_bridge.capndx + 4, &agp_bridge.mode); - switch (dev->vendor) { -#ifdef CONFIG_AGP_INTEL - case PCI_VENDOR_ID_INTEL: - switch (dev->device) { - case PCI_DEVICE_ID_INTEL_82443LX_0: - agp_bridge.type = INTEL_LX; - printk(KERN_INFO "agpgart: Detected an Intel 440LX" - " Chipset.\n"); - agp_bridge.intel_generic_setup(); - return; - - case PCI_DEVICE_ID_INTEL_82443BX_0: - agp_bridge.type = INTEL_BX; - printk(KERN_INFO "agpgart: Detected an Intel 440BX " - "Chipset.\n"); - agp_bridge.intel_generic_setup(); - return; - - case PCI_DEVICE_ID_INTEL_82443GX_0: - agp_bridge.type = INTEL_GX; - printk(KERN_INFO "agpgart: Detected an Intel 440GX " - "Chipset.\n"); - agp_bridge.intel_generic_setup(); - return; - - default: - if (agp_try_unsupported != 0) { - printk("agpgart: Trying generic intel " - "routines for device id: %x\n", - dev->device); - agp_bridge.type = INTEL_GENERIC; - agp_bridge.intel_generic_setup(); - return; - } else { - printk("agpgart: Unsupported intel chipset," - " you might want to try " - "agp_try_unsupported=1.\n"); - agp_bridge.type = NOT_SUPPORTED; - return; - } - } - break; -#endif - -#ifdef CONFIG_AGP_VIA - case PCI_VENDOR_ID_VIA: - switch (dev->device) { - case PCI_DEVICE_ID_VIA_82C597_0: - agp_bridge.type = VIA_VP3; - printk(KERN_INFO "agpgart: Detected a VIA VP3 " - "Chipset.\n"); - agp_bridge.via_generic_setup(); - return; - - case PCI_DEVICE_ID_VIA_82C598_0: - agp_bridge.type = VIA_MVP3; - printk(KERN_INFO "agpgart: Detected a VIA MVP3 " - "Chipset.\n"); - agp_bridge.via_generic_setup(); - return; - - case PCI_DEVICE_ID_VIA_82C691_0: - agp_bridge.type = VIA_APOLLO_PRO; - printk(KERN_INFO "agpgart: Detected a VIA Apollo " - "Pro Chipset.\n"); - agp_bridge.via_generic_setup(); - return; - - default: - if (agp_try_unsupported != 0) { - printk("agpgart: Trying generic VIA routines" - " for device id: %x\n", dev->device); - agp_bridge.type = VIA_GENERIC; - agp_bridge.via_generic_setup(); - return; - } else { - printk("agpgart: Unsupported VIA chipset," - " you might want to try " - "agp_try_unsupported=1.\n"); - agp_bridge.type = NOT_SUPPORTED; - return; - } - } - break; -#endif - -#ifdef CONFIG_AGP_SIS - case PCI_VENDOR_ID_SI: - switch (dev->device) { - /* ToDo need to find out the - * specific devices supported. - */ - default: - if (agp_try_unsupported != 0) { - printk("agpgart: Trying generic SiS routines" - " for device id: %x\n", dev->device); - agp_bridge.type = SIS_GENERIC; - agp_bridge.sis_generic_setup(); - return; - } else { - printk("agpgart: Unsupported SiS chipset, " - "you might want to try " - "agp_try_unsupported=1.\n"); - agp_bridge.type = NOT_SUPPORTED; - return; - } - } - break; -#endif - -#ifdef CONFIG_AGP_AMD - case PCI_VENDOR_ID_AMD: - switch (dev->device) { - case PCI_DEVICE_ID_AMD_IRONGATE_0: - agp_bridge.type = AMD_IRONGATE; - printk(KERN_INFO "agpgart: Detected an AMD Irongate" - " Chipset.\n"); - agp_bridge.amd_irongate_setup(); - return; - - default: - if (agp_try_unsupported != 0) { - printk("agpgart: Trying Amd irongate" - " routines for device id: %x\n", - dev->device); - agp_bridge.type = AMD_GENERIC; - agp_bridge.amd_irongate_setup(); - return; - } else { - printk("agpgart: Unsupported Amd chipset," - " you might want to try " - "agp_try_unsupported=1.\n"); - agp_bridge.type = NOT_SUPPORTED; - return; - } - } - break; -#endif - -#ifdef CONFIG_AGP_ALI - case PCI_VENDOR_ID_AL: - switch (dev->device) { - case PCI_DEVICE_ID_AL_M1541_0: - agp_bridge.type = ALI_M1541; - printk(KERN_INFO "agpgart: Detected an ALi M1541" - " Chipset\n"); - agp_bridge.ali_generic_setup(); - return; - default: - if (agp_try_unsupported != 0) { - printk("agpgart: Trying ALi generic routines" - " for device id: %x\n", dev->device); - agp_bridge.type = ALI_GENERIC; - agp_bridge.ali_generic_setup(); - return; - } else { - printk("agpgart: Unsupported ALi chipset," - " you might want to type " - "agp_try_unsupported=1.\n"); - agp_bridge.type = NOT_SUPPORTED; - return; - } - } - break; -#endif - default: - agp_bridge.type = NOT_SUPPORTED; - return; - } + /* probe for known chipsets */ + return agp_lookup_host_bridge (dev); } struct agp_max_table { @@ -1953,7 +1958,7 @@ struct agp_max_table { int agp; }; -static struct agp_max_table maxes_table[9] = +static struct agp_max_table maxes_table[9] __initdata = { {0, 0}, {32, 4}, @@ -1966,7 +1971,7 @@ static struct agp_max_table maxes_table[9] = {4096, 3932} }; -static int agp_find_max(void) +static int __init agp_find_max (void) { long memory, index, result; @@ -1983,7 +1988,7 @@ static int agp_find_max(void) (maxes_table[index].agp - maxes_table[index - 1].agp)) / (maxes_table[index].mem - maxes_table[index - 1].mem); - printk(KERN_INFO "agpgart: Maximum main memory to use " + printk(KERN_INFO PFX "Maximum main memory to use " "for agp memory: %ldM\n", result); result = result << (20 - PAGE_SHIFT); return result; @@ -1998,39 +2003,27 @@ static agp_version agp_current_version = AGPGART_VERSION_MINOR }; -static int agp_backend_initialize(void) +static int __init agp_backend_initialize(void) { - int size_value; + int size_value, rc, got_gatt=0, got_keylist=0; memset(&agp_bridge, 0, sizeof(struct agp_bridge_data)); agp_bridge.type = NOT_SUPPORTED; -#ifdef CONFIG_AGP_INTEL - agp_bridge.intel_generic_setup = intel_generic_setup; -#endif -#ifdef CONFIG_AGP_I810 - agp_bridge.intel_i810_setup = intel_i810_setup; -#endif -#ifdef CONFIG_AGP_VIA - agp_bridge.via_generic_setup = via_generic_setup; -#endif -#ifdef CONFIG_AGP_SIS - agp_bridge.sis_generic_setup = sis_generic_setup; -#endif -#ifdef CONFIG_AGP_AMD - agp_bridge.amd_irongate_setup = amd_irongate_setup; -#endif -#ifdef CONFIG_AGP_ALI - agp_bridge.ali_generic_setup = ali_generic_setup; -#endif agp_bridge.max_memory_agp = agp_find_max(); agp_bridge.version = &agp_current_version; - agp_find_supported_device(); + + rc = agp_find_supported_device(); + if (rc) { + /* not KERN_ERR because error msg should have already printed */ + printk(KERN_DEBUG PFX "no supported devices found.\n"); + return rc; + } if (agp_bridge.needs_scratch_page == TRUE) { agp_bridge.scratch_page = agp_alloc_page(); if (agp_bridge.scratch_page == 0) { - printk("agpgart: unable to get memory for " + printk(KERN_ERR PFX "unable to get memory for " "scratch page.\n"); return -ENOMEM; } @@ -2039,43 +2032,59 @@ static int agp_backend_initialize(void) agp_bridge.scratch_page = agp_bridge.mask_memory(agp_bridge.scratch_page, 0); } - if (agp_bridge.type == NOT_SUPPORTED) { - printk("agpgart: no supported devices found.\n"); - return -EINVAL; - } + size_value = agp_bridge.fetch_size(); if (size_value == 0) { - printk("agpgart: unable to detrimine aperture size.\n"); - return -EINVAL; + printk(KERN_ERR PFX "unable to detrimine aperture size.\n"); + rc = -EINVAL; + goto err_out; } if (agp_bridge.create_gatt_table()) { - printk("agpgart: unable to get memory for graphics " + printk(KERN_ERR PFX "unable to get memory for graphics " "translation table.\n"); - return -ENOMEM; + rc = -ENOMEM; + goto err_out; } + got_gatt = 1; + agp_bridge.key_list = vmalloc(PAGE_SIZE * 4); - if (agp_bridge.key_list == NULL) { - printk("agpgart: error allocating memory for key lists.\n"); - agp_bridge.free_gatt_table(); - return -ENOMEM; + printk(KERN_ERR PFX "error allocating memory for key lists.\n"); + rc = -ENOMEM; + goto err_out; } + got_keylist = 1; + + /* FIXME vmalloc'd memory not guaranteed contiguous */ memset(agp_bridge.key_list, 0, PAGE_SIZE * 4); if (agp_bridge.configure()) { - printk("agpgart: error configuring host chipset.\n"); - agp_bridge.free_gatt_table(); - vfree(agp_bridge.key_list); - return -EINVAL; + printk(KERN_ERR PFX "error configuring host chipset.\n"); + rc = -EINVAL; + goto err_out; } - printk(KERN_INFO "agpgart: Physical address of the agp aperture:" - " 0x%lx\n", agp_bridge.gart_bus_addr); - printk(KERN_INFO "agpgart: Agp aperture is %dM in size.\n", - size_value); + + printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n", + size_value, agp_bridge.gart_bus_addr); + return 0; + +err_out: + if (agp_bridge.needs_scratch_page == TRUE) { + agp_bridge.scratch_page &= ~(0x00000fff); + agp_destroy_page((unsigned long) + phys_to_virt(agp_bridge.scratch_page)); + } + if (got_gatt) + agp_bridge.free_gatt_table(); + if (got_keylist) + vfree(agp_bridge.key_list); + return rc; } + +/* cannot be __exit b/c as it could be called from __init code */ static void agp_backend_cleanup(void) { agp_bridge.cleanup(); @@ -2098,17 +2107,17 @@ static int __init agp_init(void) printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Jeff Hartmann\n", AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); - ret_val = agp_backend_initialize(); - if (ret_val != 0) { + ret_val = agp_backend_initialize(); + if (ret_val) return ret_val; - } - ret_val = agp_frontend_initialize(); - if (ret_val != 0) { + ret_val = agp_frontend_initialize(); + if (ret_val) { agp_backend_cleanup(); return ret_val; } + return 0; } diff --git a/drivers/char/agp/agpgart_fe.c b/drivers/char/agp/agpgart_fe.c index 8edcbf66904e..199d5c0791f6 100644 --- a/drivers/char/agp/agpgart_fe.c +++ b/drivers/char/agp/agpgart_fe.c @@ -47,6 +47,8 @@ #include #include +#include "agp.h" + static struct agp_front_data agp_fe; static agp_memory *agp_find_mem_by_key(int key) @@ -298,7 +300,7 @@ static agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) agp_memory *memory; memory = agp_allocate_memory(pg_count, type); - printk("memory : %p\n", memory); + printk(KERN_DEBUG "memory : %p\n", memory); if (memory == NULL) { return NULL; } @@ -969,95 +971,90 @@ static int agp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { agp_file_private *curr_priv = (agp_file_private *) file->private_data; - int ret_val; + int ret_val = -ENOTTY; AGP_LOCK(); if ((agp_fe.current_controller == NULL) && (cmd != AGPIOC_ACQUIRE)) { - return -EINVAL; + ret_val = -EINVAL; + goto ioctl_out; } if ((agp_fe.backend_acquired != TRUE) && (cmd != AGPIOC_ACQUIRE)) { - return -EBUSY; + ret_val = -EBUSY; + goto ioctl_out; } if (cmd != AGPIOC_ACQUIRE) { if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) { - return -EPERM; + ret_val = -EPERM; + goto ioctl_out; } /* Use the original pid of the controller, * in case it's threaded */ if (agp_fe.current_controller->pid != curr_priv->my_pid) { - return -EBUSY; + ret_val = -EBUSY; + goto ioctl_out; } } switch (cmd) { case AGPIOC_INFO: { ret_val = agpioc_info_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_ACQUIRE: { ret_val = agpioc_acquire_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_RELEASE: { ret_val = agpioc_release_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_SETUP: { ret_val = agpioc_setup_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_RESERVE: { ret_val = agpioc_reserve_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_PROTECT: { ret_val = agpioc_protect_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_ALLOCATE: { ret_val = agpioc_allocate_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_DEALLOCATE: { ret_val = agpioc_deallocate_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_BIND: { ret_val = agpioc_bind_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } case AGPIOC_UNBIND: { ret_val = agpioc_unbind_wrap(curr_priv, arg); - AGP_UNLOCK(); - return ret_val; + goto ioctl_out; } } - + +ioctl_out: AGP_UNLOCK(); - return -ENOTTY; + return ret_val; } static struct file_operations agp_fops = @@ -1074,24 +1071,23 @@ static struct file_operations agp_fops = static struct miscdevice agp_miscdev = { AGPGART_MINOR, - "agpgart", + AGPGART_MODULE_NAME, &agp_fops }; -int agp_frontend_initialize(void) +int __init agp_frontend_initialize(void) { memset(&agp_fe, 0, sizeof(struct agp_front_data)); AGP_LOCK_INIT(); if (misc_register(&agp_miscdev)) { - printk("agpgart: unable to get minor: %d\n", AGPGART_MINOR); + printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR); return -EIO; } return 0; } -void agp_frontend_cleanup(void) +void __exit agp_frontend_cleanup(void) { misc_deregister(&agp_miscdev); - return; } diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index 8bc4f4b5f20d..391cfcfc0295 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c @@ -235,16 +235,9 @@ efi_rtc_close(struct inode *inode, struct file *file) */ static struct file_operations efi_rtc_fops = { - NULL, - NULL, /* no read */ - NULL, /* No write */ - NULL, /* No readdir */ - NULL, - efi_rtc_ioctl, - NULL, /* No mmap */ - efi_rtc_open, - NULL, /* flush */ - efi_rtc_close + ioctl: efi_rtc_ioctl, + open: efi_rtc_open, + release: efi_rtc_close, }; static struct miscdevice efi_rtc_dev= diff --git a/drivers/char/pc110pad.c b/drivers/char/pc110pad.c index b5443e27ba5a..35098c7c48b7 100644 --- a/drivers/char/pc110pad.c +++ b/drivers/char/pc110pad.c @@ -1,5 +1,9 @@ /* * Linux driver for the PC110 pad + */ + +/** + * DOC: PC110 Digitizer Hardware * * The pad provides triples of data. The first byte has * 0x80=bit 8 X, 0x01=bit 7 X, 0x08=bit 8 Y, 0x01=still down @@ -7,13 +11,24 @@ * The third is bits 0-6 Y * * This is read internally and used to synthesize a stream of - * triples in the form expected from a PS/2 device. + * triples in the form expected from a PS/2 device. Specialist + * applications can choose to obtain the pad data in other formats + * including a debugging mode. + * + * It would be good to add a joystick driver mode to this pad so + * that doom and other game playing are better. One possible approach + * would be to deactive the mouse mode while the joystick port is opened. + */ + +/* + * History * * 0.0 1997-05-16 Alan Cox - Pad reader * 0.1 1997-05-19 Robin O'Leary - PS/2 emulation * 0.2 1997-06-03 Robin O'Leary - tap gesture * 0.3 1997-06-27 Alan Cox - 2.1 commit * 0.4 1997-11-09 Alan Cox - Single Unix VFS API changes + * 0.5 2000-02-10 Alan Cox - 2.3.x cleanup, documentation */ #include @@ -56,7 +71,9 @@ static int active=0; /* number of concurrent open()s */ static struct semaphore reader_lock; /* - * Utility to reset a timer to go off some time in the future. + * set_timer_callback: + * + * Utility to reset a timer to go off some time in the future. */ static void set_timer_callback(struct timer_list *timer, int ticks) @@ -67,10 +84,14 @@ static void set_timer_callback(struct timer_list *timer, int ticks) } -/* - * Take care of letting any waiting processes know that - * now would be a good time to do a read(). Called - * whenever a state transition occurs, real or synthetic. +/** + * wake_readers: + * + * Take care of letting any waiting processes know that + * now would be a good time to do a read(). Called + * whenever a state transition occurs, real or synthetic. Also + * issue any SIGIO's to programs that use SIGIO on mice (eg + * Executor) */ static void wake_readers(void) @@ -112,7 +133,10 @@ static void tap_timeout(unsigned long data); static struct timer_list tap_timer = { NULL, NULL, 0, 0, tap_timeout }; -/* +/** + * tap_timeout: + * @data: Unused + * * This callback goes off a short time after an up/down transition; * before it goes off, transitions will be considered part of a * single PS/2 event and counted in transition_count. Once the @@ -136,7 +160,9 @@ static void tap_timeout(unsigned long data) } -/* +/** + * notify_pad_up_down: + * * Called by the raw pad read routines when a (debounced) up/down * transition is detected. */ @@ -159,6 +185,13 @@ void notify_pad_up_down(void) wake_readers(); } +/** + * read_button: + * @b: pointer to the button status. + * + * The actual button state depends on what we are seeing. We have to check + * for the tap gesture and also for dragging. + */ static void read_button(int *b) { @@ -216,12 +249,17 @@ static void bounce_timeout(unsigned long data); static struct timer_list bounce_timer = { NULL, NULL, 0, 0, bounce_timeout }; + +/** + * bounce_timeout: + * @data: Unused + * + * No further up/down transitions happened within the + * bounce period, so treat this as a genuine transition. + */ + static void bounce_timeout(unsigned long data) { - /* - * No further up/down transitions happened within the - * bounce period, so treat this as a genuine transition. - */ switch(bounce) { case NO_BOUNCE: @@ -230,7 +268,7 @@ static void bounce_timeout(unsigned long data) * Strange; the timer callback should only go off if * we were expecting to do bounce processing! */ - printk("pc110pad, bounce_timeout: bounce flag not set!\n"); + printk(KERN_WARNING "pc110pad, bounce_timeout: bounce flag not set!\n"); break; } case JUST_GONE_UP: @@ -242,7 +280,7 @@ static void bounce_timeout(unsigned long data) bounce=NO_BOUNCE; if(debounced_down==raw_down) { - printk("pc110pad, bounce_timeout: raw already debounced!\n"); + printk(KERN_WARNING "pc110pad, bounce_timeout: raw already debounced!\n"); } debounced_down=raw_down; @@ -263,10 +301,17 @@ static void bounce_timeout(unsigned long data) } -/* +/** + * pad_irq: + * @irq: Interrupt number + * @ptr: Unused + * @regs: Unused + * * Callback when pad's irq goes off; copies values in to raw_* globals; - * initiates debounce processing. + * initiates debounce processing. This isn't SMP safe however there are + * no SMP machines with a PC110 touchpad on them. */ + static void pad_irq(int irq, void *ptr, struct pt_regs *regs) { @@ -356,6 +401,18 @@ static void pad_irq(int irq, void *ptr, struct pt_regs *regs) } } +/** + * read_raw_pad: + * @down: set if the pen is down + * @debounced: set if the debounced pen position is down + * @x: X position + * @y: Y position + * + * Retrieve the data saved by the interrupt handler and indicate we + * have no more pending XY to do. + * + * FIXME: We should switch to a spinlock for this. + */ static void read_raw_pad(int *down, int *debounced, int *x, int *y) { @@ -384,6 +441,12 @@ static void read_raw_pad(int *down, int *debounced, int *x, int *y) static int read_bytes[3]; static int read_byte_count=0; +/** + * sample_raw: + * @d: sample buffer + * + * Retrieve a triple of sample data. + */ static void sample_raw(int d[3]) @@ -393,6 +456,14 @@ static void sample_raw(int d[3]) d[2]=raw_data[2]; } +/** + * sample_rare: + * @d: sample buffer + * + * Retrieve a triple of sample data and sanitize it. We do the needed + * scaling and masking to get the current status. + */ + static void sample_rare(int d[3]) { @@ -409,20 +480,40 @@ static void sample_rare(int d[3]) d[2]=thisy%256; } +/** + * sample_debug: + * @d: sample buffer + * + * Retrieve a triple of sample data and mix it up with the state + * information in the gesture parser. Not useful for normal users but + * handy when debugging + */ static void sample_debug(int d[3]) { int thisd, thisdd, thisx, thisy; int b; + unsigned long flags; + + save_flags(flags); cli(); read_raw_pad(&thisd, &thisdd, &thisx, &thisy); d[0]=(thisd?0x80:0) | (thisdd?0x40:0) | bounce; d[1]=(recent_transition?0x80:0)+transition_count; read_button(&b); d[2]=(synthesize_tap<<4) | (b?0x01:0); - sti(); + restore_flags(flags); } +/** + * sample_ps2: + * @d: sample buffer + * + * Retrieve a triple of sample data and turn the debounced tap and + * stroke information into what appears to be a PS/2 mouse. This means + * the PC110 pad needs no funny application side support. + */ + static void sample_ps2(int d[3]) { @@ -474,7 +565,16 @@ static void sample_ps2(int d[3]) } - +/** + * fasync_pad: + * @fd: file number for the file + * @filp: file handle + * @on: 1 to add, 0 to remove a notifier + * + * Update the queue of asynchronous event notifiers. We can use the + * same helper the mice do and that does almost everything we need. + */ + static int fasync_pad(int fd, struct file *filp, int on) { int retval; @@ -486,9 +586,16 @@ static int fasync_pad(int fd, struct file *filp, int on) } -/* - * close access to the pad +/** + * close_pad: + * @inode: inode of pad + * @file: file handle to pad + * + * Close access to the pad. We turn the pad power off if this is the + * last user of the pad. I've not actually measured the power draw but + * the DOS driver is careful to do this so we follow suit. */ + static int close_pad(struct inode * inode, struct file * file) { fasync_pad(-1, file, 0); @@ -500,9 +607,17 @@ static int close_pad(struct inode * inode, struct file * file) } -/* - * open access to the pad +/** + * open_pad: + * @inode: inode of pad + * @file: file handle to pad + * + * Open access to the pad. We turn the pad off first (we turned it off + * on close but if this is the first open after a crash the state is + * indeterminate). The device has a small fifo so we empty that before + * we kick it back into action. */ + static int open_pad(struct inode * inode, struct file * file) { unsigned long flags; @@ -533,15 +648,31 @@ static int open_pad(struct inode * inode, struct file * file) } -/* - * writes are disallowed +/** + * write_pad: + * @file: File handle to the pad + * @buffer: Unused + * @count: Unused + * @ppos: Unused + * + * Writes are disallowed. A true PS/2 mouse lets you write stuff. Everyone + * seems happy with this and not faking the write modes. */ + static ssize_t write_pad(struct file * file, const char * buffer, size_t count, loff_t *ppos) { return -EINVAL; } +/* + * new_sample: + * @d: sample buffer + * + * Fetch a new sample according the current mouse mode the pad is + * using. + */ + void new_sample(int d[3]) { switch(current_params.mode) @@ -554,9 +685,17 @@ void new_sample(int d[3]) } -/* - * Read pad data. Currently never blocks. +/** + * read_pad: + * @file: File handle to pad + * @buffer: Target for the mouse data + * @count: Buffer length + * @ppos: Offset (unused) + * + * Read data from the pad. We use the reader_lock to avoid mess when there are + * two readers. This shouldnt be happening anyway but we play safe. */ + static ssize_t read_pad(struct file * file, char * buffer, size_t count, loff_t *ppos) { int r; @@ -578,8 +717,14 @@ static ssize_t read_pad(struct file * file, char * buffer, size_t count, loff_t } -/* - * select for pad input +/** + * pad_poll: + * @file: File of the pad device + * @wait: Poll table + * + * The pad is ready to read if there is a button or any position change + * pending in the queue. The reading and interrupt routines maintain the + * required state for us and do needed wakeups. */ static unsigned int pad_poll(struct file *file, poll_table * wait) @@ -591,6 +736,20 @@ static unsigned int pad_poll(struct file *file, poll_table * wait) } +/** + * pad_ioctl; + * @inode: Inode of the pad + * @file: File handle to the pad + * @cmd: Ioctl command + * @arg: Argument pointer + * + * The PC110 pad supports two ioctls both of which use the pc110pad_params + * structure. GETP queries the current pad status. SETP changes the pad + * configuration. Changing configuration during normal mouse operations + * may give momentarily odd results as things like tap gesture state + * may be lost. + */ + static int pad_ioctl(struct inode *inode, struct file * file, unsigned int cmd, unsigned long arg) { @@ -642,6 +801,15 @@ static struct miscdevice pc110_pad = { }; +/** + * pc110pad_init: + * + * We configure the pad with the default parameters (that is PS/2 + * emulation mode. We then claim the needed I/O and interrupt resources. + * Finally as a matter of paranoia we turn the pad off until we are + * asked to open it by an application. + */ + int pc110pad_init(void) { current_params = default_params; @@ -669,6 +837,13 @@ int pc110pad_init(void) #ifdef MODULE +/** + * pc110pad_unload: + * + * Free the resources we acquired when the module was loaded. We also + * turn the pad off to be sure we don't leave it using power. + */ + static void pc110pad_unload(void) { outb(0x30, current_params.io+2); /* switch off digitiser */ diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c index 3f587bea423a..029a76bd4c60 100644 --- a/drivers/char/wdt.c +++ b/drivers/char/wdt.c @@ -62,8 +62,13 @@ static int irq=11; #ifndef MODULE -/* - * Setup options +/** + * wdt_setup: + * @str: command line string + * + * Setup options. The board isn't really probe-able so we have to + * get the user to tell us the configuration. Sane people build it + * modular but the others come here. */ static int __init wdt_setup(char *str) @@ -108,6 +113,17 @@ static void wdt_ctr_load(int ctr, int val) * Kernel methods. */ + +/** + * wdt_status: + * + * Extract the status information from a WDT watchdog device. There are + * several board variants so we have to know which bits are valid. Some + * bits default to one and some to zero in order to be maximally painful. + * + * we then map the bits onto the status ioctl flags. + */ + static int wdt_status(void) { /* @@ -134,11 +150,26 @@ static int wdt_status(void) return flag; } +/** + * wdt_interrupt: + * @irq: Interrupt number + * @dev_id: Unused as we don't allow multiple devices. + * @regs: Unused. + * + * Handle an interrupt from the board. These are raised when the status + * map changes in what the board considers an interesting way. That means + * a failure condition occuring. + * + * FIXME: We need to pass a dev_id as the PCI card can share irqs + * although its arguably a _very_ dumb idea to share watchdog + * irq lines + */ + void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* * Read the status register see what is up and - * then printk it. + * then printk it. */ unsigned char status=inb_p(WDT_SR); @@ -175,6 +206,13 @@ static long long wdt_llseek(struct file *file, long long offset, int origin) return -ESPIPE; } +/** + * wdt_ping: + * + * Reload counter one with the watchdog timeout. We don't bother reloading + * the cascade counter. + */ + static void wdt_ping(void) { /* Write a watchdog value */ @@ -184,6 +222,17 @@ static void wdt_ping(void) outb_p(0, WDT_DC); } +/** + * wdt_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ @@ -198,8 +247,15 @@ static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_ return 0; } -/* - * Read reports the temperature in degrees Fahrenheit. +/** + * wdt_read: + * @file: file handle to the watchdog board + * @buf: buffer to write 1 byte into + * @count: length of buffer + * @ptr: offset (no seek allowed) + * + * Read reports the temperature in degrees Fahrenheit. The API is in + * farenheit. It was designed by an imperial measurement luddite. */ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr) @@ -225,6 +281,18 @@ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr) } } +/** + * wdt_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. We only actually usefully support + * querying capabilities and current status. + */ + static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -254,6 +322,18 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } } +/** + * wdt_open: + * @inode: inode of device + * @file: file handle to device + * + * One of our two misc devices has been opened. The watchdog device is + * single open and on opening we load the counters. Counter zero is a + * 100Hz cascade, into counter 1 which downcounts to reboot. When the + * counter triggers counter 2 downcounts the length of the reset pulse + * which set set to be as long as possible. + */ + static int wdt_open(struct inode *inode, struct file *file) { switch(MINOR(inode->i_rdev)) @@ -284,6 +364,18 @@ static int wdt_open(struct inode *inode, struct file *file) } } +/** + * wdt_close: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + static int wdt_release(struct inode *inode, struct file *file) { if(MINOR(inode->i_rdev)==WATCHDOG_MINOR) @@ -298,8 +390,16 @@ static int wdt_release(struct inode *inode, struct file *file) return 0; } -/* - * Notifier for system down +/** + * notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. */ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, @@ -360,6 +460,16 @@ static struct notifier_block wdt_notifier= #define wdt_init init_module +/** + * cleanup_module: + * + * Unload the watchdog. You cannot do this with any file handles open. + * If your watchdog is set to continue ticking on close and you unload + * it, well it keeps ticking. We won't get the interrupt but the board + * will not touch PC memory so all is fine. You just have to load a new + * module in 60 seconds or reboot. + */ + void cleanup_module(void) { misc_deregister(&wdt_miscdev); @@ -373,6 +483,14 @@ void cleanup_module(void) #endif +/** + * wdt_init: + * + * Set up the WDT watchdog board. All we have to do is grab the + * resources we require and bitch if anyone beat us to them. + * The open() function will actually kick the board off. + */ + int __init wdt_init(void) { printk(KERN_INFO "WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io,irq); diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index fdf2eeef9a58..0334b7fe2f12 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -58,7 +58,7 @@ * packet to arrive. When one arrives it is copied out of the buffer * and delivered to the kernel. The card is reloaded and off we go. * - * When transmitting dev->tbusy is set and the card is reset (from + * When transmitting lp->txing is set and the card is reset (from * receive mode) [possibly losing a packet just received] to command * mode. A packet is loaded and transmit mode triggered. The interrupt * handler runs different code for transmit interrupts and can handle @@ -129,6 +129,7 @@ static unsigned int netcard_portlist[] __initdata = { int el1_probe(struct net_device *dev); static int el1_probe1(struct net_device *dev, int ioaddr); static int el_open(struct net_device *dev); +static void el_timeout(struct net_device *dev); static int el_start_xmit(struct sk_buff *skb, struct net_device *dev); static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void el_receive(struct net_device *dev); @@ -154,6 +155,7 @@ struct net_local int tx_pkt_start; /* The length of the current Tx packet. */ int collisions; /* Tx collisions this packet */ int loading; /* Spot buffer load collisions */ + int txing; /* True if card is in TX mode */ spinlock_t lock; /* Serializing lock */ }; @@ -370,6 +372,8 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr) dev->open = &el_open; dev->hard_start_xmit = &el_start_xmit; + dev->tx_timeout = &el_timeout; + dev->watchdog_timeo = HZ; dev->stop = &el1_close; dev->get_stats = &el1_get_stats; dev->set_multicast_list = &set_multicast_list; @@ -412,15 +416,42 @@ static int el_open(struct net_device *dev) el_reset(dev); spin_unlock_irqrestore(&lp->lock, flags); - dev->start = 1; - + lp->txing = 0; /* Board in RX mode */ outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */ + netif_start_queue(dev); MOD_INC_USE_COUNT; return 0; } /** - * e1_start_xmit: + * el_timeout: + * @dev: The 3c501 card that has timed out + * + * Attempt to restart the board. This is basically a mixture of extreme + * violence and prayer + * + */ + +static void el_timeout(struct net_device *dev) +{ + struct net_local *lp = (struct net_local *)dev->priv; + int ioaddr = dev->base_addr; + + if (el_debug) + printk (KERN_DEBUG "%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n", + dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS)); + lp->stats.tx_errors++; + outb(TX_NORM, TX_CMD); + outb(RX_NORM, RX_CMD); + outb(AX_OFF, AX_CMD); /* Just trigger a false interrupt. */ + outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */ + lp->txing = 0; /* Ripped back in to RX */ + netif_wake_queue(dev); +} + + +/** + * el_start_xmit: * @skb: The packet that is queued to be sent * @dev: The 3c501 card we want to throw it down * @@ -447,32 +478,9 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev) int ioaddr = dev->base_addr; unsigned long flags; - if(dev->interrupt) /* May be unloading, don't stamp on */ - return 1; /* the packet buffer this time */ - - if (dev->tbusy) - { - if (jiffies - dev->trans_start < HZ) - { - if (el_debug > 2) - printk(" transmitter busy, deferred.\n"); - return 1; - } - if (el_debug) - printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n", - dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS)); - lp->stats.tx_errors++; - outb(TX_NORM, TX_CMD); - outb(RX_NORM, RX_CMD); - outb(AX_OFF, AX_CMD); /* Just trigger a false interrupt. */ - outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */ - dev->tbusy = 0; - dev->trans_start = jiffies; - } - /* - * Avoid incoming interrupts between us flipping tbusy and flipping - * mode as the driver assumes tbusy is a faithful indicator of card + * Avoid incoming interrupts between us flipping txing and flipping + * mode as the driver assumes txing is a faithful indicator of card * state */ @@ -482,17 +490,13 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev) * Avoid timer-based retransmission conflicts. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - { - spin_unlock_irqrestore(&lp->lock, flags); - printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); - } - else + netif_stop_queue(dev); + + do { int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); unsigned char *buf = skb->data; -load_it_again_sam: lp->tx_pkt_start = gp_start; lp->collisions = 0; @@ -507,7 +511,8 @@ load_it_again_sam: inb_p(RX_STATUS); inb_p(TX_STATUS); - lp->loading=1; + lp->loading = 1; + lp->txing = 1; /* * Turn interrupts back on while we spend a pleasant afternoon @@ -520,23 +525,24 @@ load_it_again_sam: outw(gp_start, GP_LOW); /* aim - packet will be loaded into buffer start */ outsb(DATAPORT,buf,skb->len); /* load buffer (usual thing each byte increments the pointer) */ outw(gp_start, GP_LOW); /* the board reuses the same register */ - - if(lp->loading==2) /* A receive upset our load, despite our best efforts */ + + if(lp->loading != 2) { - if(el_debug>2) - printk("%s: burped during tx load.\n", dev->name); - spin_lock_irqsave(&lp->lock, flags); - goto load_it_again_sam; /* Sigh... */ + outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */ + lp->loading=0; + dev->trans_start = jiffies; + if (el_debug > 2) + printk(" queued xmit.\n"); + dev_kfree_skb (skb); + return 0; } - outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */ - lp->loading=0; - dev->trans_start = jiffies; + /* A receive upset our load, despite our best efforts */ + if(el_debug>2) + printk("%s: burped during tx load.\n", dev->name); + spin_lock_irqsave(&lp->lock, flags); } + while(1); - if (el_debug > 2) - printk(" queued xmit.\n"); - dev_kfree_skb (skb); - return 0; } @@ -570,12 +576,6 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) int ioaddr; int axsr; /* Aux. status reg. */ - if (dev == NULL || dev->irq != irq) - { - printk (KERN_ERR "3c501 driver: irq %d for unknown device.\n", irq); - return; - } - ioaddr = dev->base_addr; lp = (struct net_local *)dev->priv; @@ -593,14 +593,12 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (el_debug > 3) printk(KERN_DEBUG "%s: el_interrupt() aux=%#02x", dev->name, axsr); - if (dev->interrupt) - printk(KERN_WARNING "%s: Reentering the interrupt driver!\n", dev->name); - dev->interrupt = 1; - if(lp->loading==1 && !dev->tbusy) + + if(lp->loading==1 && !lp->txing) printk(KERN_WARNING "%s: Inconsistent state loading while not in tx\n", dev->name); - if (dev->tbusy) + if (lp->txing) { /* @@ -618,7 +616,6 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW)); } lp->loading=2; /* Force a reload */ - dev->interrupt = 0; spin_unlock(&lp->lock); return; } @@ -636,8 +633,8 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x" " gp=%03x rp=%03x.\n", dev->name, txsr, axsr, inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); - dev->tbusy = 0; - mark_bh(NET_BH); + lp->txing = 0; + netif_wake_queue(dev); } else if (txsr & TX_16COLLISIONS) { @@ -647,7 +644,9 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (el_debug) printk("%s: Transmit failed 16 times, Ethernet jammed?\n",dev->name); outb(AX_SYS, AX_CMD); + lp->txing = 0; lp->stats.tx_aborted_errors++; + netif_wake_queue(dev); } else if (txsr & TX_COLLISION) { @@ -665,7 +664,6 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) outw(lp->tx_pkt_start, GP_LOW); outb(AX_XMIT, AX_CMD); lp->stats.collisions++; - dev->interrupt = 0; spin_unlock(&lp->lock); return; } @@ -682,8 +680,8 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) * This is safe the interrupt is atomic WRT itself. */ - dev->tbusy = 0; - mark_bh(NET_BH); /* In case more to transmit */ + lp->txing = 0; + netif_wake_queue(dev); /* In case more to transmit */ } } else @@ -735,7 +733,6 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) outw(0x00, RX_BUF_CLR); inb(RX_STATUS); /* Be certain that interrupts are cleared. */ inb(TX_STATUS); - dev->interrupt = 0; spin_unlock(&lp->lock); return; } @@ -818,6 +815,7 @@ static void el_receive(struct net_device *dev) static void el_reset(struct net_device *dev) { + struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; if (el_debug> 2) @@ -835,8 +833,7 @@ static void el_reset(struct net_device *dev) outb(RX_NORM, RX_CMD); /* Set Rx commands. */ inb(RX_STATUS); /* Clear status. */ inb(TX_STATUS); - dev->interrupt = 0; - dev->tbusy = 0; + lp->txing = 0; } /** @@ -857,8 +854,7 @@ static int el1_close(struct net_device *dev) if (el_debug > 2) printk("%s: Shutting down Ethernet card at %#x.\n", dev->name, ioaddr); - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); /* * Free and disable the IRQ. diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index 8ff7823b248a..a859f9ddc085 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -314,7 +314,6 @@ el2_probe1(struct net_device *dev, int ioaddr) ei_status.saved_irq = dev->irq; - dev->start = 0; dev->open = &el2_open; dev->stop = &el2_close; diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index 15959e697555..2a6ddac7a73d 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -40,7 +40,6 @@ static const char *version = info that the casual reader might think that it documents the i82586 :-<. */ -#include #include #include #include @@ -437,9 +436,7 @@ static int el16_open(struct net_device *dev) /* Initialize the 82586 memory and start it. */ init_82586_mem(dev); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); MOD_INC_USE_COUNT; @@ -453,7 +450,8 @@ static int el16_send_packet(struct sk_buff *skb, struct net_device *dev) unsigned long shmem = dev->mem_start; unsigned long flags; - if (dev->tbusy) +#if 0 /* LINK_STATE_XOFF is never set when we reach here */ + if (test_bit(LINK_STATE_XOFF, &dev->flags)) { /* If we get here, some higher level has decided we are broken. There should really be a "kick me" function call instead. */ @@ -476,31 +474,30 @@ static int el16_send_packet(struct sk_buff *skb, struct net_device *dev) outb(0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ lp->last_restart = lp->stats.tx_packets; } - dev->tbusy=0; + netif_start_queue(dev); dev->trans_start = jiffies; } +#endif - /* Block a timer-based transmit from overlapping. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; + spin_lock_irqsave(&lp->lock, flags); + lp->stats.tx_bytes+=length; /* Disable the 82586's input to the interrupt line. */ outb(0x80, ioaddr + MISC_CTRL); -#ifdef CONFIG_SMP - spin_lock_irqsave(&lp->lock, flags); - hardware_send_packet(dev, buf, length); - spin_unlock_irqrestore(&lp->lock, flags); -#else + hardware_send_packet(dev, buf, length); -#endif + dev->trans_start = jiffies; /* Enable the 82586 interrupt input. */ outb(0x84, ioaddr + MISC_CTRL); + + spin_unlock_irqrestore(&lp->lock, flags); + + netif_stop_queue(dev); } dev_kfree_skb (skb); @@ -524,8 +521,6 @@ static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs) printk ("net_interrupt(): irq %d for unknown device.\n", irq); return; } - dev->interrupt = 1; - ioaddr = dev->base_addr; lp = (struct net_local *)dev->priv; @@ -553,8 +548,7 @@ static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (tx_status & 0x2000) { lp->stats.tx_packets++; lp->stats.collisions += tx_status & 0xf; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ + netif_wake_queue(dev); } else { lp->stats.tx_errors++; if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; @@ -580,7 +574,8 @@ static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* Acknowledge the interrupt sources. */ ack_cmd = status & 0xf000; - if ((status & 0x0700) != 0x0200 && dev->start) { + if ((status & 0x0700) != 0x0200 && + (test_bit(LINK_STATE_START, &dev->state))) { if (net_debug) printk("%s: Command unit stopped, status %04x, restarting.\n", dev->name, status); @@ -590,7 +585,8 @@ static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs) ack_cmd |= CUC_RESUME; } - if ((status & 0x0070) != 0x0040 && dev->start) + if ((status & 0x0070) != 0x0040 && + (test_bit(LINK_STATE_START, &dev->state))) { static void init_rx_bufs(struct net_device *); /* The Rx unit is not ready, it must be hung. Restart the receiver by @@ -612,8 +608,6 @@ static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* Enable the 82586's interrupt input. */ outb(0x84, ioaddr + MISC_CTRL); spin_unlock(&lp->lock); - - return; } static int el16_close(struct net_device *dev) @@ -621,8 +615,7 @@ static int el16_close(struct net_device *dev) int ioaddr = dev->base_addr; unsigned long shmem = dev->mem_start; - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); /* Flush the Tx and disable Rx. */ isa_writew(RX_SUSPEND | CUC_SUSPEND,shmem+iSCB_CMD); @@ -795,7 +788,7 @@ static void hardware_send_packet(struct net_device *dev, void *buf, short length } if (lp->tx_head != lp->tx_reap) - dev->tbusy = 0; + netif_start_queue(dev); } static void el16_rx(struct net_device *dev) diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 595d69b22963..07038b4ba2ec 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -53,6 +53,7 @@ static int max_interrupt_work = 10; #include #include +#include #include #include #include @@ -149,6 +150,7 @@ static struct enet_statistics *el3_get_stats(struct net_device *dev); static int el3_rx(struct net_device *dev); static int el3_close(struct net_device *dev); static void set_multicast_list(struct net_device *dev); +static void el3_tx_timeout (struct net_device *dev); #ifdef CONFIG_MCA struct el3_mca_adapters_struct { @@ -166,12 +168,34 @@ struct el3_mca_adapters_struct el3_mca_adapters[] = { }; #endif +#ifdef CONFIG_ISAPNP +struct el3_isapnp_adapters_struct { + unsigned short vendor, function; + char *name; +}; +struct el3_isapnp_adapters_struct el3_isapnp_adapters[] = { + {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090), "3Com Etherlink III (TP)"}, + {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5091), "3Com Etherlink III"}, + {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5094), "3Com Etherlink III (combo)"}, + {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5095), "3Com Etherlink III (TPO)"}, + {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5098), "3Com Etherlink III (TPC)"}, + {ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f8), "3Com Etherlink III compatible"}, + {0, } +}; +u16 el3_isapnp_phys_addr[8][3] = { + {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, + {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} +}; +#endif +static int nopnp = 0; + int el3_probe(struct net_device *dev) { short lrs_state = 0xff, i; int ioaddr, irq, if_port; u16 phys_addr[3]; static int current_tag = 0; + static int pnp_cards = 0; int mca_slot = -1; /* First check all slots of the EISA bus. The next slot address to @@ -265,9 +289,43 @@ int el3_probe(struct net_device *dev) return -ENODEV; } #endif - /* Reset the ISA PnP mechanism on 3c509b. */ - outb(0x02, 0x279); /* Select PnP config control register. */ - outb(0x02, 0xA79); /* Return to WaitForKey state. */ + +#ifdef CONFIG_ISAPNP + if (nopnp == 1) + goto no_pnp; + + for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) { + struct pci_dev *idev = NULL; + int j; + while ((idev = isapnp_find_dev(NULL, + el3_isapnp_adapters[i].vendor, + el3_isapnp_adapters[i].function, + idev))) { + idev->prepare(idev); + /* Deactivation is needed if the driver was called + with "nopnp=1" before, does not harm if not. */ + idev->deactivate(idev); + idev->activate(idev); + if (!idev->resource[0].start || check_region(idev->resource[0].start,16)) + continue; + ioaddr = idev->resource[0].start; + irq = idev->irq_resource[0].start; + if (el3_debug > 3) + printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n", + el3_isapnp_adapters[i].name, ioaddr, irq); + EL3WINDOW(0); + for (j = 0; j < 3; j++) + el3_isapnp_phys_addr[pnp_cards][j] = + phys_addr[j] = + htons(read_eeprom(ioaddr, j)); + if_port = read_eeprom(ioaddr, 8) >> 14; + pnp_cards++; + goto found; + } + } +no_pnp: +#endif + /* Select an open I/O location at 0x1*0 to do contention select. */ for ( ; id_port < 0x200; id_port += 0x10) { if (check_region(id_port, 1)) @@ -312,6 +370,28 @@ int el3_probe(struct net_device *dev) phys_addr[i] = htons(id_read_eeprom(i)); } +#ifdef CONFIG_ISAPNP + if (nopnp == 0) { + /* The ISA PnP 3c509 cards respond to the ID sequence. + This check is needed in order not to register them twice. */ + for (i = 0; i < pnp_cards; i++) { + if (phys_addr[0] == el3_isapnp_phys_addr[i][0] && + phys_addr[1] == el3_isapnp_phys_addr[i][1] && + phys_addr[2] == el3_isapnp_phys_addr[i][2]) + { + if (el3_debug > 3) + printk("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n", + phys_addr[0] & 0xff, phys_addr[0] >> 8, + phys_addr[1] & 0xff, phys_addr[1] >> 8, + phys_addr[2] & 0xff, phys_addr[2] >> 8); + /* Set the adaptor tag so that the next card can be found. */ + outb(0xd0 + ++current_tag, id_port); + goto no_pnp; + } + } + } +#endif + { unsigned int iobase = id_read_eeprom(8); if_port = iobase >> 14; @@ -357,8 +437,8 @@ int el3_probe(struct net_device *dev) { const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"}; - printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ", - dev->name, dev->base_addr, current_tag, if_names[dev->if_port]); + printk("%s: 3c509 at %#3.3lx, %s port, address ", + dev->name, dev->base_addr, if_names[dev->if_port]); } /* Read in the station address. */ @@ -387,6 +467,8 @@ int el3_probe(struct net_device *dev) dev->stop = &el3_close; dev->get_stats = &el3_get_stats; dev->set_multicast_list = &set_multicast_list; + dev->tx_timeout = el3_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; /* Fill in the generic fields of the device structure. */ ether_setup(dev); @@ -481,9 +563,7 @@ el3_open(struct net_device *dev) outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; + netif_start_queue(dev); outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ @@ -503,28 +583,32 @@ el3_open(struct net_device *dev) return 0; /* Always succeed */ } -static int -el3_start_xmit(struct sk_buff *skb, struct net_device *dev) +static void +el3_tx_timeout (struct net_device *dev) { struct el3_private *lp = (struct el3_private *)dev->priv; int ioaddr = dev->base_addr; /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < TX_TIMEOUT) - return 1; - printk("%s: transmit timed out, Tx_status %2.2x status %4.4x " - "Tx FIFO room %d.\n", - dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS), - inw(ioaddr + TX_FREE)); - lp->stats.tx_errors++; - dev->trans_start = jiffies; - /* Issue TX_RESET and TX_START commands. */ - outw(TxReset, ioaddr + EL3_CMD); - outw(TxEnable, ioaddr + EL3_CMD); - dev->tbusy = 0; - } + printk("%s: transmit timed out, Tx_status %2.2x status %4.4x " + "Tx FIFO room %d.\n", + dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS), + inw(ioaddr + TX_FREE)); + lp->stats.tx_errors++; + dev->trans_start = jiffies; + /* Issue TX_RESET and TX_START commands. */ + outw(TxReset, ioaddr + EL3_CMD); + outw(TxEnable, ioaddr + EL3_CMD); + netif_start_queue(dev); +} + + +static int +el3_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct el3_private *lp = (struct el3_private *)dev->priv; + int ioaddr = dev->base_addr; + unsigned long flags; lp->stats.tx_bytes += skb->len; @@ -551,47 +635,37 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev) } #endif #endif - /* Avoid timer-based retransmission conflicts. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - /* - * We lock the driver against other processors. Note - * we don't need to lock versus the IRQ as we suspended - * that. This means that we lose the ability to take - * an RX during a TX upload. That sucks a bit with SMP - * on an original 3c509 (2K buffer) - * - * Using disable_irq stops us crapping on other - * time sensitive devices. - */ - -#ifdef __SMP__ - disable_irq_nosync(dev->irq); - spin_lock(&lp->lock); -#endif + /* + * We lock the driver against other processors. Note + * we don't need to lock versus the IRQ as we suspended + * that. This means that we lose the ability to take + * an RX during a TX upload. That sucks a bit with SMP + * on an original 3c509 (2K buffer) + * + * Using disable_irq stops us crapping on other + * time sensitive devices. + */ + + spin_lock_irqsave(&lp->lock, flags); - /* Put out the doubleword header... */ - outw(skb->len, ioaddr + TX_FIFO); - outw(0x00, ioaddr + TX_FIFO); - /* ... and the packet rounded to a doubleword. */ + /* Put out the doubleword header... */ + outw(skb->len, ioaddr + TX_FIFO); + outw(0x00, ioaddr + TX_FIFO); + /* ... and the packet rounded to a doubleword. */ #ifdef __powerpc__ - outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); + outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); #else - outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); + outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); #endif - dev->trans_start = jiffies; - if (inw(ioaddr + TX_FREE) > 1536) { - dev->tbusy = 0; - } else - /* Interrupt us when the FIFO has room for max-sized packet. */ - outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); -#ifdef __SMP__ - spin_unlock(&lp->lock); - enable_irq(dev->irq); -#endif - } + dev->trans_start = jiffies; + if (inw(ioaddr + TX_FREE) > 1536) + netif_start_queue(dev); + else + /* Interrupt us when the FIFO has room for max-sized packet. */ + outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); + + spin_unlock_irqrestore(&lp->lock, flags); dev_kfree_skb (skb); @@ -627,10 +701,6 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) lp = (struct el3_private *)dev->priv; spin_lock(&lp->lock); - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; - ioaddr = dev->base_addr; if (el3_debug > 4) { @@ -649,8 +719,7 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) printk(" TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue (dev); } if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) { /* Handle all uncommon interrupts. */ @@ -701,7 +770,6 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) inw(ioaddr + EL3_STATUS)); } spin_unlock(&lp->lock); - dev->interrupt = 0; return; } @@ -862,8 +930,7 @@ el3_close(struct net_device *dev) if (el3_debug > 2) printk("%s: Shutting down ethercard.\n", dev->name); - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); /* Turn off statistics ASAP. We update lp->stats below. */ outw(StatsDisable, ioaddr + EL3_CMD); @@ -902,6 +969,7 @@ MODULE_PARM(debug,"i"); MODULE_PARM(irq,"1-8i"); MODULE_PARM(xcvr,"1-8i"); MODULE_PARM(max_interrupt_work, "i"); +MODULE_PARM(nopnp, "i"); int init_module(void) diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index b18ce126e804..fe150fac53c1 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -177,7 +177,7 @@ sizeof(nop_cmd) = 8; if(!p->scb->cmd) break; \ DELAY_16(); \ if(i == 1023) { \ - printk("%s:%d: scb_cmd timed out .. resetting i82586\n",\ + printk(KERN_WARNING "%s:%d: scb_cmd timed out .. resetting i82586\n",\ dev->name,__LINE__); \ elmc_id_reset586(); } } } @@ -186,6 +186,7 @@ static int elmc_open(struct net_device *dev); static int elmc_close(struct net_device *dev); static int elmc_send_packet(struct sk_buff *, struct net_device *); static struct net_device_stats *elmc_get_stats(struct net_device *dev); +static void elmc_timeout(struct net_device *dev); #ifdef ELMC_MULTICAST static void set_multicast_list(struct net_device *dev); #endif @@ -270,17 +271,10 @@ static void elmc_do_reset586(int ioaddr, int ints) static int elmc_close(struct net_device *dev) { + netif_stop_queue(dev); elmc_id_reset586(); /* the hard way to stop the receiver */ - free_irq(dev->irq, dev); - - dev->start = 0; - dev->tbusy = 0; - -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif - return 0; } @@ -296,22 +290,15 @@ static int elmc_open(struct net_device *dev) if (request_irq(dev->irq, &elmc_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, "3c523", dev) ) { - printk("%s: couldn't get irq %d\n", dev->name, dev->irq); + printk(KERN_ERR "%s: couldn't get irq %d\n", dev->name, dev->irq); elmc_id_reset586(); return -EAGAIN; } alloc586(dev); init586(dev); startrecv586(dev); - - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; - -#ifdef MODULE + netif_wake_queue(dev); MOD_INC_USE_COUNT; -#endif - return 0; /* most done by init */ } @@ -384,7 +371,7 @@ void alloc586(struct net_device *dev) DELAY(2); if (p->iscp->busy) { - printk("%s: Init-Problems (alloc).\n", dev->name); + printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name); } memset((char *) p->scb, 0, sizeof(struct scb_struct)); } @@ -466,7 +453,7 @@ int __init elmc_probe(struct net_device *dev) mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev); /* if we get this far, adapter has been found - carry on */ - printk("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1); + printk(KERN_INFO "%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1); /* Now we extract configuration info from the card. The 3c523 provides information in two of the POS registers, but @@ -510,7 +497,7 @@ int __init elmc_probe(struct net_device *dev) ((struct priv *) (dev->priv))->slot = slot; - printk("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision, + printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision, dev->base_addr); /* Determine if we're using the on-board transceiver (i.e. coax) or @@ -532,7 +519,7 @@ int __init elmc_probe(struct net_device *dev) size = 0x4000; /* check for 16K mem */ if (!check586(dev, dev->mem_start, size)) { - printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, + printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, dev->mem_start); release_region(dev->base_addr, ELMC_IO_EXTENT); return ENODEV; @@ -548,13 +535,13 @@ int __init elmc_probe(struct net_device *dev) ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16; /* dump all the assorted information */ - printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name, + printk(KERN_INFO "%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name, dev->irq, dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end - 1); /* The hardware address for the 3c523 is stored in the first six bytes of the IO address. */ - printk("%s: hardware address ", dev->name); + printk(KERN_INFO "%s: hardware address ", dev->name); for (i = 0; i < 6; i++) { dev->dev_addr[i] = inb(dev->base_addr + i); printk(" %02x", dev->dev_addr[i]); @@ -565,6 +552,8 @@ int __init elmc_probe(struct net_device *dev) dev->stop = &elmc_close; dev->get_stats = &elmc_get_stats; dev->hard_start_xmit = &elmc_send_packet; + dev->tx_timeout = &elmc_timeout; + dev->watchdog_timeo = HZ; #ifdef ELMC_MULTICAST dev->set_multicast_list = &set_multicast_list; #else @@ -573,10 +562,6 @@ int __init elmc_probe(struct net_device *dev) ether_setup(dev); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 0; - /* note that we haven't actually requested the IRQ from the kernel. That gets done in elmc_open(). I'm not sure that's such a good idea, but it works, so I'll go with it. */ @@ -640,7 +625,7 @@ static int init586(struct net_device *dev) } if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) { - printk("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status); + printk(KERN_WARNING "%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status); return 1; } /* @@ -666,7 +651,7 @@ static int init586(struct net_device *dev) } if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) { - printk("%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status); + printk(KERN_WARNING "%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status); return 1; } /* @@ -687,7 +672,7 @@ static int init586(struct net_device *dev) s = jiffies; while (!(tdr_cmd->cmd_status & STAT_COMPL)) { if (jiffies - s > 30*HZ/100) { - printk("%s: %d Problems while running the TDR.\n", dev->name, __LINE__); + printk(KERN_WARNING "%s: %d Problems while running the TDR.\n", dev->name, __LINE__); result = 1; break; } @@ -703,14 +688,14 @@ static int init586(struct net_device *dev) if (result & TDR_LNK_OK) { /* empty */ } else if (result & TDR_XCVR_PRB) { - printk("%s: TDR: Transceiver problem!\n", dev->name); + printk(KERN_WARNING "%s: TDR: Transceiver problem!\n", dev->name); } else if (result & TDR_ET_OPN) { - printk("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); + printk(KERN_WARNING "%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else if (result & TDR_ET_SRT) { if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ - printk("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); + printk(KERN_WARNING "%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); } else { - printk("%s: TDR: Unknown status %04x\n", dev->name, result); + printk(KERN_WARNING "%s: TDR: Unknown status %04x\n", dev->name, result); } } /* @@ -754,11 +739,11 @@ static int init586(struct net_device *dev) /* I don't understand this: do we really need memory after the init? */ int len = ((char *) p->iscp - (char *) ptr - 8) / 6; if (len <= 0) { - printk("%s: Ooooops, no memory for MC-Setup!\n", dev->name); + printk(KERN_ERR "%s: Ooooops, no memory for MC-Setup!\n", dev->name); } else { if (len < num_addrs) { num_addrs = len; - printk("%s: Sorry, can only apply %d MC-Address(es).\n", + printk(KERN_WARNING "%s: Sorry, can only apply %d MC-Address(es).\n", dev->name, num_addrs); } mc_cmd = (struct mcsetup_cmd_struct *) ptr; @@ -779,7 +764,7 @@ static int init586(struct net_device *dev) break; } if (!(mc_cmd->cmd_status & STAT_COMPL)) { - printk("%s: Can't apply multicast-address-list.\n", dev->name); + printk(KERN_WARNING "%s: Can't apply multicast-address-list.\n", dev->name); } } } @@ -792,7 +777,7 @@ static int init586(struct net_device *dev) p->xmit_buffs[i] = (struct tbd_struct *) ptr; /* TBD */ ptr = (char *) ptr + sizeof(struct tbd_struct); if ((void *) ptr > (void *) p->iscp) { - printk("%s: not enough shared-mem for your configuration!\n", dev->name); + printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", dev->name); return 1; } memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct)); @@ -882,9 +867,9 @@ static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) struct priv *p; if (dev == NULL) { - printk("elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2)); + printk(KERN_ERR "elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2)); return; - } else if (!dev->start) { + } else if (!test_bit(LINK_STATE_START, &dev->state)) { /* The 3c523 has this habit of generating interrupts during the reset. I'm not sure if the ni52 has this same problem, but it's really annoying if we haven't finished initializing it. I was @@ -901,8 +886,6 @@ static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) p = (struct priv *) dev->priv; - dev->interrupt = 1; - while ((stat = p->scb->status & STAT_MASK)) { p->scb->cmd = stat; @@ -919,8 +902,8 @@ static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) #ifndef NO_NOPCOMMANDS if (stat & STAT_CNA) { /* CU went 'not ready' */ - if (dev->start) { - printk("%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); + if (test_bit(LINK_STATE_START, &dev->state)) { + printk(KERN_WARNING "%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); } } #endif @@ -935,7 +918,7 @@ static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) p->scb->cmd = RUC_RESUME; elmc_attn586(); } else { - printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); + printk(KERN_WARNING "%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); elmc_rnr_int(dev); } } @@ -944,8 +927,6 @@ static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) break; } } - - dev->interrupt = 0; } /******************************************************* @@ -980,11 +961,11 @@ static void elmc_rcv_int(struct net_device *dev) p->stats.rx_dropped++; } } else { - printk("%s: received oversized frame.\n", dev->name); + printk(KERN_WARNING "%s: received oversized frame.\n", dev->name); p->stats.rx_dropped++; } } else { /* frame !(ok), only with 'save-bad-frames' */ - printk("%s: oops! rfd-error-status: %04x\n", dev->name, status); + printk(KERN_WARNING "%s: oops! rfd-error-status: %04x\n", dev->name, status); p->stats.rx_errors++; } p->rfd_top->status = 0; @@ -1013,7 +994,7 @@ static void elmc_rnr_int(struct net_device *dev) alloc_rfa(dev, (char *) p->rfd_first); startrecv586(dev); /* restart RU */ - printk("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status); + printk(KERN_WARNING "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status); } @@ -1028,7 +1009,7 @@ static void elmc_xmt_int(struct net_device *dev) status = p->xmit_cmds[p->xmit_last]->cmd_status; if (!(status & STAT_COMPL)) { - printk("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name); + printk(KERN_WARNING "%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name); } if (status & STAT_OK) { p->stats.tx_packets++; @@ -1036,18 +1017,18 @@ static void elmc_xmt_int(struct net_device *dev) } else { p->stats.tx_errors++; if (status & TCMD_LATECOLL) { - printk("%s: late collision detected.\n", dev->name); + printk(KERN_WARNING "%s: late collision detected.\n", dev->name); p->stats.collisions++; } else if (status & TCMD_NOCARRIER) { p->stats.tx_carrier_errors++; - printk("%s: no carrier detected.\n", dev->name); + printk(KERN_WARNING "%s: no carrier detected.\n", dev->name); } else if (status & TCMD_LOSTCTS) { - printk("%s: loss of CTS detected.\n", dev->name); + printk(KERN_WARNING "%s: loss of CTS detected.\n", dev->name); } else if (status & TCMD_UNDERRUN) { p->stats.tx_fifo_errors++; - printk("%s: DMA underrun detected.\n", dev->name); + printk(KERN_WARNING "%s: DMA underrun detected.\n", dev->name); } else if (status & TCMD_MAXCOLL) { - printk("%s: Max. collisions exceeded.\n", dev->name); + printk(KERN_WARNING "%s: Max. collisions exceeded.\n", dev->name); p->stats.collisions += 16; } } @@ -1058,8 +1039,7 @@ static void elmc_xmt_int(struct net_device *dev) } #endif - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue(dev); } /*********************************************************** @@ -1076,6 +1056,37 @@ static void startrecv586(struct net_device *dev) WAIT_4_SCB_CMD(); /* wait for accept cmd. (no timeout!!) */ } +/****************************************************** + * timeout + */ + +static void elmc_timeout(struct net_device *dev) +{ + struct priv *p = (struct priv *) dev->priv; + /* COMMAND-UNIT active? */ + if (p->scb->status & CU_ACTIVE) { +#ifdef DEBUG + printk("%s: strange ... timeout with CU active?!?\n", dev->name); + printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point); +#endif + p->scb->cmd = CUC_ABORT; + elmc_attn586(); + WAIT_4_SCB_CMD(); + p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); + p->scb->cmd = CUC_START; + elmc_attn586(); + WAIT_4_SCB_CMD(); + netif_wake_queue(dev); + } else { +#ifdef DEBUG + printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status); + printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status); +#endif + elmc_close(dev); + elmc_open(dev); + } +} + /****************************************************** * send frame */ @@ -1088,103 +1099,63 @@ static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev) #endif struct priv *p = (struct priv *) dev->priv; - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) { - return 1; - } - /* COMMAND-UNIT active? */ - if (p->scb->status & CU_ACTIVE) { - dev->tbusy = 0; -#ifdef DEBUG - printk("%s: strange ... timeout with CU active?!?\n", dev->name); - printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point); -#endif - p->scb->cmd = CUC_ABORT; - elmc_attn586(); - WAIT_4_SCB_CMD(); - p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); - p->scb->cmd = CUC_START; - elmc_attn586(); - WAIT_4_SCB_CMD(); - dev->trans_start = jiffies; - return 0; - } else { -#ifdef DEBUG - printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status); - printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status); -#endif - elmc_close(dev); - elmc_open(dev); - } - dev->trans_start = jiffies; - return 0; - } - if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - } else { - memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len); - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + netif_stop_queue(dev); + + memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len); + len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; #if (NUM_XMIT_BUFFS == 1) #ifdef NO_NOPCOMMANDS - p->xmit_buffs[0]->size = TBD_LAST | len; - for (i = 0; i < 16; i++) { - p->scb->cbl_offset = make16(p->xmit_cmds[0]); - p->scb->cmd = CUC_START; - p->xmit_cmds[0]->cmd_status = 0; - + p->xmit_buffs[0]->size = TBD_LAST | len; + for (i = 0; i < 16; i++) { + p->scb->cbl_offset = make16(p->xmit_cmds[0]); + p->scb->cmd = CUC_START; + p->xmit_cmds[0]->cmd_status = 0; elmc_attn586(); - dev->trans_start = jiffies; - if (!i) { - dev_kfree_skb(skb); - } - WAIT_4_SCB_CMD(); - if ((p->scb->status & CU_ACTIVE)) { /* test it, because CU sometimes doesn't start immediately */ - break; - } - if (p->xmit_cmds[0]->cmd_status) { - break; - } - if (i == 15) { - printk("%s: Can't start transmit-command.\n", dev->name); - } + dev->trans_start = jiffies; + if (!i) { + dev_kfree_skb(skb); } + WAIT_4_SCB_CMD(); + if ((p->scb->status & CU_ACTIVE)) { /* test it, because CU sometimes doesn't start immediately */ + break; + } + if (p->xmit_cmds[0]->cmd_status) { + break; + } + if (i == 15) { + printk(KERN_WARNING "%s: Can't start transmit-command.\n", dev->name); + } + } #else - next_nop = (p->nop_point + 1) & 0x1; - p->xmit_buffs[0]->size = TBD_LAST | len; - - p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; - - p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); - dev->trans_start = jiffies; - p->nop_point = next_nop; - dev_kfree_skb(skb); + next_nop = (p->nop_point + 1) & 0x1; + p->xmit_buffs[0]->size = TBD_LAST | len; + + p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link + = make16((p->nop_cmds[next_nop])); + p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; + + p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); + dev->trans_start = jiffies; + p->nop_point = next_nop; + dev_kfree_skb(skb); #endif #else - p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; - if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) { - next_nop = 0; - } - p->xmit_cmds[p->xmit_count]->cmd_status = 0; - p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->nop_cmds[next_nop]->cmd_status = 0; - + p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; + if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) { + next_nop = 0; + } + p->xmit_cmds[p->xmit_count]->cmd_status = 0; + p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link + = make16((p->nop_cmds[next_nop])); + p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); - dev->trans_start = jiffies; - p->xmit_count = next_nop; - - cli(); - if (p->xmit_count != p->xmit_last) { - dev->tbusy = 0; - } - sti(); - dev_kfree_skb(skb); + dev->trans_start = jiffies; + p->xmit_count = next_nop; + if (p->xmit_count != p->xmit_last) + netif_wake_queue(dev); + dev_kfree_skb(skb); #endif - } return 0; } diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index a741009833f6..9cce2fa76940 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -157,6 +157,7 @@ extern int mc32_probe(struct net_device *dev); static int mc32_probe1(struct net_device *dev, int ioaddr); static int mc32_open(struct net_device *dev); +static void mc32_timeout(struct net_device *dev); static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev); static void mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int mc32_close(struct net_device *dev); @@ -456,6 +457,8 @@ static int __init mc32_probe1(struct net_device *dev, int slot) dev->hard_start_xmit = mc32_send_packet; dev->get_stats = mc32_get_stats; dev->set_multicast_list = mc32_set_multicast_list; + dev->tx_timeout = mc32_timeout; + dev->watchdog_timeo = HZ*5; /* Board does all the work */ lp->rx_halted = 1; lp->tx_halted = 1; @@ -850,10 +853,6 @@ static int mc32_open(struct net_device *dev) u8 one=1; u8 regs; - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - /* * Interrupts enabled */ @@ -902,12 +901,30 @@ static int mc32_open(struct net_device *dev) mc32_rx_begin(dev); mc32_tx_begin(dev); - + + netif_wake_queue(dev); MOD_INC_USE_COUNT; return 0; } +/** + * mc32_timeout: + * @dev: 3c527 that timed out + * + * Handle a timeout on transmit from the 3c527. This normally means + * bad things as the hardware handles cable timeouts and mess for + * us. + * + */ + +static void mc32_timeout(struct net_device *dev) +{ + printk(KERN_WARNING "%s: transmit timed out?\n", dev->name); + /* Try to restart the adaptor. */ + netif_wake_queue(dev); +} + /** * mc32_send_packet: * @skb: buffer to transmit @@ -927,83 +944,56 @@ static int mc32_open(struct net_device *dev) static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev) { struct mc32_local *lp = (struct mc32_local *)dev->priv; - - if (dev->tbusy) { - /* - * If we get here, some higher level has decided we are broken. - * There should really be a "kick me" function call instead. - */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < HZ/20) - return 1; - printk(KERN_WARNING "%s: transmit timed out?\n", dev->name); - /* Try to restart the adaptor. */ - dev->tbusy=0; - dev->trans_start = jiffies; - } - - /* - * Block a timer-based transmit from overlapping. This could better be - * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - { - printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); - dev_kfree_skb(skb); - } - else - { - unsigned long flags; + unsigned long flags; - u16 tx_head; - volatile struct skb_header *p, *np; + u16 tx_head; + volatile struct skb_header *p, *np; - save_flags(flags); - cli(); + netif_stop_queue(dev); + + save_flags(flags); + cli(); - if(atomic_read(&lp->tx_count)==0) - { - dev->tbusy=1; - restore_flags(flags); - return 1; - } - - tx_head = lp->tx_box->data[0]; - atomic_dec(&lp->tx_count); + if(atomic_read(&lp->tx_count)==0) + { + restore_flags(flags); + return 1; + } - /* We will need this to flush the buffer out */ - - lp->tx_skb[lp->tx_skb_end] = skb; - lp->tx_skb_end++; - lp->tx_skb_end&=(TX_RING_MAX-1); - - /* P is the last sending/sent buffer as a pointer */ - p=(struct skb_header *)bus_to_virt(lp->base+tx_head); - - /* NP is the buffer we will be loading */ - np=(struct skb_header *)bus_to_virt(lp->base+p->next); + tx_head = lp->tx_box->data[0]; + atomic_dec(&lp->tx_count); + /* We will need this to flush the buffer out */ + + lp->tx_skb[lp->tx_skb_end] = skb; + lp->tx_skb_end++; + lp->tx_skb_end&=(TX_RING_MAX-1); + + /* P is the last sending/sent buffer as a pointer */ + p=(struct skb_header *)bus_to_virt(lp->base+tx_head); + + /* NP is the buffer we will be loading */ + np=(struct skb_header *)bus_to_virt(lp->base+p->next); - np->control |= (1<<6); /* EOL */ - wmb(); + np->control |= (1<<6); /* EOL */ + wmb(); - np->length = skb->len; + np->length = skb->len; - if(np->length < 60) - np->length = 60; + if(np->length < 60) + np->length = 60; - np->data = virt_to_bus(skb->data); - np->status = 0; - np->control = (1<<7)|(1<<6); /* EOP EOL */ - wmb(); + np->data = virt_to_bus(skb->data); + np->status = 0; + np->control = (1<<7)|(1<<6); /* EOP EOL */ + wmb(); - p->status = 0; - p->control &= ~(1<<6); - - dev->tbusy = 0; /* Keep feeding me */ - - lp->tx_box->mbox=0; - restore_flags(flags); - } + p->status = 0; + p->control &= ~(1<<6); + + lp->tx_box->mbox=0; + restore_flags(flags); + + netif_wake_queue(dev); return 0; } @@ -1139,8 +1129,6 @@ static void mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs) printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq); return; } - dev->interrupt = 1; - ioaddr = dev->base_addr; lp = (struct mc32_local *)dev->priv; @@ -1173,8 +1161,7 @@ static void mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs) lp->tx_skb_top++; lp->tx_skb_top&=(TX_RING_MAX-1); atomic_inc(&lp->tx_count); - dev->tbusy=0; - mark_bh(NET_BH); + netif_wake_queue(dev); break; case 3: /* Halt */ case 4: /* Abort */ @@ -1249,7 +1236,6 @@ static void mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs) if(rx_event) mc32_rx_ring(dev); - dev->interrupt = 0; return; } @@ -1278,6 +1264,8 @@ static int mc32_close(struct net_device *dev) u8 regs; u16 one=1; + netif_stop_queue(dev); + /* * Send the indications on command (handy debug check) */ @@ -1303,9 +1291,6 @@ static int mc32_close(struct net_device *dev) mc32_flush_rx_ring(lp); mc32_flush_tx_ring(lp); - dev->tbusy = 1; - dev->start = 0; - /* Update the statistics here. */ MOD_DEC_USE_COUNT; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index bc155fe23d1b..4710b1d374d4 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1,4 +1,4 @@ -/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */ +/* 3c59x.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */ /* Written 1996-1998 by Donald Becker. @@ -12,10 +12,16 @@ The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O Center of Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 -*/ + + Version history: + 0.99H+lk1.0 - Jeff Garzik + Remove compatibility defines for kernel versions < 2.2.x. + Update for new 2.3.x module interface + + */ static char *version = -"3c59x.c:v0.99H 11/17/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n"; +"3c59x.c:v0.99H+lk1.0 Feb 9, 2000 The Linux Kernel Team http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n"; /* "Knobs" that adjust features and parameters. */ /* Set the copy breakpoint for the copy-only-tiny-frames scheme. @@ -49,22 +55,14 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits; #include #include -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif - #include #include #include #include #include #include +#include #include #include #include @@ -72,9 +70,6 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits; #include #include #include -#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS) -#include -#endif #include /* For NR_IRQS only. */ #include #include @@ -86,35 +81,9 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits; #include -#if (LINUX_VERSION_CODE <= 0x20100) -#ifndef __alpha__ -#define ioremap(a,b) \ - (((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b)) -#define iounmap(v) \ - do { if ((u_long)(v) > 0x100000) vfree(v); } while (0) -#endif -#endif -#if LINUX_VERSION_CODE <= 0x20139 -#define net_device_stats enet_statistics -#define NETSTATS_VER2 -#endif -#if LINUX_VERSION_CODE < 0x20138 -#define test_and_set_bit(val, addr) set_bit(val, addr) -#define le32_to_cpu(val) (val) -#define cpu_to_le32(val) (val) -#endif -#if LINUX_VERSION_CODE < 0x20155 -#define PCI_SUPPORT_VER1 -#else #define PCI_SUPPORT_VER2 -#endif -#if LINUX_VERSION_CODE < 0x20159 -#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE); -#else /* Grrr, unneeded incompatible change. */ #define DEV_FREE_SKB(skb) dev_kfree_skb(skb); -#endif -#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver"); MODULE_PARM(debug, "i"); @@ -125,7 +94,6 @@ MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(compaq_ioaddr, "i"); MODULE_PARM(compaq_irq, "i"); MODULE_PARM(compaq_device_id, "i"); -#endif /* Operational parameter that usually are not changed. */ @@ -229,12 +197,12 @@ struct pci_id_info { const char *name; u16 vendor_id, device_id, device_id_mask, flags; int drv_flags, io_size; - struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt); + struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt); }; enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, }; -static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, int dev_id, int card_idx); +static struct net_device *vortex_probe1(struct pci_dev *pdev, long ioaddr, int irq, int dev_id, int card_idx); static struct pci_id_info pci_tbl[] = { {"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff, @@ -524,7 +492,6 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; /* A list of all installed Vortex devices, for removing the driver module. */ static struct net_device *root_vortex_dev = NULL; -#ifdef MODULE #ifndef CARDBUS /* Variables to work-around the Compaq PCI BIOS32 problem. */ static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900; @@ -538,18 +505,20 @@ static dev_node_t *vortex_attach(dev_locator_t *loc) { u16 dev_id, vendor_id; u32 io; - u8 bus, devfn, irq; + u8 irq; struct net_device *dev; + struct pci_dev *pdev; int chip_idx; if (loc->bus != LOC_PCI) return NULL; - bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; - pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); - pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); - pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id); - pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); + pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn); + if (!pdev) return NULL; + io = pdev->resource[0].start; + irq = pdev->irq; + vendor_id = pdev->vendor; + dev_id = pdev->device; printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n", - bus, devfn, dev_id); + pdev->bus->number, pdev->devfn, dev_id); io &= ~3; if (io == 0 || irq == 0) { printk(KERN_ERR "The 3Com CardBus Ethernet interface was not " @@ -567,7 +536,7 @@ static dev_node_t *vortex_attach(dev_locator_t *loc) "vortex_attach().\n", vendor_id, dev_id); return NULL; } - dev = vortex_probe1(bus, devfn, io, irq, chip_idx, MAX_UNITS+1); + dev = vortex_probe1(pdev, io, irq, chip_idx, MAX_UNITS+1); if (dev) { dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); strcpy(node->dev_name, dev->name); @@ -610,7 +579,7 @@ struct driver_operations vortex_ops = { #endif /* Cardbus support */ -int init_module(void) +static int __init vortex_init_module (void) { if (vortex_debug) printk(KERN_INFO "%s", version); @@ -622,17 +591,6 @@ int init_module(void) #endif } -#else -int tc59x_probe(void) -{ - static int scanned=0; - if(scanned++) - return -ENODEV; - printk(KERN_INFO "%s", version); - return vortex_scan(pci_tbl); -} -#endif /* not MODULE */ - #ifndef CARDBUS static int vortex_scan(struct pci_id_info pci_tbl[]) { @@ -645,7 +603,7 @@ static int vortex_scan(struct pci_id_info pci_tbl[]) be best done a central PCI probe dispatch, which wouldn't work well with the current structure. So instead we detect 3Com cards in slot order. */ - if (pcibios_present()) { + if (pci_present()) { static int pci_index = 0; unsigned char pci_bus, pci_device_fn; @@ -653,15 +611,16 @@ static int vortex_scan(struct pci_id_info pci_tbl[]) u16 vendor, device, pci_command, new_command, pwr_cmd; int chip_idx, irq; long ioaddr; + struct pci_dev *pdev; if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); + pdev = pci_find_slot (pci_bus, pci_device_fn); + if (!pdev) continue; + vendor = pdev->vendor; + device = pdev->device; for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) if (vendor == pci_tbl[chip_idx].vendor_id && (device & pci_tbl[chip_idx].device_id_mask) == @@ -677,21 +636,18 @@ static int vortex_scan(struct pci_id_info pci_tbl[]) } /* Power-up the card. */ - pcibios_read_config_word(pci_bus, pci_device_fn, - 0xe0, &pwr_cmd); + pci_read_config_word(pdev, 0xe0, &pwr_cmd); + if (pwr_cmd & 0x3) { /* Save the ioaddr and IRQ info! */ printk(KERN_INFO " A 3Com network adapter is powered down!" " Setting the power state %4.4x->%4.4x.\n", pwr_cmd, pwr_cmd & ~3); - pcibios_write_config_word(pci_bus, pci_device_fn, - 0xe0, pwr_cmd & ~3); + pci_write_config_word(pdev, 0xe0, pwr_cmd & ~3); printk(KERN_INFO " Setting the IRQ to %d, IOADDR to %#lx.\n", irq, ioaddr); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, irq); - pcibios_write_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, ioaddr); + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, ioaddr); } if (ioaddr == 0) { @@ -706,19 +662,18 @@ static int vortex_scan(struct pci_id_info pci_tbl[]) continue; /* Activate the card. */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; if (pci_command != new_command) { printk(KERN_INFO " The PCI BIOS has not enabled the device " "at %d/%d. Updating PCI command %4.4x->%4.4x.\n", pci_bus, pci_device_fn, pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); + pci_write_config_word(pdev, PCI_COMMAND, new_command); } - dev = vortex_probe1(pci_bus, pci_device_fn, ioaddr, irq, - chip_idx, cards_found); + dev = vortex_probe1(pdev, ioaddr, irq, + chip_idx, cards_found); if (dev) { /* Get and check the latency values. On the 3c590 series @@ -728,14 +683,12 @@ static int vortex_scan(struct pci_id_info pci_tbl[]) u8 pci_latency; u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < new_latency) { printk(KERN_INFO "%s: Overriding PCI latency" " timer (CFLT) setting of %d, new value is %d.\n", dev->name, pci_latency, new_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, new_latency); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency); } dev = 0; cards_found++; @@ -758,27 +711,33 @@ static int vortex_scan(struct pci_id_info pci_tbl[]) device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83); if ((device_id & 0xFF00) != 0x5900) continue; - vortex_probe1(0, 0, ioaddr, inw(ioaddr + 0xC88) >> 12, - 4, cards_found); + vortex_probe1(NULL, ioaddr, inw(ioaddr + 0xC88) >> 12, + 4, cards_found); cards_found++; } } -#ifdef MODULE /* Special code to work-around the Compaq PCI BIOS32 problem. */ if (compaq_ioaddr) { - vortex_probe1(0, 0, compaq_ioaddr, compaq_irq, + vortex_probe1(NULL, compaq_ioaddr, compaq_irq, compaq_device_id, cards_found++); dev = 0; } -#endif return cards_found ? 0 : -ENODEV; } #endif /* ! Cardbus */ -static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, - long ioaddr, int irq, int chip_idx, int card_idx) +/* + * vortex_probe1 - initialize one vortex board, after probing + * has located one during bus scan. + * + * NOTE: pdev==NULL is a valid condition, indicating + * non-PCI (generally EISA) bus device + */ +static struct net_device *vortex_probe1(struct pci_dev *pdev, + long ioaddr, int irq, + int chip_idx, int card_idx) { struct vortex_private *vp; int option; @@ -805,13 +764,13 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, root_vortex_dev = dev; vp->chip_id = chip_idx; - vp->pci_bus = pci_bus; - vp->pci_devfn = pci_devfn; - vp->pdev = pci_find_slot(pci_bus, pci_devfn); + vp->pci_bus = pdev == NULL ? 0 : pdev->bus->number; + vp->pci_devfn = pdev == NULL ? 0 : pdev->devfn; + vp->pdev = pdev; - vp->priv_addr = pci_alloc_consistent(vp->pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE - + sizeof(struct boom_tx_desc) * TX_RING_SIZE - + 15, &vp->ring_dma); + vp->priv_addr = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE + + sizeof(struct boom_tx_desc) * TX_RING_SIZE + + 15, &vp->ring_dma); /* Make sure rings are 16 byte aligned. */ vp->rx_ring = (void *)(((long)vp->priv_addr + 15) & ~15); vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE); @@ -885,8 +844,7 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) { u32 fn_st_addr; /* Cardbus function status space */ - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2, - &fn_st_addr); + fn_st_addr = pdev == NULL ? 0 : pdev->resource[2].start; if (fn_st_addr) vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128); printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee" @@ -1870,9 +1828,6 @@ vortex_close(struct net_device *dev) outl(0, ioaddr + UpListPtr); for (i = 0; i < RX_RING_SIZE; i++) if (vp->rx_skbuff[i]) { -#if LINUX_VERSION_CODE < 0x20100 - vp->rx_skbuff[i]->free = 1; -#endif pci_unmap_single(vp->pdev, le32_to_cpu(vp->rx_ring[i].addr), PKT_BUF_SZ); DEV_FREE_SKB(vp->rx_skbuff[i]); vp->rx_skbuff[i] = 0; @@ -2086,9 +2041,8 @@ static void mdio_write(long ioaddr, int phy_id, int location, int value) return; } - -#ifdef MODULE -void cleanup_module(void) + +static void __exit vortex_cleanup_module (void) { struct net_device *next_dev; @@ -2113,8 +2067,10 @@ void cleanup_module(void) } } -#endif /* MODULE */ - +module_init(vortex_init_module); +module_exit(vortex_cleanup_module); + + /* * Local variables: * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" diff --git a/drivers/net/Config.in b/drivers/net/Config.in index af3fa30a2417..f3eba639f261 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -127,7 +127,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT tristate ' CS89x0 support' CONFIG_CS89x0 tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5 - tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP + tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS tristate ' EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 0231c4e71551..01adff342087 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -46,15 +46,6 @@ else endif endif -ifeq ($(CONFIG_SK98LIN),y) -SUB_DIRS += sk98lin -obj-y += sk98lin/sk98lin.o -else - ifeq ($(CONFIG_SK98LIN),m) - MOD_IN_SUB_DIRS += sk98lin - endif -endif - ifeq ($(CONFIG_TR),y) SUB_DIRS += tokenring MOD_IN_SUB_DIRS += tokenring @@ -103,7 +94,55 @@ else endif endif +# +# link order important here +# +obj-$(CONFIG_PLIP) += plip.o + +obj-$(CONFIG_ROADRUNNER) += rrunner.o + +obj-$(CONFIG_HAPPYMEAL) += sunhme.o +obj-$(CONFIG_SUNLANCE) += sunlance.o +obj-$(CONFIG_SUNQE) += sunqe.o +obj-$(CONFIG_SUNBMAC) += sunbmac.o +obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o + +obj-$(CONFIG_MACE) += mace.o +obj-$(CONFIG_BMAC) += bmac.o +obj-$(CONFIG_GMAC) += gmac.o +obj-$(CONFIG_NCR885E) += ncr885e.o + +obj-$(CONFIG_OAKNET) += oaknet.o 8390.o + +obj-$(CONFIG_DGRS) += dgrs.o +obj-$(CONFIG_RCPCI) += rcpci.o +obj-$(CONFIG_VORTEX) += 3c59x.o +obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o +obj-$(CONFIG_PCNET32) += pcnet32.o +obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o +obj-$(CONFIG_TLAN) += tlan.o +obj-$(CONFIG_TULIP) += tulip.o +obj-$(CONFIG_EPIC100) += epic100.o +obj-$(CONFIG_SIS900) += sis900.o +obj-$(CONFIG_DM9102) += dmfe.o +obj-$(CONFIG_YELLOWFIN) += yellowfin.o +obj-$(CONFIG_ACENIC) += acenic.o + +ifeq ($(CONFIG_SK98LIN),y) +SUB_DIRS += sk98lin +obj-y += sk98lin/sk98lin.o +else + ifeq ($(CONFIG_SK98LIN),m) + MOD_IN_SUB_DIRS += sk98lin + endif +endif + +obj-$(CONFIG_VIA_RHINE) += via-rhine.o +obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o +# +# end link order section +# obj-$(CONFIG_AIRONET4500) += aironet4500_core.o obj-$(CONFIG_AIRONET4500_NONCS) += aironet4500_card.o @@ -124,7 +163,6 @@ obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o obj-$(CONFIG_ARM_ETHERH) += 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o -obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o obj-$(CONFIG_NE2000) += ne.o 8390.o obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o obj-$(CONFIG_HPLAN) += hp.o 8390.o @@ -136,7 +174,6 @@ obj-$(CONFIG_E2100) += e2100.o 8390.o obj-$(CONFIG_ES3210) += es3210.o 8390.o obj-$(CONFIG_LNE390) += lne390.o 8390.o obj-$(CONFIG_NE3210) += ne3210.o 8390.o -obj-$(CONFIG_PLIP) += plip.o # bsd_comp.o is *always* a module, for some documented reason # (licensing). @@ -178,14 +215,8 @@ obj-$(CONFIG_DE620) += de620.o obj-$(CONFIG_AT1500) += lance.o obj-$(CONFIG_LANCE) += lance.o obj-$(CONFIG_SUN3LANCE) += sun3lance.o -obj-$(CONFIG_PCNET32) += pcnet32.o obj-$(CONFIG_DEFXX) += defxx.o -obj-$(CONFIG_SUNLANCE) += sunlance.o obj-$(CONFIG_SGISEEQ) += sgiseeq.o -obj-$(CONFIG_HAPPYMEAL) += sunhme.o -obj-$(CONFIG_SUNQE) += sunqe.o -obj-$(CONFIG_SUNBMAC) += sunbmac.o -obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o obj-$(CONFIG_AT1700) += at1700.o obj-$(CONFIG_FMV18X) += fmv18x.o obj-$(CONFIG_EL1) += 3c501.o @@ -195,19 +226,11 @@ obj-$(CONFIG_SKMC) += sk_mca.o obj-$(CONFIG_ELMC_II) += 3c527.o obj-$(CONFIG_EL3) += 3c509.o obj-$(CONFIG_3C515) += 3c515.o -obj-$(CONFIG_VORTEX) += 3c59x.o obj-$(CONFIG_EEXPRESS) += eexpress.o obj-$(CONFIG_EEXPRESS_PRO) += eepro.o -obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o obj-$(CONFIG_RTL8139) += rtl8139.o -obj-$(CONFIG_SIS900) += sis900.o -obj-$(CONFIG_DM9102) += dmfe.o -obj-$(CONFIG_YELLOWFIN) += yellowfin.o -obj-$(CONFIG_ACENIC) += acenic.o obj-$(CONFIG_WAVELAN) += wavelan.o obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o -obj-$(CONFIG_TLAN) += tlan.o -obj-$(CONFIG_VIA_RHINE) += via-rhine.o obj-$(CONFIG_ZNET) += znet.o obj-$(CONFIG_DEPCA) += depca.o obj-$(CONFIG_EWRK3) += ewrk3.o @@ -221,9 +244,7 @@ obj-$(CONFIG_AC3200) += ac3200.o 8390.o obj-$(CONFIG_APRICOT) += 82596.o obj-$(CONFIG_MVME16x_NET) += 82596.o obj-$(CONFIG_BVME6000_NET) += 82596.o -obj-$(CONFIG_DEC_ELCP) += tulip.o obj-$(CONFIG_ETH16I) += eth16i.o -obj-$(CONFIG_EPIC100) += epic100.o obj-$(CONFIG_ARIADNE2) += ariadne2.o 8390.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o @@ -237,27 +258,18 @@ obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o obj-$(CONFIG_A2065) += a2065.o obj-$(CONFIG_HYDRA) += hydra.o obj-$(CONFIG_ARIADNE) += ariadne.o -obj-$(CONFIG_DGRS) += dgrs.o obj-$(CONFIG_CS89x0) += cs89x0.o obj-$(CONFIG_LTPC) += ltpc.o obj-$(CONFIG_COPS) += cops.o obj-$(CONFIG_IPDDP) += ipddp.o -obj-$(CONFIG_RCPCI) += rcpci.o -obj-$(CONFIG_MACE) += mace.o obj-$(CONFIG_MACSONIC) += macsonic.o obj-$(CONFIG_MACMACE) += macmace.o obj-$(CONFIG_MAC89x0) += mac89x0.o -obj-$(CONFIG_BMAC) += bmac.o -obj-$(CONFIG_GMAC) += gmac.o -obj-$(CONFIG_NCR885E) += ncr885e.o -obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o -obj-$(CONFIG_OAKNET) += oaknet.o 8390.o # # HIPPI adapters # -obj-$(CONFIG_ROADRUNNER) += rrunner.o # Extract lists of the multi-part drivers. # The 'int-*' lists are the intermediate files used to build the multi's. diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c index 975676afec3a..c20ee80a1fc3 100644 --- a/drivers/net/ac3200.c +++ b/drivers/net/ac3200.c @@ -326,9 +326,6 @@ static void ac_block_output(struct net_device *dev, int count, static int ac_close_card(struct net_device *dev) { - dev->start = 0; - dev->tbusy = 1; - if (ei_debug > 1) printk("%s: Shutting down ethercard.\n", dev->name); diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 1329b66c75de..8420b3e07754 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -86,10 +85,6 @@ #define wmb() mb() #endif -#if (LINUX_VERSION_CODE < 0x02030e) -#define net_device device -#endif - #include "acenic.h" /* @@ -393,7 +388,7 @@ fail: return 1; } -int __init acenic_probe(void) +static int __init acenic_probe(void) { int boards_found = 0; int version_disp; @@ -487,11 +482,7 @@ int __init acenic_probe(void) * dev->base_addr since it was means for I/O port * addresses but who gives a damn. */ -#if (LINUX_VERSION_CODE < 0x02030d) - dev->base_addr = pdev->base_address[0]; -#else dev->base_addr = pdev->resource[0].start; -#endif ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); if (!ap->regs){ @@ -575,8 +566,6 @@ int __init acenic_probe(void) } -#ifdef MODULE -#if LINUX_VERSION_CODE > 0x20118 MODULE_AUTHOR("Jes Sorensen "); MODULE_DESCRIPTION("AceNIC/3C985 Gigabit Ethernet driver"); MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); @@ -585,10 +574,9 @@ MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); -#endif -int init_module(void) +static int __init acenic_init_module (void) { int cards; @@ -599,7 +587,7 @@ int init_module(void) } -void cleanup_module(void) +static void __exit acenic_cleanup_module (void) { struct ace_private *ap; struct ace_regs *regs; @@ -681,7 +669,9 @@ void cleanup_module(void) root_dev = next; } } -#endif + +module_init(acenic_init_module); +module_exit(acenic_cleanup_module); /* diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index cc1ce55a7bb1..30aa851b86c4 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -1256,7 +1257,7 @@ static int bmac_reset_and_enable(struct net_device *dev, int enable) return 1; } -int bmac_probe(void) +static int __init bmac_probe (void) { int j, rev; struct bmac_data *bp; @@ -1265,6 +1266,11 @@ int bmac_probe(void) static struct device_node *all_bmacs = NULL, *next_bmac; struct net_device *dev = NULL; +#ifdef MODULE + if(bmac_devs != NULL) + return -EBUSY; +#endif + if (all_bmacs == NULL) { all_bmacs = find_devices("bmac"); is_bmac_plus = 0; @@ -1593,23 +1599,14 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length) return len; } -#ifdef MODULE MODULE_AUTHOR("Randy Gobbel/Paul Mackerras"); MODULE_DESCRIPTION("PowerMac BMAC ethernet driver."); -int init_module(void) -{ - int res; - - if(bmac_devs != NULL) - return -EBUSY; - res = bmac_probe(); - return res; -} -void cleanup_module(void) +static void __exit bmac_cleanup (void) { +#ifdef MODULE struct bmac_data *bp; if (bmac_devs == 0) @@ -1628,6 +1625,8 @@ void cleanup_module(void) #endif kfree(bmac_devs); bmac_devs = NULL; +#endif } -#endif +module_init(bmac_probe); +module_exit(bmac_cleanup); diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c index a6df21d81b7a..7bb5b979696f 100644 --- a/drivers/net/de4x5.c +++ b/drivers/net/de4x5.c @@ -1133,7 +1133,6 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) struct bus_type *lp = &bus; int i, status=0; char *tmp; - dma_addr_t dma_rx_bufs; /* Ensure we're not sleeping */ if (lp->bus == EISA) { @@ -1261,17 +1260,23 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) } #else - dma_rx_bufs = lp->dma_rings + (NUM_RX_DESC + NUM_TX_DESC) - * sizeof(struct de4x5_desc); - dma_rx_bufs = (dma_rx_bufs + ALIGN) & ~ALIGN; - lp->rx_bufs = (char *)(((long)(lp->rx_ring + NUM_RX_DESC - + NUM_TX_DESC) + ALIGN) & ~ALIGN); - for (i=0; irx_ring[i].status = 0; - lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); - lp->rx_ring[i].buf = cpu_to_le32(dma_rx_bufs+i*RX_BUFF_SZ); - lp->rx_ring[i].next = 0; - lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */ + { + dma_addr_t dma_rx_bufs; + + dma_rx_bufs = lp->dma_rings + (NUM_RX_DESC + NUM_TX_DESC) + * sizeof(struct de4x5_desc); + dma_rx_bufs = (dma_rx_bufs + ALIGN) & ~ALIGN; + lp->rx_bufs = (char *)(((long)(lp->rx_ring + NUM_RX_DESC + + NUM_TX_DESC) + ALIGN) & ~ALIGN); + for (i=0; irx_ring[i].status = 0; + lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); + lp->rx_ring[i].buf = + cpu_to_le32(dma_rx_bufs+i*RX_BUFF_SZ); + lp->rx_ring[i].next = 0; + lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */ + } + } #endif diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 1e8a9d3a8827..b42b8d390c12 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -182,9 +182,7 @@ int dgrs_nicmode = 0; /* * Chain of device structures */ -#ifdef MODULE - static struct net_device *dgrs_root_dev = NULL; -#endif +static struct net_device *dgrs_root_dev = NULL; /* * Private per-board data structure (dev->priv) @@ -355,7 +353,7 @@ do_plx_dma( ) { int i; - ulong csr; + ulong csr = 0; DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv; if (pciaddr) @@ -717,7 +715,7 @@ static int dgrs_start_xmit(struct sk_buff *skb, struct net_device *devN) printk("%s: xmit len=%d\n", devN->name, (int) skb->len); devN->trans_start = jiffies; - devN->tbusy = 0; + netif_start_queue(devN); if (priv0->rfdp->cmd & I596_RFD_EL) { /* Out of RFD's */ @@ -790,13 +788,9 @@ no_resources: static int dgrs_open( struct net_device *dev ) { - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); -#ifdef MODULE MOD_INC_USE_COUNT; -#endif return (0); } @@ -806,12 +800,9 @@ dgrs_open( struct net_device *dev ) */ static int dgrs_close( struct net_device *dev ) { - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif return (0); } @@ -940,10 +931,10 @@ static void dgrs_intr(int irq, void *dev_id, struct pt_regs *regs) if (dgrs_nicmode) { for (i = 0; i < priv0->nports; ++i) - priv0->devtbl[i]->tbusy = 0; + netif_wake_queue (priv0->devtbl[i]); } else - dev0->tbusy = 0; + netif_wake_queue (dev0); /* if (bd->flags & TX_QUEUED) DL_sched(bd, bdd); */ } @@ -1451,16 +1442,9 @@ static int __init dgrs_scan(void) return cards_found; } -/* - * Module/driver initialization points. Two ways, depending on - * whether we are a module or statically linked, ala Don Becker's - * 3c59x driver. - */ - -#ifdef MODULE /* - * Variables that can be overriden from command line + * Variables that can be overriden from module command line */ static int debug = -1; static int dma = -1; @@ -1480,8 +1464,7 @@ MODULE_PARM(iptrap, "1-4i"); MODULE_PARM(ipxnet, "i"); MODULE_PARM(nicmode, "i"); -int -init_module(void) +static int __init dgrs_init_module (void) { int cards_found; int i; @@ -1531,8 +1514,7 @@ init_module(void) return cards_found ? 0 : -ENODEV; } -void -cleanup_module(void) +static void __exit dgrs_cleanup_module (void) { while (dgrs_root_dev) { @@ -1560,17 +1542,5 @@ cleanup_module(void) } } -#else - -int __init -dgrs_probe(struct net_device *dev) -{ - int cards_found; - - cards_found = dgrs_scan(); - if (dgrs_debug && cards_found) - printk("dgrs: SW=%s FW=Build %d %s\n", - version, dgrs_firmnum, dgrs_firmdate); - return cards_found ? 0 : -ENODEV; -} -#endif +module_init(dgrs_init_module); +module_exit(dgrs_cleanup_module); diff --git a/drivers/net/dmfe.c b/drivers/net/dmfe.c index 13d76ef2904e..e341ed22638d 100644 --- a/drivers/net/dmfe.c +++ b/drivers/net/dmfe.c @@ -275,7 +275,7 @@ unsigned long CrcTable[256] = }; /* function declaration ------------------------------------- */ -int dmfe_reg_board(void); +static int dmfe_reg_board(void); static int dmfe_open(struct net_device *); static int dmfe_start_xmit(struct sk_buff *, struct net_device *); static int dmfe_stop(struct net_device *); @@ -309,7 +309,7 @@ static unsigned long cal_CRC(unsigned char *, unsigned int); * Search DM910X board, allocate space and register it */ -int __init dmfe_reg_board(void) +static int __init dmfe_reg_board(void) { u32 pci_iobase; u16 dm9102_count = 0; @@ -329,7 +329,6 @@ int __init dmfe_reg_board(void) while ((net_dev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, net_dev))) { u32 pci_id; - u8 pci_cmd; index++; if (pci_read_config_dword(net_dev, PCI_VENDOR_ID, &pci_id) != DMFE_SUCC) @@ -341,15 +340,14 @@ int __init dmfe_reg_board(void) pci_iobase = net_dev->resource[0].start; pci_irqline = net_dev->irq; + if (check_region(pci_iobase, DM9102_IO_SIZE)) /* IO range check */ + continue; + /* Enable Master/IO access, Disable memory access */ + pci_enable_device (net_dev); pci_set_master(net_dev); - pci_read_config_byte(net_dev, PCI_COMMAND, &pci_cmd); - pci_cmd |= PCI_COMMAND_IO; - pci_cmd &= ~PCI_COMMAND_MEMORY; - pci_write_config_byte(net_dev, PCI_COMMAND, pci_cmd); - /* Set Latency Timer 80h */ /* FIXME: setting values > 32 breaks some SiS 559x stuff. @@ -359,22 +357,17 @@ int __init dmfe_reg_board(void) /* IO range and interrupt check */ - if (check_region(pci_iobase, DM9102_IO_SIZE)) /* IO range check */ - continue; - /* Found DM9102 card and PCI resource allocated OK */ dm9102_count++; /* Found a DM9102 card */ /* Init network device */ - dev = init_etherdev(NULL, 0); + dev = init_etherdev(NULL, sizeof(*db)); + if (dev == NULL) + continue; + + db = dev->priv; - /* Allocated board information structure */ - db = (void *) (kmalloc(sizeof(*db), GFP_KERNEL | GFP_DMA)); - if(db==NULL) - continue; /* Out of memory */ - memset(db, 0, sizeof(*db)); - dev->priv = db; /* link device and board info */ db->next_dev = dmfe_root_dev; dmfe_root_dev = dev; @@ -405,10 +398,9 @@ int __init dmfe_reg_board(void) } -#ifdef MODULE if (!dm9102_count) printk(KERN_WARNING "dmfe: Can't find DM910X board\n"); -#endif + return dm9102_count ? 0 : -ENODEV; } @@ -1453,7 +1445,6 @@ static unsigned long cal_CRC(unsigned char *Data, unsigned int Len) } -#ifdef MODULE MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw"); MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver"); @@ -1467,7 +1458,7 @@ MODULE_PARM(chkmode, "i"); * to initilize and register. */ -int init_module(void) +static int __init dmfe_init_module(void) { DMFE_DBUG(0, "init_module() ", debug); @@ -1497,7 +1488,7 @@ int init_module(void) * to un-register device. */ -void cleanup_module(void) +static void __exit dmfe_cleanup_module(void) { struct net_device *next_dev; @@ -1514,4 +1505,5 @@ void cleanup_module(void) DMFE_DBUG(0, "clean_module() exit", 0); } -#endif /* MODULE */ +module_init(dmfe_init_module); +module_exit(dmfe_cleanup_module); diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 7b988f297d76..21236be77fac 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -138,18 +138,6 @@ static const char *version = #include #include #include - - -/* need to remove these asap */ -/* 2.1.xx compatibility macros... */ -/* */ - - -#include - -/* For linux 2.1.xx */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 - #include #include #include @@ -160,16 +148,6 @@ static const char *version = /* udelay(2) */ #define compat_init_data __initdata -#else -/* for 2.x */ - -#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) ) -#define test_and_set_bit(a,b) set_bit((a),(b)) -#define SLOW_DOWN SLOW_DOWN_IO -#define compat_init_data - -#endif - /* First, a few definitions that the brave might change. */ /* A zero-terminated list of I/O addresses to be probed. */ @@ -210,9 +188,8 @@ struct eepro_local { int version; /* a flag to indicate if this is a TX or FX version of the 82595 chip. */ int stepping; -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + spinlock_t lock; /* Serializing lock */ -#endif }; /* The station (ethernet) address prefix, used for IDing the board. */ @@ -299,6 +276,7 @@ struct eepro_local { #define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */ #define ee_id_eepro10p1 0x31 +#define TX_TIMEOUT 40 /* Index to functions, as function prototypes. */ @@ -313,6 +291,7 @@ static void eepro_transmit_interrupt(struct net_device *dev); static int eepro_close(struct net_device *dev); static struct enet_statistics *eepro_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); +static void eepro_tx_timeout (struct net_device *dev); static int read_eeprom(int ioaddr, int location); static void hardware_send_packet(struct net_device *dev, void *buf, short length); @@ -710,14 +689,15 @@ int eepro_probe1(struct net_device *dev, short ioaddr) return -ENOMEM; memset(dev->priv, 0, sizeof(struct eepro_local)); -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 - spin_lock_init(&(((struct eepro_local *)dev->priv)->lock)); -#endif + ((struct eepro_local *)dev->priv)->lock = SPIN_LOCK_UNLOCKED; + dev->open = eepro_open; dev->stop = eepro_close; dev->hard_start_xmit = eepro_send_packet; dev->get_stats = eepro_get_stats; dev->set_multicast_list = &set_multicast_list; + dev->tx_timeout = eepro_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; /* Fill in the fields of the device structure with ethernet generic values */ @@ -969,10 +949,8 @@ static int eepro_open(struct net_device *dev) lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */ lp->tx_last = 0; - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + + netif_start_queue(dev); if (net_debug > 3) printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name); @@ -983,81 +961,53 @@ static int eepro_open(struct net_device *dev) return 0; } -static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev) +static void eepro_tx_timeout (struct net_device *dev) { - struct eepro_local *lp = (struct eepro_local *)dev->priv; + struct eepro_local *lp = (struct eepro_local *) dev->priv; int ioaddr = dev->base_addr; int rcv_ram = dev->mem_end; -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + /* if (net_debug > 1) */ + printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name, + "network cable problem"); + /* This is not a duplicate. One message for the console, + one for the the log file */ + printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name, + "network cable problem"); + lp->stats.tx_errors++; + + /* Try to restart the adaptor. */ + outb (SEL_RESET_CMD, ioaddr); + /* We are supposed to wait for 2 us after a SEL_RESET */ + SLOW_DOWN; + SLOW_DOWN; + + /* Do I also need to flush the transmit buffers here? YES? */ + lp->tx_start = lp->tx_end = rcv_ram; + lp->tx_last = 0; + + dev->trans_start = jiffies; + netif_start_queue (dev); + + outb (RCV_ENABLE_CMD, ioaddr); +} + + +static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev) +{ + struct eepro_local *lp = (struct eepro_local *)dev->priv; unsigned long flags; -#endif if (net_debug > 5) printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name); - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 40) - return 1; - - /* if (net_debug > 1) */ - printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name, - "network cable problem"); - /* This is not a duplicate. One message for the console, - one for the the log file */ - printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name, - "network cable problem"); - lp->stats.tx_errors++; - - /* Try to restart the adaptor. */ - outb(SEL_RESET_CMD, ioaddr); - /* We are supposed to wait for 2 us after a SEL_RESET */ - SLOW_DOWN; - SLOW_DOWN; - - /* Do I also need to flush the transmit buffers here? YES? */ - lp->tx_start = lp->tx_end = rcv_ram; - lp->tx_last = 0; - - dev->tbusy=0; - dev->trans_start = jiffies; - - outb(RCV_ENABLE_CMD, ioaddr); - - } - -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20155 - /* If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself. */ - /* if (skb == NULL) { - dev_tint(dev); - return 0; - }*/ - /* according to A. Cox, this is obsolete since 1.0 */ -#endif - -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 spin_lock_irqsave(&lp->lock, flags); -#endif - - /* Block a timer-based transmit from overlapping. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 - spin_unlock_irqrestore(&lp->lock, flags); -#endif - } else { + { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 lp->stats.tx_bytes+=skb->len; -#endif hardware_send_packet(dev, buf, length); dev->trans_start = jiffies; @@ -1072,9 +1022,7 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev) if (net_debug > 5) printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name); -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 spin_unlock_irqrestore(&lp->lock, flags); -#endif return 0; } @@ -1096,21 +1044,7 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs) return; } -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 spin_lock(&lp->lock); -#endif - - if (dev->interrupt) { - printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); - -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 - spin_unlock(&lp->lock); - /* FIXME : with the lock, could this ever happen ? */ -#endif - - return; - } - dev->interrupt = 1; if (net_debug > 5) printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name); @@ -1143,14 +1077,10 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs) } while ((boguscount-- > 0) && (status & 0x06)); - dev->interrupt = 0; - if (net_debug > 5) printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name); -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 spin_unlock(&lp->lock); -#endif return; } @@ -1161,8 +1091,7 @@ static int eepro_close(struct net_device *dev) int rcv_ram = dev->mem_end; short temp_reg; - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ @@ -1402,12 +1331,6 @@ hardware_send_packet(struct net_device *dev, void *buf, short length) service routines. */ outb(ALL_MASK, ioaddr + INT_MASK_REG); - if (dev->interrupt == 1) { - /* Enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); - continue; - } - /* determine how much of the transmit buffer space is available */ if (lp->tx_end > lp->tx_start) tx_available = XMT_RAM - (lp->tx_end - lp->tx_start); @@ -1484,9 +1407,8 @@ hardware_send_packet(struct net_device *dev, void *buf, short length) lp->tx_last = last; lp->tx_end = end; - if (dev->tbusy) { - dev->tbusy = 0; - } + if (test_bit(LINK_STATE_XOFF, &dev->flags)) + netif_start_queue(dev); /* Enable RX and TX interrupts */ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); @@ -1496,7 +1418,7 @@ hardware_send_packet(struct net_device *dev, void *buf, short length) return; } - dev->tbusy = 1; + netif_stop_queue(dev); if (net_debug > 5) printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name); } @@ -1529,9 +1451,7 @@ eepro_rx(struct net_device *dev) /* Malloc up new buffer. */ struct sk_buff *skb; -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 lp->stats.rx_bytes+=rcv_size; -#endif rcv_size &= 0x3fff; skb = dev_alloc_skb(rcv_size+5); if (skb == NULL) { @@ -1622,8 +1542,7 @@ eepro_transmit_interrupt(struct net_device *dev) xmt_status = inw(ioaddr+IO_PORT); lp->tx_start = inw(ioaddr+IO_PORT); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue (dev); if (xmt_status & 0x2000) lp->stats.tx_packets++; @@ -1650,8 +1569,6 @@ eepro_transmit_interrupt(struct net_device *dev) } } -#ifdef MODULE - #define MAX_EEPRO 8 static char devicename[MAX_EEPRO][9]; static struct net_device dev_eepro[MAX_EEPRO]; @@ -1670,13 +1587,14 @@ static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */ static int n_eepro = 0; /* For linux 2.1.xx */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 + MODULE_AUTHOR("Pascal Dupuis for the 2.1 stuff (locking,...)"); MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver"); MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i"); -#endif + +#ifdef MODULE int init_module(void) diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 95712c29ac88..e651be8a8dda 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -49,9 +49,7 @@ static int multicast_filter_limit = 64; e.g. "options=16" for FD, "options=32" for 100mbps-only. */ static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -#ifdef MODULE static int debug = -1; /* The debug level */ -#endif /* A few values that may be tweaked. */ /* The ring sizes should be a power of two for efficiency. */ @@ -95,6 +93,7 @@ static int debug = -1; /* The debug level */ #endif #endif #include +#include #include #include @@ -103,7 +102,6 @@ static int debug = -1; /* The debug level */ #include #include -#if LINUX_VERSION_CODE > 0x20118 && defined(MODULE) MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver"); MODULE_PARM(debug, "i"); @@ -117,7 +115,6 @@ MODULE_PARM(rxdmacount, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(multicast_filter_limit, "i"); -#endif #define RUN_AT(x) (jiffies + (x)) @@ -642,11 +639,10 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn, int i, option; u16 eeprom[0x100]; int acpi_idle_state = 0; -#ifndef MODULE + static int did_version = 0; /* Already printed version info. */ if (speedo_debug > 0 && did_version++ == 0) printk(version); -#endif pdev = pci_find_slot(pci_bus, pci_devfn); @@ -1838,10 +1834,9 @@ static void set_rx_mode(struct net_device *dev) sp->rx_mode = new_rx_mode; } - -#ifdef MODULE -int init_module(void) + +static int __init eepro100_init_module(void) { int cards_found; @@ -1866,7 +1861,7 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void __exit eepro100_cleanup_module(void) { struct net_device *next_dev; @@ -1890,22 +1885,9 @@ void cleanup_module(void) } } -#else /* not MODULE */ +module_init(eepro100_init_module); +module_exit(eepro100_cleanup_module); -int eepro100_probe(void) -{ - int cards_found = 0; - - cards_found = eepro100_init(); - - /* Only emit the version if the driver is being used. */ - if (speedo_debug > 0 && cards_found) - printk(version); - - return cards_found ? 0 : -ENODEV; -} -#endif /* MODULE */ - /* * Local variables: * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` `[ -f ./pci-netif.h ] && echo -DHAS_PCI_NETIF`" diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index d29532658aa9..c7dfb7a65e20 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -46,17 +46,7 @@ static int max_interrupt_work = 10; #define TX_FIFO_THRESH 256 /* Rounded down to 4 byte units. */ #define RX_FIFO_THRESH 1 /* 0-3, 0==32, 64,96, or 3==128 bytes */ -#include /* Evil, but neccessary */ -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif - #include #include #include @@ -65,11 +55,8 @@ static int max_interrupt_work = 10; #include #include #include -#if LINUX_VERSION_CODE >= 0x20155 +#include #define PCI_SUPPORT_VER2 -#else -#include -#endif #include #include /* Processor type for cache alignment. */ @@ -83,13 +70,8 @@ static int max_interrupt_work = 10; /* Kernel compatibility defines, common to David Hind's PCMCIA package. This is only in the support-all-kernels source code. */ -#if ! defined (LINUX_VERSION_CODE) || LINUX_VERSION_CODE < 0x20000 -#warning This driver version is only for kernel versions 2.0.0 and later. -#endif - #define RUN_AT(x) (jiffies + (x)) -#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115) MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver"); MODULE_PARM(debug, "i"); @@ -97,19 +79,7 @@ MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); -#endif -#if LINUX_VERSION_CODE < 0x20123 -#define test_and_set_bit(val, addr) set_bit(val, addr) -#endif -#if LINUX_VERSION_CODE <= 0x20139 -#define net_device_stats enet_statistics -#define NETSTATS_VER2 -#endif -#if LINUX_VERSION_CODE < 0x20159 -#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE); -#else /* Grrr, unneeded incompatible change. */ #define DEV_FREE_SKB(skb) dev_kfree_skb(skb); -#endif /* The I/O extent. */ #define EPIC_TOTAL_SIZE 0x100 @@ -151,7 +121,7 @@ IVc. Errata /* The rest of these values should never change. */ -static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, +static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq, int chip_id, int card_idx); enum pci_flags_bit { @@ -163,8 +133,9 @@ struct chip_info { const char *name; u16 vendor_id, device_id, device_id_mask, pci_flags; int io_size, min_latency; - struct net_device *(*probe1)(int pci_bus, int pci_devfn, - long ioaddr, int irq, int chip_idx, int fnd_cnt); + struct net_device *(*probe1)(struct pci_dev *pdev, + long ioaddr, int irq, int chip_idx, + int fnd_cnt); } chip_tbl[] = { {"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff, PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1}, @@ -217,6 +188,8 @@ struct epic_private { char devname[8]; /* Used only for kernel debugging. */ const char *product_name; struct net_device *next_module; + + spinlock_t lock; /* Tx and Rx rings here so that they remain paragraph aligned. */ struct epic_rx_desc rx_ring[RX_RING_SIZE]; @@ -273,7 +246,7 @@ static void set_rx_mode(struct net_device *dev); static struct net_device *root_epic_dev = NULL; #ifndef CARDBUS -int epic100_probe(void) +static int __init epic100_probe(void) { int cards_found = 0; int chip_idx, irq; @@ -281,7 +254,6 @@ int epic100_probe(void) unsigned char pci_bus, pci_device_fn; struct net_device *dev; -#ifdef PCI_SUPPORT_VER2 struct pci_dev *pcidev = NULL; while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev)) != NULL) { @@ -300,76 +272,33 @@ int epic100_probe(void) pci_bus = pcidev->bus->number; pci_device_fn = pcidev->devfn; irq = pcidev->irq; -#else - int pci_index; - - if ( ! pcibios_present()) - return -ENODEV; - - for (pci_index = 0; pci_index < 0xff; pci_index++) { - u8 pci_irq_line; - u16 vendor, device; - u32 pci_ioaddr; - - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, - pci_index, &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) - break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); - - for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++) - if (vendor == chip_tbl[chip_idx].vendor_id - && (device & chip_tbl[chip_idx].device_id_mask) == - chip_tbl[chip_idx].device_id) - break; - if (chip_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ - continue; - - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - /* Remove I/O space marker in bit 0. */ - pci_ioaddr &= ~3; - irq = pci_irq_line; - - if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size)) - continue; -#endif /* EPIC-specific code: Soft-reset the chip ere setting as master. */ outl(0x0001, pci_ioaddr + GENCTL); /* Activate the card: fix for brain-damaged Win98 BIOSes. */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); + pci_read_config_word(pcidev, PCI_COMMAND, &pci_command); new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; if (pci_command != new_command) { printk(KERN_INFO " The PCI BIOS has not enabled Ethernet" " device %4.4x-%4.4x." " Updating PCI command %4.4x->%4.4x.\n", vendor, device, pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); + pci_write_config_word(pcidev, PCI_COMMAND, new_command); } - dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, pci_ioaddr, - irq, chip_idx, cards_found); + dev = chip_tbl[chip_idx].probe1(pcidev, pci_ioaddr, irq, + chip_idx, cards_found); /* Check the latency timer. */ if (dev) { u8 pci_latency; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < chip_tbl[chip_idx].min_latency) { printk(KERN_INFO " PCI latency timer (CFLT) value of %d is " "unreasonably low, setting to %d.\n", pci_latency, chip_tbl[chip_idx].min_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, + pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, chip_tbl[chip_idx].min_latency); } dev = 0; @@ -381,8 +310,8 @@ int epic100_probe(void) } #endif /* not CARDBUS */ -static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, - int chip_idx, int card_idx) +static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq, + int chip_idx, int card_idx) { struct epic_private *ep; int i, option = 0, duplex = 0; @@ -444,13 +373,10 @@ static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, i ep->next_module = root_epic_dev; root_epic_dev = dev; - ep->pci_bus = pci_bus; - ep->pci_dev_fn = pci_devfn; -#if defined(PCI_SUPPORT_VER2) - ep->chip_id = pci_find_slot(pci_bus, pci_devfn)->device; -#else - ep->chip_id = chip_tbl[chip_idx].device_id; -#endif + ep->lock = SPIN_LOCK_UNLOCKED; + ep->pci_bus = pdev->bus->number; + ep->pci_dev_fn = pdev->devfn; + ep->chip_id = pdev->device; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but @@ -497,6 +423,8 @@ static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, i dev->get_stats = &epic_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &mii_ioctl; + dev->tx_timeout = epic_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; return dev; } @@ -653,9 +581,7 @@ epic_open(struct net_device *dev) set_rx_mode(dev); outl(0x000A, ioaddr + COMMAND); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170) @@ -864,15 +790,6 @@ epic_start_xmit(struct sk_buff *skb, struct net_device *dev) int entry; u32 flag; - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start < TX_TIMEOUT) - return 1; - epic_tx_timeout(dev); - return 1; - } - /* Caution: the write order is important here, set the base address with the "ownership" bits last. */ @@ -889,13 +806,13 @@ epic_start_xmit(struct sk_buff *skb, struct net_device *dev) if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ flag = 0x10; /* No interrupt */ - clear_bit(0, (void*)&dev->tbusy); + netif_start_queue(dev); } else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) { flag = 0x14; /* Tx-done intr. */ - clear_bit(0, (void*)&dev->tbusy); + netif_start_queue(dev); } else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) { flag = 0x10; /* No Tx-done intr. */ - clear_bit(0, (void*)&dev->tbusy); + netif_start_queue(dev); } else { /* Leave room for two additional entries. */ flag = 0x14; /* Tx-done intr. */ @@ -927,21 +844,7 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) long ioaddr = dev->base_addr; int status, boguscnt = max_interrupt_work; -#if defined(__i386__) - /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ - if (test_and_set_bit(0, (void*)&dev->interrupt)) { - printk(KERN_ERR "%s: SMP simultaneous entry of an interrupt handler.\n", - dev->name); - dev->interrupt = 0; /* Avoid halting machine. */ - return; - } -#else - if (dev->interrupt) { - printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); - return; - } - dev->interrupt = 1; -#endif + spin_lock (&ep->lock); do { status = inl(ioaddr + INTSTAT); @@ -1004,12 +907,12 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) } #endif - if (ep->tx_full && dev->tbusy - && dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) { + if (ep->tx_full && + test_bit(LINK_STATE_XOFF, &dev->flags) && + dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) { /* The ring is no longer full, clear tbusy. */ ep->tx_full = 0; - clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (dev); } ep->dirty_tx = dirty_tx; @@ -1057,12 +960,7 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, inl(ioaddr + INTSTAT)); -#if defined(__i386__) - clear_bit(0, (void*)&dev->interrupt); -#else - dev->interrupt = 0; -#endif - return; + spin_unlock (&ep->lock); } static int epic_rx(struct net_device *dev) @@ -1147,8 +1045,7 @@ static int epic_close(struct net_device *dev) struct epic_private *ep = (struct epic_private *)dev->priv; int i; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); if (epic_debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", @@ -1176,9 +1073,6 @@ static int epic_close(struct net_device *dev) ep->rx_ring[i].buflength = 0; ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */ if (skb) { -#if LINUX_VERSION_CODE < 0x20100 - skb->free = 1; -#endif DEV_FREE_SKB(skb); } } @@ -1202,7 +1096,7 @@ static struct net_device_stats *epic_get_stats(struct net_device *dev) struct epic_private *ep = (struct epic_private *)dev->priv; long ioaddr = dev->base_addr; - if (dev->start) { + if (test_bit(LINK_STATE_START, &dev->state)) { /* Update the error counts. */ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); @@ -1288,12 +1182,12 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) data[0] = ((struct epic_private *)dev->priv)->phys[0] & 0x1f; /* Fall Through */ case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - if (! dev->start) { + if (! test_bit(LINK_STATE_START, &dev->state)) { outl(0x0200, ioaddr + GENCTL); outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); } data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f); - if (! dev->start) { + if (! test_bit(LINK_STATE_START, &dev->state)) { #ifdef notdef outl(0x0008, ioaddr + GENCTL); outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL); @@ -1303,12 +1197,12 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) case SIOCDEVPRIVATE+2: /* Write the specified MII register */ if (!suser()) return -EPERM; - if (! dev->start) { + if (! test_bit(LINK_STATE_START, &dev->state)) { outl(0x0200, ioaddr + GENCTL); outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); } mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]); - if (! dev->start) { + if (! test_bit(LINK_STATE_START, &dev->state)) { #ifdef notdef outl(0x0008, ioaddr + GENCTL); outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL); @@ -1331,13 +1225,15 @@ static dev_node_t *epic_attach(dev_locator_t *loc) u16 dev_id; u32 io; u8 bus, devfn, irq; + struct pci_dev *pdev; if (loc->bus != LOC_PCI) return NULL; - bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; + pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn); + if (!pdev) return NULL; printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn); - pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); - pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); - pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); + io = pdev->resource[0].start; + irq = pdev->irq; + dev_id = pdev->device; io &= ~3; if (io == 0 || irq == 0) { printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not " @@ -1407,10 +1303,8 @@ struct driver_operations epic_ops = { #endif /* Cardbus support */ - -#ifdef MODULE -int init_module(void) +static int __init epic100_init_module(void) { if (epic_debug) printk(KERN_INFO "%s", version); @@ -1423,7 +1317,7 @@ int init_module(void) #endif } -void cleanup_module(void) +static void __exit epic100_cleanup_module(void) { struct net_device *next_dev; @@ -1443,8 +1337,10 @@ void cleanup_module(void) } } -#endif /* MODULE */ - +module_init(epic100_init_module); +module_exit(epic100_cleanup_module); + + /* * Local variables: * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" diff --git a/drivers/net/gmac.c b/drivers/net/gmac.c index 3df9d924f4cd..7ee18bfe90fc 100644 --- a/drivers/net/gmac.c +++ b/drivers/net/gmac.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -78,7 +79,7 @@ static int gmac_tx_cleanup(struct gmac *gm); static void gmac_receive(struct net_device *dev); static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct net_device_stats *gmac_stats(struct net_device *dev); -int gmac_probe(struct net_device *dev); +static int gmac_probe(void); /* Stuff for talking to the physical-layer chip */ static int @@ -502,7 +503,7 @@ static struct net_device_stats *gmac_stats(struct net_device *dev) return &gm->stats; } -int gmac_probe(struct net_device *dev) +static int __init gmac_probe(void) { static int gmacs_found; static struct device_node *next_gmac; @@ -512,6 +513,9 @@ int gmac_probe(struct net_device *dev) unsigned char *addr; int i; + if (gmacs != NULL) + return -EBUSY; + /* * We could (and maybe should) do this using PCI scanning * for vendor/net_device ID 0x106b/0x21. @@ -583,19 +587,11 @@ int gmac_probe(struct net_device *dev) return 0; } -#ifdef MODULE - MODULE_AUTHOR("Paul Mackerras"); MODULE_DESCRIPTION("PowerMac GMAC driver."); -int init_module(void) -{ - if (gmacs != NULL) - return -EBUSY; - return gmac_probe(NULL); -} -void cleanup_module(void) +static void __exit gmac_cleanup_module(void) { struct gmac *gm; @@ -611,4 +607,6 @@ void cleanup_module(void) gmacs = NULL; } -#endif +module_init(gmac_probe); +module_exit(gmac_cleanup_module); + diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 07bc64c78af0..85270f7079b0 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -96,6 +96,7 @@ #include #include #include +#include #include #include @@ -177,6 +178,7 @@ struct hp100_pci_id { struct hp100_private { struct hp100_eisa_id *id; + spinlock_t lock; u_short chip; u_short soft_model; u_int memory_size; @@ -192,7 +194,7 @@ struct hp100_private { struct pci_dev *pci_dev; #endif short mem_mapped; /* memory mapped access */ - u32 *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */ + void *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */ unsigned long mem_ptr_phys; /* physical memory mapped area */ short lan_type; /* 10Mb/s, 100Mb/s or -1 (error) */ int hub_status; /* was login to hub successful? */ @@ -308,7 +310,7 @@ static void hp100_rx( struct net_device *dev ); static hp100_stats_t *hp100_get_stats( struct net_device *dev ); static void hp100_misc_interrupt( struct net_device *dev ); static void hp100_update_stats( struct net_device *dev ); -static void hp100_clear_stats( int ioaddr ); +static void hp100_clear_stats( struct hp100_private *lp, int ioaddr ); static void hp100_set_multicast_list( struct net_device *dev); static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs ); static void hp100_start_interface( struct net_device *dev ); @@ -533,7 +535,7 @@ static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, u_short local_mode, lsw; short mem_mapped; unsigned long mem_ptr_phys; - u32 **mem_ptr_virt; + void **mem_ptr_virt; struct hp100_private *lp; struct hp100_eisa_id *eid; @@ -761,7 +763,7 @@ static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, else { #ifdef HP100_DEBUG - printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to 0x%lx.\n", dev->name, virt_memory_size, mem_ptr_phys, (u_long)mem_ptr_virt); + printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to %p.\n", dev->name, virt_memory_size, mem_ptr_phys, mem_ptr_virt); #endif break; } @@ -792,6 +794,7 @@ static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, lp = (struct hp100_private *)dev->priv; memset( lp, 0, sizeof( struct hp100_private ) ); + lp->lock = SPIN_LOCK_UNLOCKED; lp->id = eid; lp->chip = chip; lp->mode = local_mode; @@ -855,7 +858,7 @@ static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, dev->dev_addr[ i ] = hp100_inb( LAN_ADDR + i ); /* Reset statistics (counters) */ - hp100_clear_stats( ioaddr ); + hp100_clear_stats( lp, ioaddr ); ether_setup( dev ); @@ -914,7 +917,7 @@ static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, dev->name,mem_ptr_phys, (mem_ptr_phys+(mem_ptr_phys>0x100000?(u_long)lp->memory_size:16*1024))-1 ); if ( mem_ptr_virt ) - printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt ); + printk( " (virtual base %p)", mem_ptr_virt ); printk( ".\n" ); /* Set for info when doing ifconfig */ @@ -1252,10 +1255,8 @@ static int hp100_open( struct net_device *dev ) MOD_INC_USE_COUNT; - dev->tbusy = 0; dev->trans_start = jiffies; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); lp->lan_type = hp100_sense_lan( dev ); lp->mac1_mode = HP100_MAC1MODE3; @@ -1291,8 +1292,7 @@ static int hp100_close( struct net_device *dev ) if ( lp->lan_type == HP100_LAN_100 ) lp->hub_status=hp100_login_to_vg_hub( dev, FALSE ); - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); free_irq( dev->irq, dev ); @@ -1724,8 +1724,7 @@ static int hp100_start_xmit_bm( struct sk_buff *skb, struct net_device *dev ) * we have to turn int's off before modifying this, otherwise * a tx_pdl_cleanup could occur at the same time */ - save_flags( flags ); - cli(); + spin_lock_irqsave (&lp->lock, flags); ringptr=lp->txrtail; lp->txrtail=ringptr->next; @@ -1751,7 +1750,7 @@ static int hp100_start_xmit_bm( struct sk_buff *skb, struct net_device *dev ) hp100_outl( ringptr->pdl_paddr, TX_PDA_L ); /* Low Prio. Queue */ lp->txrcommit++; - restore_flags( flags ); + spin_unlock_irqrestore (&lp->lock, flags); /* Update statistics */ lp->stats.tx_packets++; @@ -1931,9 +1930,9 @@ static int hp100_start_xmit( struct sk_buff *skb, struct net_device *dev ) if ( lp->mem_ptr_virt ) /* high pci memory was remapped */ { /* Note: The J2585B needs alignment to 32bits here! */ - memcpy( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 ); + memcpy_toio( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 ); if ( !ok_flag ) - memset( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len ); + memset_io( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len ); } else { @@ -2060,7 +2059,7 @@ static void hp100_rx( struct net_device *dev ) if ( lp->mode==2 ) { if ( lp->mem_ptr_virt ) - memcpy( ptr, lp->mem_ptr_virt, pkt_len ); + memcpy_fromio( ptr, lp->mem_ptr_virt, pkt_len ); /* Note alignment to 32bit transfers */ else isa_memcpy_fromio( ptr, lp->mem_ptr_phys, pkt_len ); @@ -2284,7 +2283,7 @@ static void hp100_misc_interrupt( struct net_device *dev ) lp->stats.tx_errors++; } -static void hp100_clear_stats( int ioaddr ) +static void hp100_clear_stats( struct hp100_private *lp, int ioaddr ) { unsigned long flags; @@ -2293,14 +2292,13 @@ static void hp100_clear_stats( int ioaddr ) printk("hp100: %s: clear_stats\n", dev->name); #endif - save_flags( flags ); - cli(); + spin_lock_irqsave (&lp->lock, flags); hp100_page( MAC_CTRL ); /* get all statistics bytes */ hp100_inw( DROPPED ); hp100_inb( CRC ); hp100_inb( ABORT ); hp100_page( PERFORMANCE ); - restore_flags( flags ); + spin_unlock_irqrestore (&lp->lock, flags); } @@ -2323,8 +2321,7 @@ static void hp100_set_multicast_list( struct net_device *dev ) printk("hp100: %s: set_mc_list\n", dev->name); #endif - save_flags( flags ); - cli(); + spin_lock_irqsave (&lp->lock, flags); hp100_ints_off(); hp100_page( MAC_CTRL ); hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); /* stop rx/tx */ @@ -2457,7 +2454,7 @@ static void hp100_set_multicast_list( struct net_device *dev ) hp100_page( PERFORMANCE ); hp100_ints_on(); - restore_flags( flags ); + spin_unlock_irqrestore (&lp->lock, flags); } @@ -2475,11 +2472,10 @@ static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs ) if ( dev == NULL ) return; ioaddr = dev->base_addr; + + spin_lock (&lp->lock); - if ( dev->interrupt ) - printk( "hp100: %s: re-entering the interrupt handler\n", dev->name ); hp100_ints_off(); - dev->interrupt = 1; /* mark that we are inside the handler */ #ifdef HP100_DEBUG_B hp100_outw( 0x4219, TRACE ); @@ -2501,7 +2497,7 @@ static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs ) if(val==0) /* might be a shared interrupt */ { - dev->interrupt=0; + spin_unlock (&lp->lock); hp100_ints_on(); return; } @@ -2598,8 +2594,8 @@ static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs ) } hp100_misc_interrupt( dev ); } - - dev->interrupt = 0; + + spin_unlock (&lp->lock); hp100_ints_on(); } @@ -2619,8 +2615,7 @@ static void hp100_start_interface( struct net_device *dev ) printk("hp100: %s: hp100_start_interface\n",dev->name); #endif - save_flags( flags ); - cli(); + spin_lock_irqsave (&lp->lock, flags); /* Ensure the adapter does not want to request an interrupt when */ /* enabling the IRQ line to be active on the bus (i.e. not tri-stated) */ @@ -2671,7 +2666,7 @@ static void hp100_start_interface( struct net_device *dev ) /* Enable MAC Tx and RX, set MAC modes, ... */ hp100_set_multicast_list( dev ); - restore_flags( flags ); + spin_unlock_irqrestore (&lp->lock, flags); } diff --git a/drivers/net/ltpc.c b/drivers/net/ltpc.c index 53fe53464495..f572a5ea65b6 100644 --- a/drivers/net/ltpc.c +++ b/drivers/net/ltpc.c @@ -1250,8 +1250,12 @@ int __init ltpc_probe(struct net_device *dev) } /* handles "ltpc=io,irq,dma" kernel command lines */ -void __init ltpc_setup(char *str, int *ints) +static int __init ltpc_setup(char *str) { + int ints[5]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] == 0) { if (str && !strncmp(str, "auto", 4)) { /* do nothing :-) */ @@ -1261,22 +1265,24 @@ void __init ltpc_setup(char *str, int *ints) printk (KERN_ERR "ltpc: usage: ltpc=auto|iobase[,irq[,dma]]\n"); } - return; + return 1; } else { io = ints[1]; if (ints[0] > 1) { irq = ints[2]; - return; + return 1; } if (ints[0] > 2) { dma = ints[3]; - return; + return 1; } /* ignore any other paramters */ } - return; + return 1; } +__setup("ltpc=", ltpc_setup); + #ifdef MODULE static char dev_name[8]; diff --git a/drivers/net/mace.c b/drivers/net/mace.c index 7ad7007b9691..3a69c5c80f9a 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -5,17 +5,15 @@ * Copyright (C) 1996 Paul Mackerras. */ -#ifdef MODULE #include #include -#endif - #include #include #include #include #include #include +#include #include #include #include @@ -101,7 +99,7 @@ bitrev(int b) return d; } -int mace_probe(void) +static int __init mace_probe (void) { int j, rev; struct net_device *dev; @@ -111,6 +109,11 @@ int mace_probe(void) static int maces_found = 0; static struct device_node *next_mace; +#ifdef MODULE + if(mace_devs != NULL) + return -EBUSY; +#endif + if (!maces_found) { next_mace = find_devices("mace"); maces_found = 1; @@ -894,25 +897,13 @@ static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) } } -#ifdef MODULE -#if LINUX_VERSION_CODE > 0x20118 MODULE_AUTHOR("Paul Mackerras"); MODULE_DESCRIPTION("PowerMac MACE driver."); -#endif -int init_module(void) -{ - int res; - - if(mace_devs != NULL) - return -EBUSY; - res = mace_probe(); - return res; -} - -void cleanup_module(void) +static void __exit mace_cleanup (void) { +#ifdef MODULE struct mace_data *mp = (struct mace_data *) mace_devs->priv; unregister_netdev(mace_devs); @@ -922,6 +913,8 @@ void cleanup_module(void) kfree(mace_devs); mace_devs = NULL; +#endif } -#endif +module_init(mace_probe); +module_exit(mace_cleanup); diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 23bb50c64735..3c4e230166c1 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -1094,7 +1094,7 @@ static int __init myri_sbus_match(struct sbus_dev *sdev) return 0; } -int __init myri_sbus_probe(void) +static int __init myri_sbus_probe(void) { struct net_device *dev = NULL; struct sbus_bus *bus; @@ -1102,6 +1102,10 @@ int __init myri_sbus_probe(void) static int called = 0; int cards = 0, v; +#ifdef MODULE + root_myri_dev = NULL; +#endif + if (called) return ENODEV; called++; @@ -1123,18 +1127,9 @@ int __init myri_sbus_probe(void) return 0; } -#ifdef MODULE - -int -init_module(void) -{ - root_myri_dev = NULL; - return myri_sbus_probe(); -} - -void -cleanup_module(void) +static void __exit myri_sbus_cleanup(void) { +#ifdef MODULE /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_myri_dev) { struct myri_eth *next = root_myri_dev->next_module; @@ -1143,6 +1138,8 @@ cleanup_module(void) kfree(root_myri_dev->dev); root_myri_dev = next; } +#endif /* MODULE */ } -#endif /* MODULE */ +module_init(myri_sbus_probe); +module_exit(myri_sbus_cleanup); diff --git a/drivers/net/ncr885e.c b/drivers/net/ncr885e.c index d7c7fb23900e..fd120de2b6a4 100644 --- a/drivers/net/ncr885e.c +++ b/drivers/net/ncr885e.c @@ -14,18 +14,8 @@ static const char *version = "ncr885e.c:v0.8 11/30/98 dan@synergymicro.com\n"; #include - -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif #include #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif - #include #include #include @@ -91,6 +81,8 @@ static const char *chipname = "ncr885e"; int ncr885e_debug = NCR885E_DEBUG; static int print_version = 0; +static int debug = NCR885E_DEBUG; /* module parm */ + struct ncr885e_private { @@ -124,10 +116,7 @@ struct ncr885e_private { spinlock_t lock; }; -#ifdef MODULE static struct net_device *root_dev = NULL; -#endif - static int ncr885e_open( struct net_device *dev ); static int ncr885e_close( struct net_device *dev ); @@ -1169,13 +1158,18 @@ ncr885e_probe1(unsigned long ioaddr, unsigned char irq ) unsigned char *p; int i; + if (!request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name)) + return -EBUSY; + dev = init_etherdev(NULL, 0 ); /* construct private data for the 885 ethernet */ dev->priv = kmalloc( sizeof( struct ncr885e_private ), GFP_KERNEL ); - if ( dev->priv == NULL ) + if ( dev->priv == NULL ) { + release_region( ioaddr, NCR885E_TOTAL_SIZE ); return -ENOMEM; + } sp = (struct ncr885e_private *) dev->priv; memset( sp, 0, sizeof( struct ncr885e_private )); @@ -1198,8 +1192,6 @@ ncr885e_probe1(unsigned long ioaddr, unsigned char irq ) printk(", IRQ %d.\n", irq ); - request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name ); - /* set up a timer */ init_timer( &sp->tx_timeout ); sp->timeout_active = 0; @@ -1216,6 +1208,8 @@ ncr885e_probe1(unsigned long ioaddr, unsigned char irq ) dev->hard_start_xmit = ncr885e_xmit_start; dev->set_multicast_list = ncr885e_set_multicast; dev->set_mac_address = ncr885e_set_address; + + root_dev = dev; return 0; } @@ -1226,13 +1220,16 @@ ncr885e_probe1(unsigned long ioaddr, unsigned char irq ) * worry about the rest. */ -int __init ncr885e_probe(void) +static int __init ncr885e_probe(void) { struct pci_dev *pdev = NULL; unsigned int ioaddr, chips = 0; unsigned short cmd; unsigned char irq, latency; + if ( debug >= 0) + ncr885e_debug = debug; + while(( pdev = pci_find_device( PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885_ETHERNET, pdev )) != NULL ) { @@ -1416,26 +1413,12 @@ write_mii( unsigned long ioaddr, int reg, int data ) #endif /* NCR885E_DEBUG_MII */ -#ifdef MODULE -#if defined(LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20118 MODULE_AUTHOR("dan@synergymicro.com"); MODULE_DESCRIPTION("Symbios 53C885 Ethernet driver"); MODULE_PARM(debug, "i"); -#endif -static int debug = 1; -int -init_module(void) -{ - if ( debug >= 0) - ncr885e_debug = debug; - - return ncr885e_probe(); -} - -void -cleanup_module(void) +static void __exit ncr885e_cleanup (void) { struct ncr885e_private *np; @@ -1448,7 +1431,10 @@ cleanup_module(void) root_dev = NULL; } } -#endif /* MODULE */ + +module_init(ncr885e_probe); +module_exit(ncr885e_cleanup); + /* * Local variables: diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 58573948c2db..477db0958039 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -606,9 +606,8 @@ static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, i if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d][intr:%ld].\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + "[DMAstat:%d][irqlock:%d].\n", + dev->name, ei_status.dmaing, ei_status.irqlock); return; } @@ -646,9 +645,8 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d][intr:%ld].\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + "[DMAstat:%d][irqlock:%d].\n", + dev->name, ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; @@ -721,9 +719,8 @@ static void ne_block_output(struct net_device *dev, int count, if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d][intr:%ld]\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + "[DMAstat:%d][irqlock:%d]\n", + dev->name, ei_status.dmaing, ei_status.irqlock); return; } ei_status.dmaing |= 0x01; diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index 01f1e2ea7938..f6929905e08d 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -104,7 +104,7 @@ pci_clone_list[] __initdata = { #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ -int ne2k_pci_probe(void); +static int ne2k_pci_probe(void); static struct net_device *ne2k_pci_probe1(long ioaddr, int irq, int chip_idx); static int ne2k_pci_open(struct net_device *dev); @@ -129,10 +129,7 @@ struct ne2k_pci_card { /* A list of all installed devices, for removing the driver module. */ static struct ne2k_pci_card *ne2k_card_list = NULL; -#ifdef MODULE - -int -init_module(void) +static int __init ne2k_pci_init_module(void) { /* We must emit version information. */ if (debug) @@ -146,8 +143,7 @@ init_module(void) return 0; } -void -cleanup_module(void) +static void __exit ne2k_pci_cleanup_module(void) { struct net_device *dev; struct ne2k_pci_card *this_card; @@ -165,7 +161,8 @@ cleanup_module(void) unlock_8390_module(); } -#endif /* MODULE */ +module_init(ne2k_pci_init_module); +module_exit(ne2k_pci_cleanup_module); /* NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet @@ -185,7 +182,7 @@ struct netdev_entry netcard_drv = {"ne2k_pci", ne2k_pci_probe1, NE_IO_EXTENT, 0}; #endif -int __init ne2k_pci_probe(void) +static int __init ne2k_pci_probe(void) { struct pci_dev *pdev = NULL; int cards_found = 0; @@ -216,13 +213,11 @@ int __init ne2k_pci_probe(void) if (check_region(pci_ioaddr, NE_IO_EXTENT)) continue; -#ifndef MODULE { static unsigned version_printed = 0; if (version_printed++ == 0) printk(KERN_INFO "%s", version); } -#endif /* Activate the card: fix for brain-damaged Win98 BIOSes. */ new_command = pci_command | PCI_COMMAND_IO; diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 5df1c9ffac19..9a81ff0f73fc 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -186,7 +186,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) { static unsigned version_printed = 0; int i; - unsigned int data; + unsigned int data = 0; int boguscount = 40; /* diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index fc24bd1ee4f7..5c671a4ea39d 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -808,7 +808,7 @@ static int ni65_lance_reinit(struct net_device *dev) */ static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs) { - int csr0; + int csr0 = 0; struct net_device *dev = dev_id; struct priv *p; int bcnt = 32; diff --git a/drivers/net/oaknet.c b/drivers/net/oaknet.c index 3cd09fc30f6e..1f6243f9f684 100644 --- a/drivers/net/oaknet.c +++ b/drivers/net/oaknet.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -52,9 +53,7 @@ static const char *name = "National DP83902AV"; -#if defined(MODULE) -static struct net_device *oaknet_devs; -#endif +static struct net_device *oaknet_devs = NULL; /* Function Prototypes */ @@ -91,8 +90,7 @@ static void oaknet_dma_error(struct net_device *dev, const char *name); * 0 if OK, otherwise system error number on error. * */ -int -oaknet_init(void) +static int __init oaknet_init(void) { register int i; int reg0, regd; @@ -112,10 +110,15 @@ oaknet_init(void) tmp.base_addr = ioaddr; dev = &tmp; + if (!request_region(OAKNET_IO_BASE, OAKNET_IO_SIZE, name)) + return -EBUSY; + /* Quick register check to see if the device is really there. */ - if ((reg0 = ei_ibp(ioaddr)) == 0xFF) + if ((reg0 = ei_ibp(ioaddr)) == 0xFF) { + release_region(OAKNET_IO_BASE, OAKNET_IO_SIZE); return (ENODEV); + } /* * That worked. Now a more thorough check, using the multicast @@ -136,6 +139,7 @@ oaknet_init(void) ei_obp(regd, ioaddr + 0x0D); dev->base_addr = 0; + release_region(dev->base_addr, OAKNET_IO_SIZE); return (ENODEV); } @@ -144,8 +148,10 @@ oaknet_init(void) * sure its symbols are loaded. */ - if (load_8390_module("oaknet.c")) + if (load_8390_module("oaknet.c")) { + release_region(dev->base_addr, OAKNET_IO_SIZE); return (-ENOSYS); + } /* * We're not using the old-style probing API, so we have to allocate @@ -153,9 +159,7 @@ oaknet_init(void) */ dev = init_etherdev(0, 0); -#if defined(MODULE) oaknet_devs = dev; -#endif /* * This controller is on an embedded board, so the base address @@ -169,6 +173,7 @@ oaknet_init(void) if (ethdev_init(dev)) { printk(" unable to get memory for dev->priv.\n"); + release_region(dev->base_addr, OAKNET_IO_SIZE); return (-ENOMEM); } @@ -186,12 +191,10 @@ oaknet_init(void) printk("%s: unable to request interrupt %d.\n", dev->name, dev->irq); kfree(dev->priv); - dev->priv = NULL; + release_region(dev->base_addr, OAKNET_IO_SIZE); return (EAGAIN); } - request_region(dev->base_addr, OAKNET_IO_SIZE, name); - /* Tell the world about what and where we've found. */ printk("%s: %s at", dev->name, name); @@ -666,12 +669,10 @@ oaknet_dma_error(struct net_device *dev, const char *name) return; } -#if defined(MODULE) /* * Oak Ethernet module load interface. */ -int -init_module(void) +static int __init oaknet_init_module (void) { int status; @@ -680,7 +681,8 @@ init_module(void) status = oaknet_init() - lock_8390_module(); + if (status == 0) + lock_8390_module(); return (status); } @@ -688,8 +690,7 @@ init_module(void) /* * Oak Ethernet module unload interface. */ -void -cleanup_module(void) +static void __exit oaknet_cleanup_module (void) { if (oaknet_devs == NULL) return; @@ -706,7 +707,7 @@ cleanup_module(void) oaknet_devs = NULL; unlock_8390_module(); - - return; } -#endif /* MODULE */ + +module_init(oaknet_init_module); +module_exit(oaknet_cleanup_module); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index dcd45ca795b4..b9a013111722 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -43,9 +43,7 @@ static unsigned int pcnet32_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, static int pcnet32_debug = 1; static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */ -#ifdef MODULE static struct net_device *pcnet32_dev = NULL; -#endif static const int max_interrupt_work = 80; static const int rx_copybreak = 200; @@ -273,17 +271,16 @@ struct pcnet32_private { #endif full_duplex:1, /* full duplex possible */ mii:1; /* mii port available */ -#ifdef MODULE struct net_device *next; -#endif }; -int pcnet32_probe(void); +static int pcnet32_probe(void); static int pcnet32_probe1(unsigned long, unsigned char, int, int); static int pcnet32_open(struct net_device *); static int pcnet32_init_ring(struct net_device *); static int pcnet32_start_xmit(struct sk_buff *, struct net_device *); static int pcnet32_rx(struct net_device *); +static void pcnet32_tx_timeout (struct net_device *dev); static void pcnet32_interrupt(int, void *, struct pt_regs *); static int pcnet32_close(struct net_device *); static struct net_device_stats *pcnet32_get_stats(struct net_device *); @@ -433,7 +430,7 @@ static struct pcnet32_access pcnet32_dwio = { -int __init pcnet32_probe(void) +static int __init pcnet32_probe(void) { unsigned long ioaddr = 0; // FIXME dev ? dev->base_addr: 0; unsigned int irq_line = 0; // FIXME dev ? dev->irq : 0; @@ -754,12 +751,11 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car #ifdef HAVE_PRIVATE_IOCTL dev->do_ioctl = &pcnet32_mii_ioctl; #endif + dev->tx_timeout = pcnet32_tx_timeout; + dev->watchdog_timeo = (HZ >> 1); - -#ifdef MODULE lp->next = pcnet32_dev; pcnet32_dev = dev; -#endif /* Fill in the generic fields of the device structure. */ ether_setup(dev); @@ -852,9 +848,8 @@ pcnet32_open(struct net_device *dev) lp->a.write_csr (ioaddr, 4, 0x0915); lp->a.write_csr (ioaddr, 0, 0x0001); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); + i = 0; while (i++ < 100) if (lp->a.read_csr (ioaddr, 0) & 0x0100) @@ -963,20 +958,14 @@ pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) lp->a.write_csr (ioaddr, 0, csr0_bits); } -static int -pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) + +static void +pcnet32_tx_timeout (struct net_device *dev) { struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; unsigned int ioaddr = dev->base_addr; - u16 status; - int entry; - unsigned long flags; /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < HZ/2) - return 1; printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name, lp->a.read_csr (ioaddr, 0)); lp->a.write_csr (ioaddr, 0, 0x0004); @@ -998,24 +987,25 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) } pcnet32_restart(dev, 0x0042); - dev->tbusy = 0; dev->trans_start = jiffies; - dev_kfree_skb(skb); - return 0; - } + netif_start_queue(dev); +} + + +static int +pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; + unsigned int ioaddr = dev->base_addr; + u16 status; + int entry; + unsigned long flags; if (pcnet32_debug > 3) { printk("%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", dev->name, lp->a.read_csr (ioaddr, 0)); } - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } - spin_lock_irqsave(&lp->lock, flags); /* Default status -- will not enable Successful-TxDone @@ -1059,7 +1049,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) - clear_bit (0, (void *)&dev->tbusy); + netif_start_queue(dev); else lp->tx_full = 1; spin_unlock_irqrestore(&lp->lock, flags); @@ -1087,11 +1077,6 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) spin_lock(&lp->lock); - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - dev->interrupt = 1; - rap = lp->a.read_rap(ioaddr); while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) { /* Acknowledge all of the current interrupt sources ASAP. */ @@ -1167,12 +1152,12 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) dirty_tx += TX_RING_SIZE; } #endif - if (lp->tx_full && dev->tbusy - && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + if (lp->tx_full && + test_bit(LINK_STATE_XOFF, &dev->flags) && + dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { /* The ring is no longer full, clear tbusy. */ lp->tx_full = 0; - clear_bit(0, (void *)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (dev); } lp->dirty_tx = dirty_tx; } @@ -1213,10 +1198,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) printk("%s: exiting interrupt, csr0=%#4.4x.\n", dev->name, lp->a.read_csr (ioaddr, 0)); - dev->interrupt = 0; - spin_unlock(&lp->lock); - return; } static int @@ -1317,8 +1299,7 @@ pcnet32_close(struct net_device *dev) struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; int i; - dev->start = 0; - set_bit (0, (void *)&dev->tbusy); + netif_stop_queue(dev); lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); @@ -1478,21 +1459,20 @@ static int pcnet32_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } #endif /* HAVE_PRIVATE_IOCTL */ -#ifdef MODULE MODULE_PARM(debug, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(tx_start_pt, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); - +MODULE_AUTHOR("Thomas Bogendoerfer"); +MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards"); /* An additional parameter that may be passed in... */ static int debug = -1; static int tx_start_pt = -1; -int -init_module(void) +static int __init pcnet32_init_module(void) { if (debug > 0) pcnet32_debug = debug; @@ -1503,8 +1483,7 @@ init_module(void) return pcnet32_probe(); } -void -cleanup_module(void) +static void __exit pcnet32_cleanup_module(void) { struct net_device *next_dev; @@ -1518,10 +1497,10 @@ cleanup_module(void) pcnet32_dev = next_dev; } } -#endif /* MODULE */ +module_init(pcnet32_init_module); +module_exit(pcnet32_cleanup_module); - /* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c pcnet32.c" diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 1058341b681c..75a7038868df 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -160,7 +160,6 @@ static int plip_hard_header_cache(struct neighbour *neigh, static int plip_open(struct net_device *dev); static int plip_close(struct net_device *dev); static struct net_device_stats *plip_get_stats(struct net_device *dev); -static int plip_config(struct net_device *dev, struct ifmap *map); static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int plip_preempt(void *handle); static void plip_wakeup(void *handle); @@ -1256,9 +1255,7 @@ MODULE_PARM(timid, "1i"); static struct net_device *dev_plip[PLIP_MAX] = { NULL, }; -#ifdef MODULE -void -cleanup_module(void) +static void __exit plip_cleanup_module (void) { int i; @@ -1278,14 +1275,16 @@ cleanup_module(void) } } -#define plip_init init_module - -#else /* !MODULE */ +#ifndef MODULE static int parport_ptr = 0; -void plip_setup(char *str, int *ints) +static void __init plip_setup(char *str) { + int ints[4]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + /* Ugh. */ if (!strncmp(str, "parport", 7)) { int n = simple_strtoul(str+7, NULL, 10); @@ -1307,7 +1306,9 @@ void plip_setup(char *str, int *ints) } } -#endif /* MODULE */ +__setup("plip=", plip_setup); + +#endif /* !MODULE */ static int inline plip_searchfor(int list[], int a) @@ -1319,8 +1320,7 @@ plip_searchfor(int list[], int a) return 0; } -int __init -plip_init(void) +static int __init plip_init (void) { struct parport *pb = parport_enumerate(); int i=0; @@ -1375,7 +1375,10 @@ plip_init(void) } return 0; } - + +module_init(plip_init); +module_exit(plip_cleanup_module); + /* * Local variables: * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -g -fomit-frame-pointer -pipe -c plip.c" diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c index 746455bf0b59..396e783c59d9 100644 --- a/drivers/net/rcpci45.c +++ b/drivers/net/rcpci45.c @@ -52,13 +52,13 @@ static char *version = #include -#include #include #include #include #include #include #include +#include #include #include #include @@ -67,14 +67,7 @@ static char *version = #include /* For NR_IRQS only. */ #include #include - -#if LINUX_VERSION_CODE >= 0x020100 -#define LINUX_2_1 -#endif - -#ifdef LINUX_2_1 #include -#endif #include #include @@ -91,11 +84,6 @@ static char *version = #define NEW_MULTICAST #include -#ifndef LINUX_2_1 -#define ioremap vremap -#define iounmap vfree -#endif - /* PCI/45 Configuration space values */ #define RC_PCI45_VENDOR_ID 0x4916 #define RC_PCI45_DEVICE_ID 0x1960 @@ -178,11 +166,7 @@ static int RC_allocate_and_post_buffers(struct net_device *, int); /* A list of all installed RC devices, for removing the driver module. */ static struct net_device *root_RCdev = NULL; -#ifdef MODULE -int init_module(void) -#else -int rcpci_probe(void) -#endif +static int __init rcpci_init_module (void) { int cards_found; @@ -562,11 +546,7 @@ RCxmit_callback(U32 Status, printk("rc: skb = 0x%x\n", (uint)skb); #endif BufferContext++; -#ifdef LINUX_2_1 dev_kfree_skb (skb); -#else - dev_kfree_skb (skb, FREE_WRITE); -#endif } dev->tbusy = 0; @@ -727,18 +707,10 @@ RCrecv_callback(U32 Status, while(PktCount--) { skb = (struct sk_buff *)PacketDescBlock[0]; -#ifndef LINUX_2_1 - skb->free = 1; - skb->lock = 0; -#endif #ifdef RCDEBUG printk("free skb 0x%p\n", skb); #endif -#ifdef LINUX_2_1 dev_kfree_skb (skb); -#else - dev_kfree_skb(skb, FREE_READ); -#endif pDpa->numOutRcvBuffers--; PacketDescBlock += BD_SIZE; /* point to next context field */ } @@ -777,12 +749,7 @@ RCrecv_callback(U32 Status, if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR) { printk("rc: RCrecv_callback: post buffer failed!\n"); -#ifdef LINUX_2_1 dev_kfree_skb (skb); -#else - skb->free = 1; - dev_kfree_skb(skb, FREE_READ); -#endif } else { @@ -1089,17 +1056,8 @@ static int RCioctl(struct net_device *dev, struct ifreq *rq, int cmd) case RCU_COMMAND: { -#ifdef LINUX_2_1 if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser))) return -EFAULT; -#else - int error; - error=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(RCuser)); - if (error) { - return error; - } - memcpy_fromfs(&RCuser, rq->ifr_data, sizeof(RCuser)); -#endif #ifdef RCDEBUG printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd); @@ -1208,11 +1166,7 @@ static int RCioctl(struct net_device *dev, struct ifreq *rq, int cmd) RCUD_DEFAULT -> rc = 0x11223344; break; } -#ifdef LINUX_2_1 copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser)); -#else - memcpy_tofs(rq->ifr_data, &RCuser, sizeof(RCuser)); -#endif break; } /* RCU_COMMAND */ @@ -1243,9 +1197,7 @@ static int RCconfig(struct net_device *dev, struct ifmap *map) } -#ifdef MODULE -void -cleanup_module(void) +static void __exit rcpci_cleanup_module (void) { PDPA pDpa; struct net_device *next; @@ -1273,7 +1225,9 @@ cleanup_module(void) root_RCdev = next; } } -#endif + +module_init(rcpci_init_module); +module_exit(rcpci_clenaup_module); static int @@ -1356,17 +1310,10 @@ RC_allocate_and_post_buffers(struct net_device *dev, int numBuffers) while(p[0]) { skb = (struct sk_buff *)pB->context; -#ifndef LINUX_2_1 - skb->free = 1; -#endif #ifdef RCDEBUG printk("rc: freeing 0x%x\n", (uint)skb); #endif -#ifdef LINUX_2_1 dev_kfree_skb (skb); -#else - dev_kfree_skb(skb, FREE_READ); -#endif p[0]--; pB++; } diff --git a/drivers/net/setup.c b/drivers/net/setup.c index f57b97d491c6..29a63e1aa863 100644 --- a/drivers/net/setup.c +++ b/drivers/net/setup.c @@ -8,7 +8,6 @@ #include #include -extern int plip_init(void); extern int mkiss_init_ctrl_dev(void); extern int ppp_init(void); extern int slip_init_ctrl_dev(void); @@ -21,44 +20,16 @@ extern int dmascc_init(void); extern int scc_init(void); extern int yam_init(void); -extern int acenic_probe(void); extern int awc4500_pci_probe(void); extern int awc4500_isa_probe(void); extern int awc4500_pnp_probe(void); extern int awc4500_365_probe(void); extern int arcnet_init(void); -extern int bigmac_probe(void); -extern int bmac_probe(void); -extern int gmac_probe(void); extern int cpm_enet_init(void); -extern int oaknet_init(void); extern int dlci_setup(void); -extern int dgrs_probe(void); -extern int dmfe_reg_board(void); -extern int eepro100_probe(void); -extern int epic100_probe(void); -extern int happy_meal_probe(void); extern int lapbeth_init(void); -extern int mace_probe(void); -extern int myri_sbus_probe(void); -extern int ncr885e_probe(void); -extern int ne2k_pci_probe(void); -extern int pcnet32_probe(void); -extern int qec_probe(void); -extern int rcpci_probe(void); -extern int rr_hippi_probe(void); -extern int rtl8139_probe(void); extern int sdla_setup(void); extern int sdla_c_setup(void); -extern int sis900_probe(void); -extern int skge_probe(void); -extern int sparc_lance_probe(void); -extern int starfire_probe(void); -extern int tc59x_probe(void); -extern int tlan_probe(void); -extern int tulip_probe(void); -extern int via_rhine_probe(void); -extern int yellowfin_probe(void); extern int abyss_probe(void); extern int madgemc_probe(void); @@ -106,9 +77,6 @@ struct net_probe pci_probes[] __initdata = { #if defined(CONFIG_LAPBETHER) {lapbeth_init, 0}, #endif -#if defined(CONFIG_PLIP) - {plip_init, 0}, -#endif #if defined(CONFIG_ARCNET) {arcnet_init, 0}, #endif @@ -127,117 +95,6 @@ struct net_probe pci_probes[] __initdata = { {slhc_install, 0}, #endif #endif -/* - * HIPPI - */ -#ifdef CONFIG_ROADRUNNER - {rr_hippi_probe, 0}, -#endif - -/* - * ETHERNET - */ - -/* - * SBUS Ethernet - */ - -#ifdef CONFIG_HAPPYMEAL - {happy_meal_probe, 0}, -#endif -#ifdef CONFIG_SUNLANCE - {sparc_lance_probe, 0}, -#endif -#ifdef CONFIG_SUNQE - {qec_probe, 0}, -#endif -#ifdef CONFIG_SUNBMAC - {bigmac_probe, 0}, -#endif -#ifdef CONFIG_MYRI_SBUS - {myri_sbus_probe, 0}, -#endif - -/* - * PowerPC Mainboard - */ - -#ifdef CONFIG_MACE - {mace_probe, 0}, -#endif -#ifdef CONFIG_BMAC - {bmac_probe, 0}, -#endif -#ifdef CONFIG_GMAC - {gmac_probe, 0}, -#endif -#ifdef CONFIG_NCR885E - {ncr885e_probe, 0}, -#endif - -/* - * IBM "Oak" Evaluation board - */ -#ifdef CONFIG_OAKNET - {oaknet_init, 0}, -#endif - -/* - * PCI Ethernet - */ -#ifdef CONFIG_DGRS - {dgrs_probe, 0}, -#endif -#ifdef CONFIG_RCPCI - {rcpci_probe, 0}, -#endif -#ifdef CONFIG_VORTEX - {tc59x_probe, 0}, -#endif -#ifdef CONFIG_NE2K_PCI - {ne2k_pci_probe, 0}, -#endif -#ifdef CONFIG_PCNET32 - {pcnet32_probe, 0}, -#endif -#ifdef CONFIG_EEXPRESS_PRO100 /* Intel EtherExpress Pro/100 */ - {eepro100_probe, 0}, -#endif -#ifdef CONFIG_TLAN - {tlan_probe, 0}, -#endif -#ifdef CONFIG_DEC_ELCP - {tulip_probe, 0}, -#endif -#ifdef CONFIG_EPIC100 - {epic100_probe, 0}, -#endif -#ifdef CONFIG_RTL8139 - {rtl8139_probe, 0}, -#endif -#ifdef CONFIG_SIS900 - {sis900_probe, 0}, -#endif - -#ifdef CONFIG_DM9102 - {dmfe_reg_board, 0}, -#endif - -#ifdef CONFIG_YELLOWFIN - {yellowfin_probe, 0}, -#endif -#ifdef CONFIG_ACENIC - {acenic_probe, 0}, -#endif -#ifdef CONFIG_SK98LIN - {skge_probe, 0}, -#endif -#ifdef CONFIG_VIA_RHINE - {via_rhine_probe, 0}, -#endif -#ifdef CONFIG_ADAPTEC_STARFIRE - {starfire_probe, 0}, -#endif /* * diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 228803fb0768..60d73069934a 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -112,6 +113,8 @@ struct sis900_private { struct net_device *next_module; struct net_device_stats stats; struct pci_dev * pci_dev; + + spinlock_t lock; struct mac_chip_info * mac; struct mii_phy * mii; @@ -131,15 +134,11 @@ struct sis900_private { int LinkOn; }; -#ifdef MODULE -#if LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Jim Huang "); MODULE_DESCRIPTION("SiS 900 PCI Fast Ethernet driver"); MODULE_PARM(multicast_filter_limit, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(debug, "i"); -#endif -#endif static int sis900_open(struct net_device *net_dev); static int sis900_mii_probe (struct net_device * net_dev); @@ -167,18 +166,16 @@ static void sis900_reset(struct net_device *net_dev); static struct net_device *root_sis900_dev = NULL; /* walk through every ethernet PCI devices to see if some of them are matched with our card list*/ -int sis900_probe (struct net_device * net_dev) +static int __init sis900_probe (void) { int found = 0; struct pci_dev * pci_dev = NULL; - if (!pci_present()) - return -ENODEV; - while ((pci_dev = pci_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_dev)) != NULL) { /* pci_dev contains all ethernet devices */ u32 pci_io_base; struct mac_chip_info * mac; + struct net_device *net_dev = NULL; for (mac = mac_chip_table; mac->vendor_id; mac++) { /* try to match our card list */ @@ -198,6 +195,7 @@ int sis900_probe (struct net_device * net_dev) continue; /* setup various bits in PCI command register */ + pci_enable_device (pci_dev); pci_set_master(pci_dev); /* do the real low level jobs */ @@ -258,6 +256,7 @@ static struct net_device * sis900_mac_probe (struct mac_chip_info * mac, struct net_dev->irq = irq; sis_priv->pci_dev = pci_dev; sis_priv->mac = mac; + sis_priv->lock = SPIN_LOCK_UNLOCKED; /* probe for mii transciver */ if (sis900_mii_probe(net_dev) == 0) { @@ -277,6 +276,8 @@ static struct net_device * sis900_mac_probe (struct mac_chip_info * mac, struct net_dev->get_stats = &sis900_get_stats; net_dev->set_multicast_list = &set_rx_mode; net_dev->do_ioctl = &mii_ioctl; + net_dev->tx_timeout = sis900_tx_timeout; + net_dev->watchdog_timeo = TX_TIMEOUT; return net_dev; } @@ -506,9 +507,7 @@ sis900_open(struct net_device *net_dev) set_rx_mode(net_dev); - net_dev->tbusy = 0; - net_dev->interrupt = 0; - net_dev->start = 1; + netif_start_queue(net_dev); /* Enable all known interrupts by setting the interrupt mask. */ outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr); @@ -811,7 +810,8 @@ static void sis900_tx_timeout(struct net_device *net_dev) } net_dev->trans_start = jiffies; - net_dev->tbusy = sis_priv->tx_full = 0; + sis_priv->tx_full = 0; + netif_start_queue(net_dev); /* FIXME: Should we restart the transmission thread here ?? */ @@ -827,13 +827,6 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev) long ioaddr = net_dev->base_addr; unsigned int entry; - /* test tbusy to see if we have timeout situation then set it */ - if (test_and_set_bit(0, (void*)&net_dev->tbusy) != 0) { - if (jiffies - net_dev->trans_start > TX_TIMEOUT) - sis900_tx_timeout(net_dev); - return 1; - } - /* Calculate the next Tx descriptor entry. */ entry = sis_priv->cur_tx % NUM_TX_DESC; sis_priv->tx_skbuff[entry] = skb; @@ -846,7 +839,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev) if (++sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC) { /* Typical path, clear tbusy to indicate more transmission is possible */ - clear_bit(0, (void*)&net_dev->tbusy); + netif_start_queue(net_dev); } else { /* no more transmit descriptor avaiable, tbusy remain set */ sis_priv->tx_full = 1; @@ -867,26 +860,12 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev) static void sis900_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *net_dev = (struct net_device *)dev_instance; + struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; int boguscnt = max_interrupt_work; long ioaddr = net_dev->base_addr; u32 status; -#if defined(__i386__) - /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ - if (test_and_set_bit(0, (void*)&net_dev->interrupt)) { - printk(KERN_INFO "%s: SMP simultaneous entry of " - "an interrupt handler.\n", net_dev->name); - net_dev->interrupt = 0; /* Avoid halting machine. */ - return; - } -#else - if (net_dev->interrupt) { - printk(KERN_INFO "%s: Re-entering the interrupt handler.\n", - net_dev->name); - return; - } - net_dev->interrupt = 1; -#endif + spin_lock (&sis_priv->lock); do { status = inl(ioaddr + isr); @@ -923,11 +902,7 @@ static void sis900_interrupt(int irq, void *dev_instance, struct pt_regs *regs) "interrupt status = 0x%#8.8x.\n", net_dev->name, inl(ioaddr + isr)); -#if defined(__i386__) - clear_bit(0, (void*)&net_dev->interrupt); -#else - net_dev->interrupt = 0; -#endif + spin_unlock (&sis_priv->lock); return; } @@ -1079,13 +1054,12 @@ static void sis900_finish_xmit (struct net_device *net_dev) sis_priv->tx_ring[entry].cmdsts = 0; } - if (sis_priv->tx_full && net_dev->tbusy && + if (sis_priv->tx_full && test_bit(LINK_STATE_XOFF, &net_dev->flags) && sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) { /* The ring is no longer full, clear tbusy, tx_full and schedule more transmission by marking NET_BH */ sis_priv->tx_full = 0; - clear_bit(0, (void *)&net_dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (net_dev); } } @@ -1096,8 +1070,7 @@ sis900_close(struct net_device *net_dev) struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; int i; - net_dev->start = 0; - net_dev->tbusy = 1; + netif_stop_queue(net_dev); /* Disable interrupts by clearing the interrupt mask. */ outl(0x0000, ioaddr + imr); @@ -1264,14 +1237,7 @@ static void sis900_reset(struct net_device *net_dev) outl(PESEL, ioaddr + cfg); } -#ifdef MODULE -int init_module(void) -{ - return sis900_probe(NULL); -} - -void -cleanup_module(void) +static void __exit sis900_cleanup_module(void) { /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_sis900_dev) { @@ -1289,4 +1255,5 @@ cleanup_module(void) } } -#endif /* MODULE */ +module_init(sis900_probe); +module_exit(sis900_cleanup_module); diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 7e834bd7b3fb..d7ed239a46fd 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -228,6 +228,7 @@ static const char SysKonnectBuildNumber[] = "@(#)SK-BUILD: 3.02 (19991111) PL: 01"; #include +#include #include "h/skdrv1st.h" #include "h/skdrv2nd.h" @@ -341,13 +342,14 @@ static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; * 0, if everything is ok * !=0, on error */ -int __init skge_probe (struct net_device *dev) +static int __init skge_probe (void) { -int boards_found = 0; -int version_disp = 0; -SK_AC *pAC; -struct pci_dev *pdev = NULL; -unsigned long base_address; + int boards_found = 0; + int version_disp = 0; + SK_AC *pAC; + struct pci_dev *pdev = NULL; + unsigned long base_address; + struct net_device *dev = NULL; if (probed) return -ENODEV; @@ -375,21 +377,12 @@ unsigned long base_address; } dev = init_etherdev(dev, sizeof(SK_AC)); - if (dev == NULL){ + if (dev == NULL || dev->priv == NULL){ printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); break; } - if (!dev->priv) - dev->priv = kmalloc(sizeof(SK_AC), GFP_KERNEL); - if (dev->priv == NULL){ - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } - - memset(dev->priv, 0, sizeof(SK_AC)); pAC = dev->priv; @@ -471,14 +464,7 @@ unsigned long base_address; * or more boards. Otherwise, return failure (-ENODEV). */ -#ifdef MODULE return boards_found; -#else - if (boards_found > 0) - return 0; - else - return -ENODEV; -#endif } /* skge_probe */ @@ -515,8 +501,6 @@ SK_AC *pAC; } /* FreeResources */ -#ifdef MODULE - MODULE_AUTHOR("Christoph Goos "); MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver"); MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); @@ -533,8 +517,6 @@ MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i"); MODULE_PARM(debug, "i"); -#endif // MODULE - #ifdef AUTO_NEG_A static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A; @@ -597,15 +579,13 @@ static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", }; #endif -#ifdef MODULE - static int debug = 0; /* not used */ static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */ /***************************************************************************** * - * init_module - module initialization function + * skge_init_module - module initialization function * * Description: * Very simple, only call skge_probe and return approriate result. @@ -614,9 +594,9 @@ static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */ * 0, if everything is ok * !=0, on error */ -int init_module(void) +static int __init skge_init_module(void) { -int cards; + int cards; root_dev = NULL; @@ -624,17 +604,17 @@ int cards; debug = 0; options[0] = 0; - cards = skge_probe(NULL); + cards = skge_probe(); if (cards == 0) { printk("No adapter found\n"); } return cards ? 0 : -ENODEV; -} /* init_module */ +} /* skge_init_module */ /***************************************************************************** * - * cleanup_module - module unload function + * skge_cleanup_module - module unload function * * Description: * Disable adapter if it is still running, free resources, @@ -642,7 +622,7 @@ int cards; * * Returns: N/A */ -void cleanup_module(void) +static void __exit skge_cleanup_module(void) { SK_AC *pAC; struct net_device *next; @@ -687,9 +667,10 @@ SK_EVPARA EvPara; root_dev = next; } -} -#endif /* cleanup_module */ +} /* skge_cleanup_module */ +module_init(skge_init_module); +module_exit(skge_cleanup_module); /***************************************************************************** * diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c index 9c57cb2691e4..24dd1ff1c1f5 100644 --- a/drivers/net/sk_g16.c +++ b/drivers/net/sk_g16.c @@ -69,6 +69,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 @@ -455,6 +456,8 @@ struct priv static SK_RAM *board; /* pointer to our memory mapped board components */ +static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED; + /* Macros */ @@ -939,11 +942,7 @@ static int SK_open(struct net_device *dev) if (!(i = SK_lance_init(dev, 0))) /* LANCE init OK? */ { - - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); #ifdef SK_DEBUG @@ -979,7 +978,6 @@ static int SK_open(struct net_device *dev) PRINTK(("## %s: LANCE init failed: CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0))); - dev->start = 0; /* Device not ready */ return -EAGAIN; } @@ -1176,7 +1174,7 @@ static int SK_send_packet(struct sk_buff *skb, struct net_device *dev) struct priv *p = (struct priv *) dev->priv; struct tmd *tmdp; - if (dev->tbusy) + if (test_bit(LINK_STATE_XOFF, &dev->flags)) { /* if Transmitter more than 150ms busy -> time_out */ @@ -1190,7 +1188,7 @@ static int SK_send_packet(struct sk_buff *skb, struct net_device *dev) SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */ - dev->tbusy = 0; /* Clear Transmitter flag */ + netif_start_queue(dev); /* Clear Transmitter flag */ dev->trans_start = jiffies; /* Mark Start of transmission */ @@ -1205,12 +1203,10 @@ static int SK_send_packet(struct sk_buff *skb, struct net_device *dev) * This means check if we are already in. */ - if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) /* dev->tbusy already set ? */ - { - printk("%s: Transmitter access conflict.\n", dev->name); - } - else + netif_stop_queue (dev); + { + /* Evaluate Packet length */ short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; @@ -1248,11 +1244,13 @@ static int SK_send_packet(struct sk_buff *skb, struct net_device *dev) * We own next buffer and are ready to transmit, so * clear busy flag */ - dev->tbusy = 0; + netif_start_queue(dev); } p->stats.tx_bytes += skb->len; + } + dev_kfree_skb(skb); return 0; } /* End of SK_send_packet */ @@ -1290,16 +1288,10 @@ static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs) printk("SK_interrupt(): IRQ %d for unknown device.\n", irq); } - - if (dev->interrupt) - { - printk("%s: Re-entering the interrupt handler.\n", dev->name); - } + spin_lock (&SK_lock); csr0 = SK_read_reg(CSR0); /* store register for checking */ - dev->interrupt = 1; /* We are handling an interrupt */ - /* * Acknowledge all of the current interrupt sources, disable * Interrupts (INEA = 0) @@ -1329,7 +1321,7 @@ static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs) SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */ - dev->interrupt = 0; /* We are out */ + spin_unlock (&SK_lock); } /* End of SK_interrupt() */ @@ -1430,14 +1422,7 @@ static void SK_txintr(struct net_device *dev) * We mark transmitter not busy anymore, because now we have a free * transmit descriptor which can be filled by SK_send_packet and * afterwards sent by the LANCE - */ - - dev->tbusy = 0; - - /* - * mark_bh(NET_BH); - * This will cause net_bh() to run after this interrupt handler. - * + * * The function which do handle slow IRQ parts is do_bottom_half() * which runs at normal kernel priority, that means all interrupt are * enabled. (see kernel/irq.c) @@ -1450,7 +1435,7 @@ static void SK_txintr(struct net_device *dev) * - try to transmit something from the send queue */ - mark_bh(NET_BH); + netif_wake_queue(dev); } /* End of SK_txintr() */ @@ -1625,8 +1610,7 @@ static int SK_close(struct net_device *dev) PRINTK(("## %s: SK_close(). CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0))); - dev->tbusy = 1; /* Transmitter busy */ - dev->start = 0; /* Card down */ + netif_stop_queue(dev); /* Transmitter busy */ printk("%s: Shutting %s down CSR0 %#06x\n", dev->name, SK_NAME, (int) SK_read_reg(CSR0)); @@ -2005,9 +1989,6 @@ void SK_print_dev(struct net_device *dev, char *text) printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n", dev->name, dev->base_addr, dev->irq); - printk("## FLAGS: start: %d tbusy: %ld int: %ld\n", - dev->start, dev->tbusy, dev->interrupt); - printk("## next device: %#08x init function: %#08x\n", (int) dev->next, (int) dev->init); } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 4f0e291fdd41..30e9e5b3dc37 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -68,19 +68,8 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #error You must compile this driver with "-O". #endif -/* Include files, designed to support most kernel versions 2.0.0 and later. */ -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif - #include -#include #include #include #include @@ -92,6 +81,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -101,7 +91,6 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #define RUN_AT(x) (jiffies + (x)) -#ifdef MODULE MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); MODULE_PARM(max_interrupt_work, "i"); @@ -111,7 +100,6 @@ MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif /* Theory of Operation @@ -407,9 +395,6 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) unsigned char pci_bus, pci_device_fn; struct net_device *dev; - if ( ! pcibios_present()) - return -ENODEV; - for (;pci_index < 0xff; pci_index++) { struct pci_dev *pdev; u16 vendor, device, pci_command, new_command; @@ -421,28 +406,24 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); + pdev = pci_find_slot (pci_bus, pci_device_fn); + if (!pdev) continue; + vendor = pdev->vendor; + device = pdev->device; for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) if (vendor == pci_tbl[chip_idx].vendor_id && (device & pci_tbl[chip_idx].device_id_mask) == pci_tbl[chip_idx].device_id) break; - if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ + if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ continue; - pdev = pci_find_slot(pci_bus, pci_device_fn); - - { - pciaddr = pdev->resource[0].start; + pciaddr = pdev->resource[0].start; #if defined(ADDR_64BITS) && defined(__alpha__) - pciaddr |= ((long)pdev->base_address[1]) << 32; + pciaddr |= ((long)pdev->base_address[1]) << 32; #endif - irq = pdev->irq; - } + irq = pdev->irq; if (debug > 2) printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n", @@ -458,15 +439,13 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) continue; } - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); new_command = pci_command | (pci_tbl[chip_idx].flags & 7); if (pci_command != new_command) { printk(KERN_INFO " The PCI BIOS has not enabled the" " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", pci_bus, pci_device_fn, pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); + pci_write_config_word(pdev, PCI_COMMAND, new_command); } dev = pci_tbl[chip_idx].probe1(pdev, pci_bus, pci_device_fn, ioaddr, @@ -474,14 +453,12 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) if (dev && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) { u8 pci_latency; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < min_pci_latency) { printk(KERN_INFO " PCI latency timer (CFLT) is " "unreasonably low at %d. Setting to %d clocks.\n", pci_latency, min_pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, min_pci_latency); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency); } } cards_found++; @@ -490,21 +467,15 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) return cards_found ? 0 : -ENODEV; } -int starfire_probe(void) -{ - if (pci_etherdev_probe(pci_tbl) < 0) - return -ENODEV; - printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); - return 0; -} - - static struct net_device * starfire_probe1(struct pci_dev *pdev, int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_id, int card_idx) { struct netdev_private *np; int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0; - struct net_device *dev = init_etherdev(NULL, sizeof(struct netdev_private)); + struct net_device *dev = init_etherdev(NULL, 0); + + if (!dev) + return NULL; printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr); @@ -991,7 +962,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) skb->len); /* Scavenge the descriptor. */ - dev_kfree_skb(skb); + kfree_skb(skb); np->tx_info[entry].skb = NULL; np->tx_info[entry].mapping = 0; np->dirty_tx++; @@ -1185,10 +1156,8 @@ static struct enet_statistics *get_stats(struct net_device *dev) /* We should lock this segment of code for SMP eventually, although the vulnerability window is very small and statistics are non-critical. */ -#if LINUX_VERSION_CODE > 0x20119 np->stats.tx_bytes = readl(ioaddr + 0x57010); np->stats.rx_bytes = readl(ioaddr + 0x57044); -#endif np->stats.tx_packets = readl(ioaddr + 0x57000); np->stats.tx_aborted_errors = readl(ioaddr + 0x57024) + readl(ioaddr + 0x57028); @@ -1356,7 +1325,7 @@ static int netdev_close(struct net_device *dev) np->rx_ring[i].rxaddr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ if (np->rx_info[i].skb != NULL) { pci_unmap_single(np->pdev, np->rx_info[i].mapping, np->rx_buf_sz); - dev_kfree_skb(np->rx_info[i].skb); + kfree_skb(np->rx_info[i].skb); } np->rx_info[i].skb = NULL; np->rx_info[i].mapping = 0; @@ -1367,7 +1336,7 @@ static int netdev_close(struct net_device *dev) pci_unmap_single(np->pdev, np->tx_info[i].mapping, skb->len); - dev_kfree_skb(skb); + kfree_skb(skb); } np->tx_info[i].skb = NULL; np->tx_info[i].mapping = 0; @@ -1378,9 +1347,7 @@ static int netdev_close(struct net_device *dev) return 0; } - -#ifdef MODULE -int init_module(void) +static int __init starfire_init_module (void) { if (debug) /* Emit version even if no cards detected. */ printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); @@ -1396,7 +1363,7 @@ int init_module(void) #endif } -void cleanup_module(void) +static void __exit starfire_cleanup_module (void) { struct net_device *next_dev; @@ -1428,8 +1395,10 @@ void cleanup_module(void) } } -#endif /* MODULE */ - +module_init(starfire_init_module); +module_exit(starfire_cleanup_module); + + /* * Local variables: * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c starfire.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index ad9a1f7c76b1..11efd3d4da74 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -1251,7 +1251,7 @@ static int __init bigmac_match(struct sbus_dev *sdev) return 1; } -int __init bigmac_probe(void) +static int __init bigmac_probe(void) { struct net_device *dev = NULL; struct sbus_bus *sbus; @@ -1259,6 +1259,10 @@ int __init bigmac_probe(void) static int called = 0; int cards = 0, v; +#ifdef MODULE + root_bigmac_dev = NULL; +#endif + if (called) return ENODEV; called++; @@ -1280,18 +1284,9 @@ int __init bigmac_probe(void) return 0; } -#ifdef MODULE - -int -init_module(void) -{ - root_bigmac_dev = NULL; - return bigmac_probe(); -} - -void -cleanup_module(void) +static void __exit bigmac_cleanup(void) { +#ifdef MODULE /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_bigmac_dev) { struct bigmac *bp = root_bigmac_dev; @@ -1310,6 +1305,8 @@ cleanup_module(void) kfree(bp->dev); root_bigmac_dev = bp_nxt; } +#endif /* MODULE */ } -#endif /* MODULE */ +module_init(bigmac_probe); +module_exit(bigmac_cleanup); diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 2c628ba9557f..8766c1dc4b07 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2910,12 +2910,16 @@ static int __init happy_meal_pci_probe(struct net_device *dev) } #endif -int __init happy_meal_probe(void) +static int __init happy_meal_probe(void) { struct net_device *dev = NULL; static int called = 0; int cards; +#ifdef MODULE + root_happy_dev = NULL; +#endif + if (called) return ENODEV; called++; @@ -2934,18 +2938,10 @@ int __init happy_meal_probe(void) return 0; } -#ifdef MODULE - -int -init_module(void) -{ - root_happy_dev = NULL; - return happy_meal_probe(); -} -void -cleanup_module(void) +static void __exit cleanup_module(void) { +#ifdef MODULE /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_happy_dev) { struct happy_meal *hp = root_happy_dev; @@ -2976,6 +2972,8 @@ cleanup_module(void) kfree(hp->dev); root_happy_dev = next; } +#endif /* MODULE */ } -#endif /* MODULE */ +module_init(happy_meal_probe); +module_exit(happy_meal_cleanup_module); diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index ba2a62858ab5..c7630dba3c53 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1519,11 +1519,15 @@ static inline struct sbus_dma *find_ledma(struct sbus_dev *sdev) #include /* Find all the lance cards on the system and initialize them */ -int __init sparc_lance_probe(void) +static int __init sparc_lance_probe(void) { static struct sbus_dev sdev; static int called = 0; +#ifdef MODULE + root_lance_dev = NULL; +#endif + if (called) return ENODEV; called++; @@ -1541,7 +1545,7 @@ int __init sparc_lance_probe(void) #else /* !CONFIG_SUN4 */ /* Find all the lance cards on the system and initialize them */ -int __init sparc_lance_probe(void) +static int __init sparc_lance_probe(void) { struct sbus_bus *bus; struct sbus_dev *sdev = 0; @@ -1550,6 +1554,10 @@ int __init sparc_lance_probe(void) static int called = 0; int cards = 0, v; +#ifdef MODULE + root_lance_dev = NULL; +#endif + if (called) return ENODEV; called++; @@ -1587,18 +1595,9 @@ int __init sparc_lance_probe(void) } #endif /* !CONFIG_SUN4 */ -#ifdef MODULE - -int -init_module(void) -{ - root_lance_dev = NULL; - return sparc_lance_probe(); -} - -void -cleanup_module(void) +static void __exit sparc_lance_cleanup(void) { +#ifdef MODULE struct lance_private *lp; while (root_lance_dev) { @@ -1609,6 +1608,8 @@ cleanup_module(void) kfree(root_lance_dev->dev); root_lance_dev = lp; } +#endif /* MODULE */ } -#endif /* MODULE */ +module_init(sparc_lance_probe); +module_exit(sparc_lance_cleanup); diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 15221ecbc34d..ed538b5a7ef8 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -986,7 +986,7 @@ static int __init qec_match(struct sbus_dev *sdev) return 1; } -int __init qec_probe(void) +static int __init qec_probe(void) { struct net_device *dev = NULL; struct sbus_bus *bus; @@ -994,6 +994,10 @@ int __init qec_probe(void) static int called = 0; int cards = 0, v; +#ifdef MODULE + root_qec_dev = NULL; +#endif + if (called) return ENODEV; called++; @@ -1015,18 +1019,9 @@ int __init qec_probe(void) return 0; } -#ifdef MODULE - -int -init_module(void) -{ - root_qec_dev = NULL; - return qec_probe(); -} - -void -cleanup_module(void) +static void __exit qec_cleanup(void) { +#ifdef MODULE struct sunqec *next_qec; int i; @@ -1054,6 +1049,8 @@ cleanup_module(void) kfree(root_qec_dev); root_qec_dev = next_qec; } +#endif /* MODULE */ } -#endif /* MODULE */ +module_init(qec_probe); +module_exit(qec_cleanup); diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index acdc4fbfb581..9b21a13ea54b 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -89,16 +89,12 @@ static int aui = 0; static int duplex = 0; static int speed = 0; -#ifdef MODULE - MODULE_PARM(aui, "i"); MODULE_PARM(duplex, "i"); MODULE_PARM(speed, "i"); MODULE_PARM(debug, "i"); EXPORT_NO_SYMBOLS; -#endif - /* Turn on debugging. See linux/Documentation/networking/tlan.txt for details */ static int debug = 0; @@ -314,7 +310,7 @@ TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type ) **************************************************************/ -void __exit tlan_exit(void) +static void __exit tlan_exit(void) { struct net_device *dev; TLanPrivateInfo *priv; @@ -355,7 +351,7 @@ void __exit tlan_exit(void) * **************************************************************/ -int __init tlan_probe(void) +static int __init tlan_probe(void) { struct net_device *dev; @@ -645,9 +641,7 @@ int TLan_Open( struct net_device *dev ) return -EAGAIN; } - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); /* NOTE: It might not be necessary to read the stats before a reset if you don't care what the values are. @@ -704,7 +698,7 @@ int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) { TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail ); - dev->tbusy = 1; + netif_stop_queue(dev); priv->txBusyCount++; return 1; } @@ -799,10 +793,6 @@ void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs) priv = (TLanPrivateInfo *) dev->priv; spin_lock(&priv->lock); - if ( dev->interrupt ) { - printk( "TLAN: Re-entering interrupt handler for %s: %ld.\n" , dev->name, dev->interrupt ); - } - dev->interrupt++; host_int = inw( dev->base_addr + TLAN_HOST_INT ); outw( host_int, dev->base_addr + TLAN_HOST_INT ); @@ -816,7 +806,6 @@ void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs) outl( host_cmd, dev->base_addr + TLAN_HOST_CMD ); } - dev->interrupt--; spin_unlock(&priv->lock); } /* TLan_HandleInterrupts */ @@ -843,8 +832,7 @@ int TLan_Close(struct net_device *dev) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); TLan_ReadAndClearStats( dev, TLAN_RECORD ); outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD ); @@ -1058,7 +1046,7 @@ u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int ) priv->stats.tx_bytes += head_list->frameSize; head_list->cStat = TLAN_CSTAT_UNUSED; - dev->tbusy = 0; + netif_start_queue(dev); CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS ); if ( eoc ) { TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail ); @@ -1367,7 +1355,7 @@ u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int ) TLan_FreeLists( dev ); TLan_ResetLists( dev ); TLan_ResetAdapter( dev ); - dev->tbusy = 0; + netif_start_queue(dev); ack = 0; } else { TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name ); @@ -2377,9 +2365,7 @@ int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val ) outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR); sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO; - if ( dev->interrupt == 0 ) - spin_lock_irqsave(&priv->lock, flags); - dev->interrupt++; + spin_lock_irqsave(&priv->lock, flags); TLan_MiiSync(dev->base_addr); @@ -2426,10 +2412,7 @@ int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val ) *val = tmp; - dev->interrupt--; - if ( dev->interrupt == 0 ) - spin_unlock_irqrestore(&priv->lock, flags); - + spin_unlock_irqrestore(&priv->lock, flags); return err; } /* TLan_MiiReadReg */ @@ -2546,9 +2529,7 @@ void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val ) outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR); sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO; - if ( dev->interrupt == 0 ) - spin_lock_irqsave(&priv->lock, flags); - dev->interrupt++; + spin_lock_irqsave(&priv->lock, flags); TLan_MiiSync( dev->base_addr ); @@ -2570,10 +2551,7 @@ void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val ) if ( minten ) TLan_SetBit( TLAN_NET_SIO_MINTEN, sio ); - dev->interrupt--; - if ( dev->interrupt == 0 ) - spin_unlock_irqrestore(&priv->lock, flags); - + spin_unlock_irqrestore(&priv->lock, flags); } /* TLan_MiiWriteReg */ @@ -2774,9 +2752,7 @@ int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data ) unsigned long flags = 0; int ret=0; - if ( dev->interrupt == 0 ) - spin_lock_irqsave(&priv->lock, flags); - dev->interrupt++; + spin_lock_irqsave(&priv->lock, flags); TLan_EeSendStart( dev->base_addr ); err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK ); @@ -2799,11 +2775,9 @@ int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data ) goto fail; } TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP ); -fail: - dev->interrupt--; - if ( dev->interrupt == 0 ) - spin_unlock_irqrestore(&priv->lock, flags); +fail: + spin_unlock_irqrestore(&priv->lock, flags); return ret; } /* TLan_EeReadByte */ diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index cd353e3f4e2b..5e4093b1492e 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -3684,13 +3684,7 @@ int __init smctr_probe (struct net_device *dev) int ioaddr = smctr_portlist[i]; if(check_region(ioaddr, SMCTR_IO_EXTENT)) continue; - if(smctr_probe1(dev, ioaddr)) - { -#ifndef MODULE - tr_freedev(dev); -#endif - } - else + if (!smctr_probe1(dev, ioaddr)) return (0); } diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c index 278b5e3d4da9..fa4e9dc62bb8 100644 --- a/drivers/net/tulip.c +++ b/drivers/net/tulip.c @@ -75,6 +75,7 @@ static int rx_copybreak = 100; #include #include #include +#include #include /* Processor type for cache alignment. */ #include @@ -101,10 +102,6 @@ static int rx_copybreak = 100; #define IRQ(irq, dev_id, pt_regs) (irq, pt_regs) #endif -#if (LINUX_VERSION_CODE < 0x20123) -#define test_and_set_bit(val, addr) set_bit(val, addr) -#endif - /* This my implementation of shared IRQs, now only used for 1.2.13. */ #ifdef HAVE_SHARED_IRQ #define USE_SHARED_IRQ @@ -368,11 +365,7 @@ struct tulip_private { u32 setup_frame[48]; /* Pseudo-Tx frame to init address table. */ int chip_id; int revision; -#if LINUX_VERSION_CODE > 0x20139 struct net_device_stats stats; -#else - struct enet_statistics stats; -#endif struct timer_list timer; /* Media selection timer. */ spinlock_t tx_lock; unsigned int cur_rx, cur_tx; /* The next free ring entry */ @@ -432,7 +425,7 @@ static struct net_device *root_tulip_dev = NULL; This allows the probe routine to use the old driver initialization interface. */ -int tulip_probe(void) +static int __init tulip_probe(void) { int cards_found = 0; static int pci_index = 0; /* Static, for multiple probe calls. */ @@ -443,17 +436,13 @@ int tulip_probe(void) well with the current structure. So instead we detect just the Tulip cards in slot order. */ -#if LINUX_VERSION_CODE >= 0x20155 if (! pci_present()) return -ENODEV; -#else - if (! pcibios_present()) - return -ENODEV; -#endif for (;pci_index < 0xff; pci_index++) { u16 vendor, device, pci_command, new_command; unsigned long pci_ioaddr = 0; int chip_idx = 0; + struct pci_dev *pdev; if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, @@ -465,10 +454,10 @@ int tulip_probe(void) else break; } - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); + + pdev = pci_find_slot (pci_bus, pci_device_fn); + vendor = pdev->vendor; + device = pdev->device; for (chip_idx = 0; tulip_tbl[chip_idx].chip_name; chip_idx++) if (vendor == tulip_tbl[chip_idx].vendor_id && @@ -482,12 +471,7 @@ int tulip_probe(void) vendor, device); continue; } -#if LINUX_VERSION_CODE >= 0x20155 pci_ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start; -#else - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, - &pci_ioaddr); -#endif /* Remove I/O space marker in bit 0. */ pci_ioaddr &= ~3; @@ -498,37 +482,32 @@ int tulip_probe(void) if (check_region(pci_ioaddr, tulip_tbl[chip_idx].io_size)) continue; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; if (pci_command != new_command) { printk(KERN_INFO " The PCI BIOS has not enabled this" " device! Updating PCI command %4.4x->%4.4x.\n", pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); + pci_write_config_word(pdev, PCI_COMMAND, new_command); } if(tulip_probe1(pci_bus, pci_device_fn, chip_idx, cards_found)) { /* Get and check the bus-master and latency values. */ unsigned char pci_latency; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < 10) { printk(KERN_INFO " PCI latency timer (CFLT) is " "unreasonably low at %d. Setting to 64 clocks.\n", pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, 64); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); } else if (tulip_debug > 1) printk(KERN_INFO " PCI latency timer (CFLT) is %#x, " " PCI command is %4.4x.\n", pci_latency, new_command); /* Bring the 21143 out power-down mode. */ if (device == PCI_DEVICE_ID_DEC_TULIP_21142) - pcibios_write_config_dword(pci_bus, pci_device_fn, - 0x40, 0x40000000); + pci_write_config_dword(pdev, 0x40, 0x40000000); cards_found++; } } @@ -1215,9 +1194,7 @@ tulip_open(struct net_device *dev) /* When a module we don't have 'x86' to check. */ outl(0x01A00000 | 0x4800, ioaddr + CSR0); #else -#if (LINUX_VERSION_CODE > 0x2014c) #define x86 boot_cpu_data.x86 -#endif outl(0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0); if (x86 <= 4) printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache " @@ -2208,19 +2185,13 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg #ifdef ETHER_STATS if (status & 0x0001) tp->stats.tx_deferred++; #endif -#if LINUX_VERSION_CODE > 0x20127 tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff; -#endif tp->stats.collisions += (status >> 3) & 15; tp->stats.tx_packets++; } /* Free the original skb. */ -#if (LINUX_VERSION_CODE > 0x20155) dev_kfree_skb_irq(tp->tx_skbuff[entry]); -#else - dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE); -#endif tp->tx_skbuff[entry] = 0; } @@ -2379,9 +2350,7 @@ tulip_rx(struct net_device *dev) netif_rx(skb); dev->last_rx = jiffies; tp->stats.rx_packets++; -#if LINUX_VERSION_CODE > 0x20127 tp->stats.rx_bytes += pkt_len; -#endif } entry = (++tp->cur_rx) % RX_RING_SIZE; } @@ -2444,23 +2413,12 @@ tulip_close(struct net_device *dev) tp->rx_ring[i].length = 0; tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */ if (skb) { -#if LINUX_VERSION_CODE < 0x20100 - skb->free = 1; -#endif -#if (LINUX_VERSION_CODE > 0x20155) dev_kfree_skb(skb); -#else - dev_kfree_skb(skb, FREE_WRITE); -#endif } } for (i = 0; i < TX_RING_SIZE; i++) { if (tp->tx_skbuff[i]) -#if (LINUX_VERSION_CODE > 0x20155) dev_kfree_skb(tp->tx_skbuff[i]); -#else - dev_kfree_skb(tp->tx_skbuff[i], FREE_WRITE); -#endif tp->tx_skbuff[i] = 0; } @@ -2692,12 +2650,14 @@ static dev_node_t *tulip_attach(dev_locator_t *loc) u32 io; u8 bus, devfn; struct net_device *dev; + struct pci_dev *pdev; if (loc->bus != LOC_PCI) return NULL; - bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; + pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn); + if (!pdev) return NULL; printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn); - pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); - pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); + io = pdev->resource[0].start; + dev_id = pdev->device; io &= ~3; dev = tulip_probe1(bus, devfn, DC21142, -1); if (dev) { @@ -2734,9 +2694,6 @@ struct driver_operations tulip_ops = { #endif /* Cardbus support */ - -#ifdef MODULE -#if LINUX_VERSION_CODE > 0x20118 MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver"); MODULE_PARM(debug, "i"); @@ -2745,13 +2702,11 @@ MODULE_PARM(reverse_probe, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif /* An additional parameter that may be passed in... */ static int debug = -1; -int -init_module(void) +static int __init tulip_init_module (void) { if (debug >= 0) tulip_debug = debug; @@ -2764,8 +2719,7 @@ init_module(void) #endif } -void -cleanup_module(void) +static void __exit tulip_cleanup_module (void) { struct net_device *next_dev; @@ -2783,8 +2737,10 @@ cleanup_module(void) } } -#endif /* MODULE */ - +module_init(tulip_init_module); +module_exit(tulip_cleanup_module); + + /* * Local variables: * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index dc1b879d9b01..5d412d161d5a 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -66,7 +66,6 @@ static const int multicast_filter_limit = 32; #include #include -#include #include #include #include @@ -77,6 +76,7 @@ static const int multicast_filter_limit = 32; #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -109,10 +109,6 @@ static const int multicast_filter_limit = 32; #define RUN_AT(x) (jiffies + (x)) -#ifdef MODULE -char kernel_version[] = UTS_RELEASE; -#endif -#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver"); MODULE_PARM(max_interrupt_work, "i"); @@ -121,27 +117,6 @@ MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -#if LINUX_VERSION_CODE < 0x20123 -#define test_and_set_bit(val, addr) set_bit(val, addr) -#endif -#if LINUX_VERSION_CODE <= 0x20139 -#define net_device_stats enet_statistics -#else -#define NETSTATS_VER2 -#endif -#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS) -/* Grrrr, the PCI code changed, but did not consider CardBus... */ -#include -#define PCI_SUPPORT_VER1 -#else -#define PCI_SUPPORT_VER2 -#endif -#if LINUX_VERSION_CODE < 0x20159 -#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE); -#else -#define dev_free_skb(skb) dev_kfree_skb(skb); -#endif /* @@ -248,10 +223,10 @@ struct pci_id_info { const char *name; u16 vendor_id, device_id, device_id_mask, flags; int io_size; - struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt); + struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt); }; -static struct net_device *via_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, +static struct net_device *via_probe1(struct pci_dev *pdev, long ioaddr, int irq, int chp_idx, int fnd_cnt); static struct pci_id_info pci_tbl[] = { @@ -343,7 +318,7 @@ struct netdev_private { struct net_device *next_module; /* Link for devices of this type. */ struct net_device_stats stats; struct timer_list timer; /* Media monitoring timer. */ - unsigned char pci_bus, pci_devfn; + spinlock_t lock; /* Frequently used values: keep some adjacent for cache effect. */ int chip_id; long in_interrupt; /* Word-long for SMP locks. */ @@ -398,23 +373,22 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) unsigned char pci_bus, pci_device_fn; struct net_device *dev; - if ( ! pcibios_present()) - return -ENODEV; - for (;pci_index < 0xff; pci_index++) { u16 vendor, device, pci_command, new_command; int chip_idx, irq; long pciaddr; long ioaddr; + struct pci_dev *pdev; if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); + + pdev = pci_find_slot (pci_bus, pci_device_fn); + if (!pdev) continue; + vendor = pdev->vendor; + device = pdev->device; for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) if (vendor == pci_tbl[chip_idx].vendor_id @@ -424,32 +398,12 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ continue; - { -#if defined(PCI_SUPPORT_VER2) - struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); #ifdef VIA_USE_IO - pciaddr = pdev->resource[0].start; + pciaddr = pdev->resource[0].start; #else - pciaddr = pdev->resource[1].start; + pciaddr = pdev->resource[1].start; #endif - irq = pdev->irq; -#else - u32 pci_memaddr; - u8 pci_irq_line; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); -#ifdef VIA_USE_IO - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_memaddr); - pciaddr = pci_memaddr; -#else - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_memaddr); - pciaddr = pci_memaddr; -#endif - irq = pci_irq_line; -#endif - } + irq = pdev->irq; if (debug > 2) printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n", @@ -466,30 +420,25 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) continue; } - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); new_command = pci_command | (pci_tbl[chip_idx].flags & 7); if (pci_command != new_command) { printk(KERN_INFO " The PCI BIOS has not enabled the" " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", - pci_bus, pci_device_fn, pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); + pdev->bus->number, pdev->devfn, pci_command, new_command); + pci_write_config_word(pdev, PCI_COMMAND, new_command); } - dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, ioaddr, - irq, chip_idx, cards_found); + dev = pci_tbl[chip_idx].probe1(pdev, ioaddr, irq, chip_idx, cards_found); if (dev && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) { u8 pci_latency; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < min_pci_latency) { printk(KERN_INFO " PCI latency timer (CFLT) is " "unreasonably low at %d. Setting to %d clocks.\n", pci_latency, min_pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, min_pci_latency); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency); } } dev = 0; @@ -499,17 +448,10 @@ static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) return cards_found ? 0 : -ENODEV; } -#ifndef MODULE -int via_rhine_probe(void) -{ - printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); - return pci_etherdev_probe(pci_tbl); -} -#endif -static struct net_device *via_probe1(int pci_bus, int pci_devfn, - long ioaddr, int irq, - int chip_id, int card_idx) +static struct net_device *via_probe1(struct pci_dev *pdev, + long ioaddr, int irq, + int chip_id, int card_idx) { struct net_device *dev; struct netdev_private *np; @@ -522,6 +464,14 @@ static struct net_device *via_probe1(int pci_bus, int pci_devfn, printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, pci_tbl[chip_id].name, ioaddr); +#ifdef VIA_USE_IO + if (!request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name)) { + unregister_netdev (dev); + kfree (dev); + return NULL; + } +#endif + /* Ideally we would be read the EEPROM but access may be locked. */ for (i = 0; i <6; i++) dev->dev_addr[i] = readb(ioaddr + StationAddr + i); @@ -529,10 +479,6 @@ static struct net_device *via_probe1(int pci_bus, int pci_devfn, printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); -#ifdef VIA_USE_IO - request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name); -#endif - /* Reset the chip to erase previous misconfiguration. */ writew(CmdReset, ioaddr + ChipCmd); @@ -548,8 +494,7 @@ static struct net_device *via_probe1(int pci_bus, int pci_devfn, np->next_module = root_net_dev; root_net_dev = dev; - np->pci_bus = pci_bus; - np->pci_devfn = pci_devfn; + np->lock = SPIN_LOCK_UNLOCKED; np->chip_id = chip_id; if (dev->mem_start) @@ -576,6 +521,8 @@ static struct net_device *via_probe1(int pci_bus, int pci_devfn, dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &mii_ioctl; + dev->tx_timeout = tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; if (cap_tbl[np->chip_id].flags & CanHaveMII) { int phy, phy_idx = 0; @@ -671,14 +618,11 @@ static int netdev_open(struct net_device *dev) if (dev->if_port == 0) dev->if_port = np->default_port; - dev->tbusy = 0; - dev->interrupt = 0; + netif_start_queue(dev); np->in_interrupt = 0; set_rx_mode(dev); - dev->start = 1; - /* Enable interrupts by setting the interrupt mask. */ writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow| IntrRxDropped| IntrTxDone | IntrTxAbort | IntrTxUnderrun | @@ -824,15 +768,6 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) struct netdev_private *np = (struct netdev_private *)dev->priv; unsigned entry; - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start < TX_TIMEOUT) - return 1; - tx_timeout(dev); - return 1; - } - /* Caution: the write order is important here, set the field with the "ownership" bits last. */ @@ -862,7 +797,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd); if (np->cur_tx - np->dirty_tx < TX_RING_SIZE - 1) - clear_bit(0, (void*)&dev->tbusy); /* Typical path */ + netif_start_queue(dev); /* Typical path */ else np->tx_full = 1; dev->trans_start = jiffies; @@ -884,21 +819,8 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) ioaddr = dev->base_addr; np = (struct netdev_private *)dev->priv; -#if defined(__i386__) - /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ - if (test_and_set_bit(0, (void*)&dev->interrupt)) { - printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", - dev->name); - dev->interrupt = 0; /* Avoid halting machine. */ - return; - } -#else - if (dev->interrupt) { - printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); - return; - } - dev->interrupt = 1; -#endif + + spin_lock (&np->lock); do { u32 intr_status = readw(ioaddr + IntrStatus); @@ -936,30 +858,22 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) if (txstatus & 0x0100) np->stats.tx_aborted_errors++; if (txstatus & 0x0080) np->stats.tx_heartbeat_errors++; if (txstatus & 0x0002) np->stats.tx_fifo_errors++; -#ifdef ETHER_STATS - if (txstatus & 0x0100) np->stats.collisions16++; -#endif /* Transmitter restarted in 'abnormal' handler. */ } else { -#ifdef ETHER_STATS - if (txstatus & 0x0001) np->stats.tx_deferred++; -#endif np->stats.collisions += (txstatus >> 3) & 15; -#if defined(NETSTATS_VER2) np->stats.tx_bytes += np->tx_ring[entry].desc_length & 0x7ff; -#endif np->stats.tx_packets++; } /* Free the original skb. */ - dev_free_skb(np->tx_skbuff[entry]); + kfree_skb(np->tx_skbuff[entry]); np->tx_skbuff[entry] = 0; } - if (np->tx_full && dev->tbusy - && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) { + if (np->tx_full && + test_bit(LINK_STATE_XOFF, &dev->flags) && + np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) { /* The ring is no longer full, clear tbusy. */ np->tx_full = 0; - clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (dev); } /* Abnormal error summary/uncommon events handlers. */ @@ -979,12 +893,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", dev->name, readw(ioaddr + IntrStatus)); -#if defined(__i386__) - clear_bit(0, (void*)&dev->interrupt); -#else - dev->interrupt = 0; -#endif - return; + spin_unlock (&np->lock); } /* This routine is logically part of the interrupt handler, but isolated @@ -1217,8 +1126,7 @@ static int netdev_close(struct net_device *dev) struct netdev_private *np = (struct netdev_private *)dev->priv; int i; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); if (debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n", @@ -1239,16 +1147,13 @@ static int netdev_close(struct net_device *dev) np->rx_ring[i].rx_length = 0; np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ if (np->rx_skbuff[i]) { -#if LINUX_VERSION_CODE < 0x20100 - np->rx_skbuff[i]->free = 1; -#endif - dev_free_skb(np->rx_skbuff[i]); + kfree_skb(np->rx_skbuff[i]); } np->rx_skbuff[i] = 0; } for (i = 0; i < TX_RING_SIZE; i++) { if (np->tx_skbuff[i]) - dev_free_skb(np->tx_skbuff[i]); + kfree_skb(np->tx_skbuff[i]); np->tx_skbuff[i] = 0; } @@ -1257,9 +1162,7 @@ static int netdev_close(struct net_device *dev) return 0; } - -#ifdef MODULE -int init_module(void) +static int __init via_rhine_init_module (void) { if (debug) /* Emit version even if no cards detected. */ printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); @@ -1271,7 +1174,7 @@ int init_module(void) #endif } -void cleanup_module(void) +static void __exit via_rhine_cleanup_module (void) { #ifdef CARDBUS @@ -1296,8 +1199,10 @@ void cleanup_module(void) } } -#endif /* MODULE */ - +module_init(via_rhine_init_module); +module_exit(via_rhine_cleanup_module); + + /* * Local variables: * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c via-rhine.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 637873962ac6..37cf755edbd6 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -74,6 +74,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -83,27 +84,9 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include -/* Kernel compatibility defines, most common to the PCCard package. */ -#include /* Evil and unneccessary */ - #define RUN_AT(x) (jiffies + (x)) -#if (LINUX_VERSION_CODE < 0x20123) -#define test_and_set_bit(val, addr) set_bit(val, addr) -#endif -#if LINUX_VERSION_CODE <= 0x20139 -#define net_device_stats enet_statistics -#define NETSTATS_VER2 -#endif -#if LINUX_VERSION_CODE < 0x20155 -#define PCI_SUPPORT_VER1 -#define pci_present pcibios_present -#endif -#if LINUX_VERSION_CODE < 0x20159 -#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE); -#else #define DEV_FREE_SKB(skb) dev_kfree_skb(skb); -#endif /* The PCI I/O space extent. */ #define YELLOWFIN_TOTAL_SIZE 0x100 @@ -280,9 +263,9 @@ struct yellowfin_private { struct tx_status_words tx_status[TX_RING_SIZE]; struct timer_list timer; /* Media selection timer. */ struct enet_statistics stats; + spinlock_t lock; /* Frequently used and paired value: keep adjacent for cache effect. */ int chip_id; - int in_interrupt; struct yellowfin_desc *rx_head_desc; struct tx_status_words *tx_tail_desc; unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ @@ -300,9 +283,6 @@ struct yellowfin_private { u32 pad[4]; /* Used for 32-byte alignment */ }; -#ifdef MODULE - -#if LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver"); MODULE_PARM(max_interrupt_work, "i"); @@ -312,9 +292,6 @@ MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif - -#endif static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, int options); static int read_eeprom(long ioaddr, int location); @@ -340,7 +317,7 @@ static void set_rx_mode(struct net_device *dev); /* A list of all installed Yellowfin devices, for removing the driver module. */ static struct net_device *root_yellowfin_dev = NULL; -int yellowfin_probe(void) +static int __init yellowfin_probe(void) { int cards_found = 0; int pci_index = 0; @@ -355,6 +332,7 @@ int yellowfin_probe(void) int chip_idx; int irq; long ioaddr; + struct pci_dev *pdev; if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, @@ -362,10 +340,10 @@ int yellowfin_probe(void) != PCIBIOS_SUCCESSFUL) break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); + pdev = pci_find_slot (pci_bus, pci_device_fn); + if (!pdev) break; + vendor = pdev->vendor; + device = pdev->device; for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++) if (vendor == chip_tbl[chip_idx].vendor_id @@ -388,28 +366,24 @@ int yellowfin_probe(void) if (check_region(ioaddr, YELLOWFIN_TOTAL_SIZE)) continue; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; if (pci_command != new_command) { printk(KERN_INFO " The PCI BIOS has not enabled the" " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", pci_bus, pci_device_fn, pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); + pci_write_config_word(pdev, PCI_COMMAND, new_command); } if(yellowfin_probe1(ioaddr, irq, chip_idx, cards_found)) { /* Get and check the bus-master and latency values. */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < min_pci_latency) { printk(KERN_INFO " PCI latency timer (CFLT) is " "unreasonably low at %d. Setting to %d clocks.\n", pci_latency, min_pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, min_pci_latency); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency); } else if (yellowfin_debug > 1) printk(KERN_INFO " PCI latency timer (CFLT) is %#x.\n", pci_latency); @@ -465,6 +439,7 @@ static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, in root_yellowfin_dev = dev; yp->chip_id = chip_id; + yp->lock = SPIN_LOCK_UNLOCKED; option = card_idx < MAX_UNITS ? options[card_idx] : 0; if (dev->mem_start) @@ -493,6 +468,9 @@ static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, in #ifdef HAVE_PRIVATE_IOCTL dev->do_ioctl = &mii_ioctl; #endif + dev->tx_timeout = yellowfin_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + if (mtu) dev->mtu = mtu; @@ -602,9 +580,7 @@ static int yellowfin_open(struct net_device *dev) if (dev->if_port == 0) dev->if_port = yp->default_port; - dev->tbusy = 0; - dev->interrupt = 0; - yp->in_interrupt = 0; + netif_start_queue(dev); /* Setting the Rx mode will start the Rx process. */ if (yp->chip_id == 0) { @@ -618,8 +594,6 @@ static int yellowfin_open(struct net_device *dev) } set_rx_mode(dev); - dev->start = 1; - /* Enable interrupts by setting the interrupt mask. */ outw(0x81ff, ioaddr + IntrEnb); /* See enum intr_status_bits */ outw(0x0000, ioaddr + EventStatus); /* Clear non-interrupting events */ @@ -787,15 +761,6 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; unsigned entry; - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start < TX_TIMEOUT) - return 1; - yellowfin_tx_timeout(dev); - return 1; - } - /* Caution: the write order is important here, set the base address with the "ownership" bits last. */ @@ -840,7 +805,7 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) outl(0x10001000, dev->base_addr + TxCtrl); if (yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 1) - clear_bit(0, (void*)&dev->tbusy); /* Typical path */ + netif_start_queue(dev); /* Typical path */ else yp->tx_full = 1; dev->trans_start = jiffies; @@ -869,11 +834,8 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg ioaddr = dev->base_addr; yp = (struct yellowfin_private *)dev->priv; - if (test_and_set_bit(0, (void*)&yp->in_interrupt)) { - dev->interrupt = 1; - printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); - return; - } + + spin_lock (&yp->lock); do { u16 intr_status = inw(ioaddr + IntrClear); @@ -900,12 +862,12 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg yp->tx_skbuff[entry] = 0; yp->stats.tx_packets++; } - if (yp->tx_full && dev->tbusy - && yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) { + if (yp->tx_full && + test_bit(LINK_STATE_XOFF, &dev->flags) && + yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) { /* The ring is no longer full, clear tbusy. */ yp->tx_full = 0; - clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (dev); } #else if (intr_status & IntrTxDone @@ -973,12 +935,12 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg } #endif - if (yp->tx_full && dev->tbusy - && yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) { + if (yp->tx_full && + test_bit(LINK_STATE_XOFF, &dev->flags) && + yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) { /* The ring is no longer full, clear tbusy. */ yp->tx_full = 0; - clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (dev); } yp->dirty_tx = dirty_tx; @@ -1004,15 +966,14 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg /* Code that should never be run! Perhaps remove after testing.. */ { static int stopit = 10; - if (dev->start == 0 && --stopit < 0) { + if ((!test_bit(LINK_STATE_START, &dev->state)) && --stopit < 0) { printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n", dev->name); free_irq(irq, dev); } } - dev->interrupt = 0; - clear_bit(0, (void*)&yp->in_interrupt); + spin_lock (&yp->lock); return; } @@ -1171,8 +1132,7 @@ static int yellowfin_close(struct net_device *dev) struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; int i; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); if (yellowfin_debug > 1) { printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n", @@ -1233,9 +1193,6 @@ static int yellowfin_close(struct net_device *dev) yp->rx_ring[i].cmd = CMD_STOP; yp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ if (yp->rx_skbuff[i]) { -#if LINUX_VERSION_CODE < 0x20100 - yp->rx_skbuff[i]->free = 1; -#endif DEV_FREE_SKB(yp->rx_skbuff[i]); } yp->rx_skbuff[i] = 0; @@ -1358,13 +1315,11 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } #endif /* HAVE_PRIVATE_IOCTL */ - -#ifdef MODULE /* An additional parameter that may be passed in... */ static int debug = -1; -int init_module(void) +static int __init yellowfin_init_module(void) { if (debug >= 0) yellowfin_debug = debug; @@ -1372,7 +1327,7 @@ int init_module(void) return yellowfin_probe(); } -void cleanup_module(void) +static void __exit yellowfin_cleanup_module (void) { struct net_device *next_dev; @@ -1386,8 +1341,10 @@ void cleanup_module(void) } } -#endif /* MODULE */ - +module_init(yellowfin_init_module); +module_exit(yellowfin_cleanup_module); + + /* * Local variables: * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f3c89a89adaa..cc76f78dbc34 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -401,7 +401,7 @@ pci_set_master(struct pci_dev *dev) * Translate the low bits of the PCI base * to the resource type */ -static inline unsigned int pci_resource_flags(unsigned int flags) +static inline unsigned int pci_calc_resource_flags(unsigned int flags) { if (flags & PCI_BASE_ADDRESS_SPACE_IO) return IORESOURCE_IO; @@ -445,7 +445,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) sz = ~(sz & PCI_BASE_ADDRESS_IO_MASK) & 0xffff; } res->end = res->start + (unsigned long) sz; - res->flags |= (l & 0xf) | pci_resource_flags(l); + res->flags |= (l & 0xf) | pci_calc_resource_flags(l); if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { pci_read_config_dword(dev, reg+4, &l); diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index ab7d94bb1756..2e60789cfa25 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -1,4 +1,4 @@ -/* $Id: flash.c,v 1.16 2000/02/09 22:33:24 davem Exp $ +/* $Id: flash.c,v 1.17 2000/02/10 02:51:35 davem Exp $ * flash.c: Allow mmap access to the OBP Flash, for OBP updates. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -133,9 +133,9 @@ static struct file_operations flash_fops = { */ llseek: flash_llseek, read: flash_read, - ioctl: flash_mmap, - mmap: flash_open, - flush: flash_release, + mmap: flash_mmap, + open: flash_open, + release: flash_release, }; static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h index 30e97ff3edf4..191e4469ed7d 100644 --- a/drivers/scsi/hosts.h +++ b/drivers/scsi/hosts.h @@ -25,6 +25,7 @@ $Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $ */ +#include #include /* It is senseless to set SG_ALL any higher than this - the performance diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 7529c30636db..e092f40a1147 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -36,6 +36,7 @@ * # cat /proc/scsi/sg/debug * */ +#include #include #include diff --git a/drivers/sound/ac97_codec.h b/drivers/sound/ac97_codec.h index 36d2b052a659..27d41f5bba2b 100644 --- a/drivers/sound/ac97_codec.h +++ b/drivers/sound/ac97_codec.h @@ -154,4 +154,5 @@ struct ac97_codec { }; extern int ac97_probe_codec(struct ac97_codec *); -#endif + +#endif /* _AC97_CODEC_H_ */ diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index 71d820b9efe0..6038865045f3 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -13,6 +13,7 @@ */ #include +#include #define _DEV_TABLE_C_ @@ -313,9 +314,12 @@ int sndtable_identify_card(char *name) return 0; } -void sound_setup(char *str, int *ints) +static int __init sound_setup(char *str) { int i, n = num_sound_cards; + int ints[32]; + + str = get_options(str, ARRAY_SIZE(ints), ints); /* * First disable all drivers @@ -325,7 +329,7 @@ void sound_setup(char *str, int *ints) snd_installed_cards[i].enabled = 0; if (ints[0] == 0 || ints[1] == 0) - return; + return 1; /* * Then enable them one by time */ @@ -343,7 +347,7 @@ void sound_setup(char *str, int *ints) /* * Add any future extensions here */ - return; + return 1; } ioaddr = (val & 0x000fff00) >> 8; irq = (val & 0x000000f0) >> 4; @@ -376,8 +380,12 @@ void sound_setup(char *str, int *ints) snd_installed_cards[ptr].config.card_subtype = 0; } } + + return 1; } +__setup("sound=", sound_setup); + struct address_info * sound_getconf(int card_type) { diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h index 14c8cd2ac3f7..427c6f4db17c 100644 --- a/drivers/sound/dev_table.h +++ b/drivers/sound/dev_table.h @@ -717,7 +717,10 @@ int snd_find_driver(int type); void sound_unload_drivers(void); void sound_unload_driver(int type); int sndtable_identify_card(char *name); + +#if FIXED_FOR_2_4_0 void sound_setup (char *str, int *ints); +#endif extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info); int sndtable_probe (int unit, struct address_info *hw_config); diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c index 55aa0aae4848..ae627ed3b761 100644 --- a/drivers/sound/dmasound.c +++ b/drivers/sound/dmasound.c @@ -5682,10 +5682,12 @@ void __init dmasound_init(void) } -#define MAXARGS 8 /* Should be sufficient for now */ - -void __init dmasound_setup(char *str, int *ints) +static int __init dmasound_setup(char *str) { + int ints[6]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + /* check the bootstrap parameter for "dmasound=" */ switch (ints[0]) { @@ -5709,9 +5711,14 @@ void __init dmasound_setup(char *str, int *ints) break; default: printk("dmasound_setup: illegal number of arguments\n"); + return 0; } + + return 1; } +__setup("dmasound=", dmasound_setup); + #ifdef MODULE diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index d8a9c2be7439..5593cf5ddb7a 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -875,8 +875,10 @@ MODULE_PARM(dmabug, "i"); int init_module(void) { int err; +#if FIXED_FOR_2_4_0 int ints[21]; int i; +#endif trace_init=traceinit; @@ -888,6 +890,7 @@ int init_module(void) printk(KERN_ERR "sound: rebuild with PCI_QUIRKS enabled to configure this.\n"); #endif +#if FIXED_FOR_2_4_0 /* * "sound=" command line handling by Harald Milz. */ @@ -898,6 +901,7 @@ int init_module(void) if (i) sound_setup("sound=", ints); +#endif err = create_special_devices(); if (err) diff --git a/drivers/usb/keybdev.c b/drivers/usb/keybdev.c index f45f7032fe29..cd89cedb2a6d 100644 --- a/drivers/usb/keybdev.c +++ b/drivers/usb/keybdev.c @@ -112,7 +112,7 @@ void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int #error "Cannot generate rawmode keyboard for your architecture yet." #endif - mark_bh(KEYBOARD_BH); + tasklet_schedule(&keyboard_tasklet); } static int keybdev_connect(struct input_handler *handler, struct input_dev *dev) diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index 9760a6d3f389..3bec2e85171c 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.137 2000/01/09 03:11:49 davem Exp $ +/* $Id: atyfb.c,v 1.138 2000/02/10 02:52:12 davem Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 05937987535c..140e28598454 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -299,25 +299,4 @@ struct inode_operations adfs_dir_inode_operations = { &adfs_dir_operations, /* default directory file-ops */ NULL, /* create */ adfs_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* read link */ - NULL, /* follow link */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - NULL, /* bmap */ - NULL, /* read page */ - NULL, /* write page */ -#else - NULL, /* read page */ - NULL, /* write page */ - NULL, /* bmap */ -#endif - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; diff --git a/fs/adfs/file.c b/fs/adfs/file.c index a02eae894cdf..a2f105b06d85 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c @@ -29,28 +29,6 @@ #include "adfs.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -/* - * Write to a file (through the page cache). - */ -static ssize_t -adfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - ssize_t retval; - - retval = generic_file_write(file, buf, count, ppos, - block_write_partial_page); - - if (retval > 0) { - struct inode *inode = file->f_dentry->d_inode; - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - mark_inode_dirty(inode); - } - - return retval; -} -#endif - /* * We have mostly NULLs here: the current defaults are OK for * the adfs filesystem. @@ -60,33 +38,10 @@ static struct file_operations adfs_file_operations = { mmap: generic_file_mmap, fsync: file_fsync, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - write: adfs_file_write, + write: generic_file_write, #endif }; struct inode_operations adfs_file_inode_operations = { &adfs_file_operations, /* default file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - adfs_get_block, /* bmap */ - block_read_full_page, /* readpage */ - block_write_full_page, /* writepage */ -#else - generic_readpage, /* readpage */ - NULL, /* writepage */ - adfs_bmap, /* bmap */ -#endif - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* revalidate */ }; diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index e0cfbc259103..30398d62f9c8 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -48,6 +48,30 @@ abort_negative: abort_toobig: return 0; } +static int adfs_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,adfs_get_block); +} +static int adfs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,adfs_get_block); +} +static int adfs_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return cont_prepare_write(page,from,to,adfs_get_block, + &((struct inode*)page->mapping->host)->u.adfs_i.mmu_private); +} +static int _adfs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,adfs_get_block); +} +struct address_space_operations adfs_aops = { + readpage: adfs_readpage, + writepage: adfs_writepage, + prepare_write: adfs_prepare_write, + commit_write: generic_commit_write, + bmap: _adfs_bmap +}; #else int adfs_bmap(struct inode *inode, int block) { @@ -255,8 +279,11 @@ adfs_iget(struct super_block *sb, struct object_info *obj) if (S_ISDIR(inode->i_mode)) inode->i_op = &adfs_dir_inode_operations; - else if (S_ISREG(inode->i_mode)) - inode->i_op = &adfs_file_inode_operations; + else if (S_ISREG(inode->i_mode)) { + inode->i_op = &adfs_file_inode_operations; + inode->i_mapping->a_ops = &adfs_aops; + inode->u.adfs_i.mmu_private = inode->i_size; + } insert_inode_hash(inode); diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 818a45b59823..b554daf0c1bc 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -47,14 +47,6 @@ struct inode_operations affs_dir_inode_operations = { affs_rmdir, /* rmdir */ NULL, /* mknod */ affs_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permissions */ - NULL /* revalidate */ }; static ssize_t diff --git a/fs/affs/file.c b/fs/affs/file.c index 52ccd1d31dad..8881fe3e452b 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -63,9 +63,6 @@ struct inode_operations affs_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - affs_bmap, /* get_block */ - block_read_full_page, /* readpage */ - NULL, /* writepage */ affs_truncate, /* truncate */ NULL, /* permission */ NULL /* revalidate */ @@ -90,9 +87,6 @@ struct inode_operations affs_file_inode_operations_ofs = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ affs_truncate, /* truncate */ NULL, /* permission */ NULL /* revalidate */ @@ -322,6 +316,37 @@ affs_bmap(struct inode *inode, int block) return key; } +/* AFFS is currently broken */ +static int affs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create) +{ + BUG(); + return -1; +} +static int affs_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,affs_get_block); +} +static int affs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,affs_get_block); +} +static int affs_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return cont_prepare_write(page,from,to,affs_get_block, + &((struct inode*)page->mapping->host)->u.affs_i.mmu_private); +} +static int _affs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,affs_get_block); +} +struct address_space_operations affs_aops = { + readpage: affs_readpage, + writepage: affs_writepage, + prepare_write: affs_prepare_write, + commit_write: generic_commit_write, + bmap: _affs_bmap +}; + /* With the affs, getting a random block from a file is not * a simple business. Since this fs does not allow holes, * it may be necessary to allocate all the missing blocks diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 9b05ec062ae1..ed4993e36d51 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -166,16 +166,20 @@ affs_read_inode(struct inode *inode) if (S_ISREG(inode->i_mode)) { if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) { inode->i_op = &affs_file_inode_operations_ofs; - } else { - inode->i_op = &affs_file_inode_operations; + return; } + inode->i_op = &affs_file_inode_operations; + inode->i_mapping->a_ops = &affs_aops; + inode->u.affs_i.mmu_private = inode->i_size; } else if (S_ISDIR(inode->i_mode)) { /* Maybe it should be controlled by mount parameter? */ inode->i_mode |= S_ISVTX; inode->i_op = &affs_dir_inode_operations; } - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &affs_symlink_inode_operations; + else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &affs_symlink_aops; + } } void diff --git a/fs/affs/namei.c b/fs/affs/namei.c index aad5b8f149b4..d2c27b9d1e96 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -275,9 +275,11 @@ affs_create(struct inode *dir, struct dentry *dentry, int mode) pr_debug("AFFS: ino=%lu\n",inode->i_ino); if (dir->i_sb->u.affs_sb.s_flags & SF_OFS) inode->i_op = &affs_file_inode_operations_ofs; - else + else { inode->i_op = &affs_file_inode_operations; - + inode->i_mapping->a_ops = &affs_aops; + inode->u.affs_i.mmu_private = inode->i_size; + } error = affs_add_entry(dir,NULL,inode,dentry,ST_FILE); if (error) goto out_iput; @@ -401,7 +403,8 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) if (!inode) goto out; - inode->i_op = &affs_symlink_inode_operations; + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &affs_symlink_aops; inode->i_mode = S_IFLNK | 0777; inode->u.affs_i.i_protect = mode_to_prot(inode->i_mode); error = -EIO; diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index 6aad1c2222f1..885d5099da1b 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -71,8 +71,6 @@ fail: return err; } -struct inode_operations affs_symlink_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, +struct address_space_operations affs_symlink_aops = { readpage: affs_symlink_readpage, }; diff --git a/fs/autofs/dir.c b/fs/autofs/dir.c index 1aedab1e43b4..a62fd6c54612 100644 --- a/fs/autofs/dir.c +++ b/fs/autofs/dir.c @@ -50,20 +50,5 @@ struct inode_operations autofs_dir_inode_operations = { &autofs_dir_operations, /* file operations */ NULL, /* create */ autofs_dir_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; diff --git a/fs/autofs/init.c b/fs/autofs/init.c index 5c31dc889b7e..4c9e8fe76ac2 100644 --- a/fs/autofs/init.c +++ b/fs/autofs/init.c @@ -31,8 +31,8 @@ static void __exit exit_autofs_fs(void) unregister_filesystem(&autofs_fs_type); } -module_init(init_autofs_fs) -module_exit(exit_autofs_fs) +module_init(init_autofs_fs); +module_exit(exit_autofs_fs); #ifdef DEBUG void autofs_say(const char *name, int len) diff --git a/fs/autofs/root.c b/fs/autofs/root.c index e5a4d84ca5b4..e2c03ff34521 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -37,16 +37,6 @@ struct inode_operations autofs_root_inode_operations = { autofs_root_symlink, /* symlink */ autofs_root_mkdir, /* mkdir */ autofs_root_rmdir, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldir) diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 0febe463c4ff..931a32a4e167 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -59,9 +59,6 @@ struct inode_operations bad_inode_ops = EIO_ERROR, /* rename */ EIO_ERROR, /* readlink */ bad_follow_link, /* follow_link */ - EIO_ERROR, /* get_block */ - EIO_ERROR, /* readpage */ - EIO_ERROR, /* writepage */ EIO_ERROR, /* truncate */ EIO_ERROR, /* permission */ EIO_ERROR /* revalidate */ diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 9ca1ce88a4a1..83b3e517b880 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -107,6 +107,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode) inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = inode->i_blksize = 0; inode->i_op = &bfs_file_inops; + inode->i_mapping->a_ops = &bfs_aops; inode->i_mode = mode; inode->i_ino = inode->iu_dsk_ino = ino; inode->iu_sblock = inode->iu_eblock = 0; @@ -265,14 +266,6 @@ struct inode_operations bfs_dir_inops = { rmdir: NULL, mknod: NULL, rename: bfs_rename, - readlink: NULL, - follow_link: NULL, - get_block: NULL, - readpage: NULL, - writepage: NULL, - truncate: NULL, - permission: NULL, - revalidate: NULL }; static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino) diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 8b6632f8f6c1..c3d5a890549b 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -18,14 +18,9 @@ #define dprintf(x...) #endif -static ssize_t bfs_file_write(struct file * f, const char * buf, size_t count, loff_t *ppos) -{ - return generic_file_write(f, buf, count, ppos, block_write_partial_page); -} - static struct file_operations bfs_file_operations = { read: generic_file_read, - write: bfs_file_write, + write: generic_file_write, mmap: generic_file_mmap, }; @@ -129,23 +124,30 @@ out: return err; } +static int bfs_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,bfs_get_block); +} +static int bfs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,bfs_get_block); +} +static int bfs_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return block_prepare_write(page,from,to,bfs_get_block); +} +static int bfs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,bfs_get_block); +} +struct address_space_operations bfs_aops = { + readpage: bfs_readpage, + writepage: bfs_writepage, + prepare_write: bfs_prepare_write, + commit_write: generic_commit_write, + bmap: bfs_bmap +}; + struct inode_operations bfs_file_inops = { default_file_ops: &bfs_file_operations, - create: NULL, - lookup: NULL, - link: NULL, - unlink: NULL, - symlink: NULL, - mkdir: NULL, - rmdir: NULL, - mknod: NULL, - rename: NULL, - readlink: NULL, - follow_link: NULL, - get_block: bfs_get_block, - readpage: block_read_full_page, - writepage: block_write_full_page, - truncate: NULL, - permission: NULL, - revalidate: NULL }; diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 300605789e28..14e440f27792 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -62,6 +62,7 @@ static void bfs_read_inode(struct inode * inode) } else if (di->i_vtype == BFS_VREG) { inode->i_mode |= S_IFREG; inode->i_op = &bfs_file_inops; + inode->i_mapping->a_ops = &bfs_aops; } else inode->i_op = NULL; diff --git a/fs/buffer.c b/fs/buffer.c index d9ab9c25db9a..9113c07cceed 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1371,9 +1371,8 @@ static void unmap_underlying_metadata(struct buffer_head * bh) * block_write_full_page() is SMP-safe - currently it's still * being called with the kernel lock held, but the code is ready. */ -int block_write_full_page(struct dentry *dentry, struct page *page) +static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block) { - struct inode *inode = dentry->d_inode; int err, i, need_balance_dirty = 0; unsigned long block; struct buffer_head *bh, *head; @@ -1385,17 +1384,11 @@ int block_write_full_page(struct dentry *dentry, struct page *page) create_empty_buffers(page, inode, inode->i_sb->s_blocksize); head = page->buffers; - /* The page cache is now PAGE_CACHE_SIZE aligned, period. We handle old a.out - * and others via unaligned private mappings. - */ block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); bh = head; i = 0; do { - if (!bh) - BUG(); - /* * If the buffer isn't up-to-date, we can't be sure * that the buffer has been initialized with the proper @@ -1406,7 +1399,7 @@ int block_write_full_page(struct dentry *dentry, struct page *page) */ bh->b_end_io = end_buffer_io_sync; if (!buffer_mapped(bh)) { - err = inode->i_op->get_block(inode, block, bh, 1); + err = get_block(inode, block, bh, 1); if (err) goto out; if (buffer_new(bh)) @@ -1432,13 +1425,12 @@ out: return err; } -int block_write_zero_range(struct inode *inode, struct page *page, - unsigned zerofrom, unsigned from, unsigned to, - const char * buf) +static int __block_prepare_write(struct inode *inode, struct page *page, + unsigned from, unsigned to, get_block_t *get_block) { - unsigned zeroto = 0, block_start, block_end; + unsigned block_start, block_end; unsigned long block; - int err = 0, partial = 0, need_balance_dirty = 0; + int err = 0; unsigned blocksize, bbits; struct buffer_head *bh, *head, *wait[2], **wait_bh=wait; char *kaddr = (char *)kmap(page); @@ -1451,35 +1443,31 @@ int block_write_zero_range(struct inode *inode, struct page *page, bbits = inode->i_sb->s_blocksize_bits; block = page->index << (PAGE_CACHE_SHIFT - bbits); - /* - * First pass - map what needs to be mapped, initiate reads - * on the boundaries if needed (i.e. if block is partially covered - * _and_ is not up-to-date _and_ is not new). - */ for(bh = head, block_start = 0; bh != head || !block_start; block++, block_start=block_end, bh = bh->b_this_page) { if (!bh) BUG(); block_end = block_start+blocksize; - if (block_end <= zerofrom) + if (block_end <= from) continue; if (block_start >= to) break; bh->b_end_io = end_buffer_io_sync; if (!buffer_mapped(bh)) { - err = inode->i_op->get_block(inode, block, bh, 1); + err = get_block(inode, block, bh, 1); if (err) goto out; if (buffer_new(bh)) { unmap_underlying_metadata(bh); - zeroto = block_end; - if (block_start < zerofrom) - zerofrom = block_start; + if (block_end > to) + memset(kaddr+to, 0, block_end-to); + if (block_start < from) + memset(kaddr+block_start, 0, from-block_start); continue; } } if (!buffer_uptodate(bh) && - (block_start < zerofrom || block_end > to)) { + (block_start < from || block_end > to)) { ll_rw_block(READ, 1, &bh); *wait_bh++=bh; } @@ -1493,39 +1481,26 @@ int block_write_zero_range(struct inode *inode, struct page *page, if (!buffer_uptodate(*wait_bh)) goto out; } - /* - * Now we can copy the data. - */ - if (zerofrom < from) - memset(kaddr+zerofrom, 0, from-zerofrom); - if (from < to) - err = copy_from_user(kaddr+from, buf, to-from); - if (to < zeroto) - memset(kaddr+to, 0, zeroto-to); - else - zeroto = to; - if (err < 0) - goto out; - /* - * Second pass: check if all out-of-range blocks are up-to-date - * and mark the rest up-to-date and dirty. - * - * NOTE! This also does a direct dirty balace check, - * rather than relying on bdflush just waking up every - * once in a while. This is to catch (and slow down) - * the processes that write tons of buffer.. - * - * Note how we do NOT want to do this in the full block - * case: full pages are flushed not by the people who - * dirtied them, but by people who need memory. And we - * should not penalize them for somebody else writing - * lots of dirty pages. - */ - for(bh = head, block_start = 0; + return 0; +out: + return err; +} + +static int __block_commit_write(struct inode *inode, struct page *page, + unsigned from, unsigned to) +{ + unsigned block_start, block_end; + int partial = 0, need_balance_dirty = 0; + unsigned blocksize; + struct buffer_head *bh, *head; + + blocksize = inode->i_sb->s_blocksize; + + for(bh = head = page->buffers, block_start = 0; bh != head || !block_start; block_start=block_end, bh = bh->b_this_page) { block_end = block_start + blocksize; - if (block_end <= zerofrom || block_start >= zeroto) { + if (block_end <= from || block_start >= to) { if (!buffer_uptodate(bh)) partial = 1; } else { @@ -1547,51 +1522,202 @@ int block_write_zero_range(struct inode *inode, struct page *page, */ if (!partial) SetPageUptodate(page); - kunmap(page); return 0; -out: - ClearPageUptodate(page); - kunmap(page); - return err; } -int block_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) +/* + * Generic "read page" function for block devices that have the normal + * get_block functionality. This is most of the block device filesystems. + * Reads the page asynchronously --- the unlock_buffer() and + * mark_buffer_uptodate() functions propagate buffer state into the + * page struct once IO has completed. + */ +static inline int __block_read_full_page(struct inode *inode, struct page *page, + get_block_t *get_block) { - struct inode *inode = file->f_dentry->d_inode; - int err; + unsigned long iblock; + struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; + unsigned int blocksize, blocks; + unsigned long kaddr = 0; + int nr, i; if (!PageLocked(page)) - BUG(); - if (offset < 0 || offset >= PAGE_SIZE) - BUG(); - if (bytes+offset < 0 || bytes+offset > PAGE_SIZE) - BUG(); + PAGE_BUG(page); + blocksize = inode->i_sb->s_blocksize; + if (!page->buffers) + create_empty_buffers(page, inode, blocksize); + head = page->buffers; + + blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits; + iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); + bh = head; + nr = 0; + i = 0; + + do { + if (buffer_uptodate(bh)) + continue; + + if (!buffer_mapped(bh)) { + get_block(inode, iblock, bh, 0); + if (!buffer_mapped(bh)) { + if (!kaddr) + kaddr = kmap(page); + memset((char *)(kaddr + i*blocksize), 0, blocksize); + set_bit(BH_Uptodate, &bh->b_state); + continue; + } + } + + init_buffer(bh, end_buffer_io_async, NULL); + atomic_inc(&bh->b_count); + arr[nr] = bh; + nr++; + } while (i++, iblock++, (bh = bh->b_this_page) != head); - err = block_write_range(inode, page, offset, bytes, buf); - return err ? err : bytes; + ++current->maj_flt; + if (nr) { + if (Page_Uptodate(page)) + BUG(); + ll_rw_block(READ, nr, arr); + } else { + /* + * all buffers are uptodate - we can set the page + * uptodate as well. + */ + SetPageUptodate(page); + UnlockPage(page); + } + if (kaddr) + kunmap(page); + return 0; } /* * For moronic filesystems that do not allow holes in file. - * we allow offset==PAGE_SIZE, bytes==0 + * We may have to extend the file. */ -int block_write_cont_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) +int cont_prepare_write(struct page *page, unsigned offset, unsigned to, get_block_t *get_block, unsigned long *bytes) +{ + struct address_space *mapping = page->mapping; + struct inode *inode = (struct inode*)mapping->host; + struct page *new_page; + unsigned long pgpos; + long status; + unsigned zerofrom; + unsigned blocksize = inode->i_sb->s_blocksize; + char *kaddr; + + while(page->index > (pgpos = *bytes>>PAGE_CACHE_SHIFT)) { + status = -ENOMEM; + new_page = grab_cache_page(mapping, pgpos); + if (!new_page) + goto out; + /* we might sleep */ + if (*bytes>>PAGE_CACHE_SHIFT != pgpos) { + UnlockPage(new_page); + page_cache_release(new_page); + continue; + } + zerofrom = *bytes & ~PAGE_CACHE_MASK; + if (zerofrom & (blocksize-1)) { + *bytes |= (blocksize-1); + (*bytes)++; + } + status = __block_prepare_write(inode, new_page, zerofrom, + PAGE_CACHE_SIZE, get_block); + if (status) + goto out_unmap; + kaddr = (char*)page_address(page); + memset(kaddr+zerofrom, 0, PAGE_CACHE_SIZE-zerofrom); + __block_commit_write(inode, new_page, zerofrom, to); + kunmap(new_page); + UnlockPage(new_page); + page_cache_release(new_page); + } + + if (page->index < pgpos) { + /* completely inside the area */ + zerofrom = offset; + } else { + /* page covers the boundary, find the boundary offset */ + zerofrom = *bytes & ~PAGE_CACHE_MASK; + + /* if we will expand the thing last block will be filled */ + if (to > zerofrom && (zerofrom & (blocksize-1))) { + *bytes |= (blocksize-1); + (*bytes)++; + } + + /* starting below the boundary? Nothing to zero out */ + if (offset <= zerofrom) + zerofrom = offset; + } + status = __block_prepare_write(inode, page, zerofrom, to, get_block); + if (status) + goto out1; + kaddr = (char*)page_address(page); + if (zerofrom < offset) { + memset(kaddr+zerofrom, 0, offset-zerofrom); + __block_commit_write(inode, page, zerofrom, offset); + } + return 0; +out1: + ClearPageUptodate(page); + kunmap(page); + return status; + +out_unmap: + ClearPageUptodate(new_page); + kunmap(new_page); + UnlockPage(new_page); + page_cache_release(new_page); +out: + return status; +} + +int block_prepare_write(struct page *page, unsigned from, unsigned to, + get_block_t *get_block) { - struct inode *inode = file->f_dentry->d_inode; - int err; - unsigned zerofrom = offset; + struct inode *inode = (struct inode*)page->mapping->host; + int err = __block_prepare_write(inode, page, from, to, get_block); + if (err) { + ClearPageUptodate(page); + kunmap(page); + } + return err; +} + +int generic_commit_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + __block_commit_write((struct inode*)page->mapping->host,page,from,to); + kunmap(page); + return 0; +} + +int block_write_full_page(struct page *page, get_block_t *get_block) +{ + struct inode *inode = (struct inode*)page->mapping->host; + return __block_write_full_page(inode, page, get_block); +} - if (page->index > (inode->i_size >> PAGE_CACHE_SHIFT)) - zerofrom = 0; - else if (page->index == (inode->i_size >> PAGE_CACHE_SHIFT) && - offset > (inode->i_size & ~PAGE_CACHE_MASK)) - zerofrom = inode->i_size & ~PAGE_CACHE_MASK; - err = block_write_zero_range(inode, page, zerofrom,offset,offset+bytes, - buf); - return err ? err : bytes; +int block_read_full_page(struct page *page, get_block_t *get_block) +{ + struct inode *inode = (struct inode*)page->mapping->host; + return __block_read_full_page(inode, page, get_block); } +int generic_block_bmap(struct address_space *mapping, long block, get_block_t *get_block) +{ + struct buffer_head tmp; + struct inode *inode = (struct inode*)mapping->host; + tmp.b_state = 0; + tmp.b_blocknr = 0; + get_block(inode, block, &tmp, 0); + return tmp.b_blocknr; +} /* * IO completion routine for a buffer_head being used for kiobuf IO: we @@ -1869,93 +1995,22 @@ int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size) return 0; } -/* - * Generic "read page" function for block devices that have the normal - * get_block functionality. This is most of the block device filesystems. - * Reads the page asynchronously --- the unlock_buffer() and - * mark_buffer_uptodate() functions propagate buffer state into the - * page struct once IO has completed. - */ -static inline int __block_read_full_page(struct inode *inode, struct page *page) -{ - unsigned long iblock; - struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; - unsigned int blocksize, blocks; - unsigned long kaddr = 0; - int nr, i; - - if (!PageLocked(page)) - PAGE_BUG(page); - blocksize = inode->i_sb->s_blocksize; - if (!page->buffers) - create_empty_buffers(page, inode, blocksize); - head = page->buffers; - - blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits; - iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); - bh = head; - nr = 0; - i = 0; - - do { - if (buffer_uptodate(bh)) - continue; - - if (!buffer_mapped(bh)) { - inode->i_op->get_block(inode, iblock, bh, 0); - if (!buffer_mapped(bh)) { - if (!kaddr) - kaddr = kmap(page); - memset((char *)(kaddr + i*blocksize), 0, blocksize); - set_bit(BH_Uptodate, &bh->b_state); - continue; - } - } - - init_buffer(bh, end_buffer_io_async, NULL); - atomic_inc(&bh->b_count); - arr[nr] = bh; - nr++; - } while (i++, iblock++, (bh = bh->b_this_page) != head); - - ++current->maj_flt; - if (nr) { - if (Page_Uptodate(page)) - BUG(); - ll_rw_block(READ, nr, arr); - } else { - /* - * all buffers are uptodate - we can set the page - * uptodate as well. - */ - SetPageUptodate(page); - UnlockPage(page); - } - if (kaddr) - kunmap(page); - return 0; -} - -int block_read_full_page(struct dentry *dentry, struct page *page) -{ - return __block_read_full_page(dentry->d_inode, page); -} - int block_symlink(struct inode *inode, const char *symname, int len) { - struct page *page = grab_cache_page(&inode->i_data, 0); - mm_segment_t fs; + struct address_space *mapping = inode->i_mapping; + struct page *page = grab_cache_page(mapping, 0); int err = -ENOMEM; + char *kaddr; if (!page) goto fail; - fs = get_fs(); - set_fs(KERNEL_DS); - err = block_write_range(inode, page, 0, len-1, symname); - set_fs(fs); - inode->i_size = len-1; + err = mapping->a_ops->prepare_write(page, 0, len-1); if (err) - goto fail_write; + goto fail_map; + kaddr = (char*)page_address(page); + memcpy(kaddr, symname, len-1); + mapping->a_ops->commit_write(NULL, page, 0, len-1); + inode->i_size = len-1; /* * Notice that we are _not_ going to block here - end of page is * unmapped, so this will only try to map the rest of page, see @@ -1963,14 +2018,15 @@ int block_symlink(struct inode *inode, const char *symname, int len) * ->i_size will be enough for everything) and zero it out. * OTOH it's obviously correct and should make the page up-to-date. */ - err = __block_read_full_page(inode, page); + err = mapping->a_ops->readpage(NULL, page); wait_on_page(page); page_cache_release(page); if (err < 0) goto fail; mark_inode_dirty(inode); return 0; -fail_write: +fail_map: + inode->i_size = len-1; UnlockPage(page); page_cache_release(page); fail: diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index faa983e0f428..88e954eeb738 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -39,12 +39,62 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) inode->i_op = &coda_file_inode_operations; else if (S_ISDIR(inode->i_mode)) inode->i_op = &coda_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &coda_symlink_inode_operations; - else + else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &coda_symlink_aops; + } else init_special_inode(inode, inode->i_mode, attr->va_rdev); } +struct inode * coda_iget(struct super_block * sb, ViceFid * fid, + struct coda_vattr * attr) +{ + struct inode *inode; + struct coda_sb_info *sbi= coda_sbp(sb); + struct coda_inode_info *cii; + ino_t ino = attr->va_fileid; + + inode = iget(sb, ino); + if ( !inode ) { + CDEBUG(D_CNODE, "coda_iget: no inode\n"); + return NULL; + } + + /* check if the inode is already initialized */ + cii = ITOC(inode); + if (cii->c_magic == CODA_CNODE_MAGIC) + goto out; + + /* Initialize the Coda inode info structure */ + memset(cii, 0, (int) sizeof(struct coda_inode_info)); + cii->c_magic = CODA_CNODE_MAGIC; + cii->c_fid = *fid; + cii->c_flags = 0; + cii->c_vnode = inode; + INIT_LIST_HEAD(&(cii->c_cnhead)); + INIT_LIST_HEAD(&(cii->c_volrootlist)); + + coda_fill_inode(inode, attr); + + /* check if it is a weird fid (hashed fid != ino), f.i mountpoints + repair object, expanded local-global conflict trees, etc. + */ + if ( coda_f2i(fid) == ino ) + goto out; + + /* check if we expect this weird fid */ + if ( !coda_fid_is_weird(fid) ) + printk("Coda: unknown weird fid: ino %ld, fid %s." + "Tell Peter.\n", (long)ino, coda_f2s(&cii->c_fid)); + + /* add the inode to a global list so we can find it back later */ + list_add(&cii->c_volrootlist, &sbi->sbi_volroothead); + CDEBUG(D_CNODE, "Added %ld, %s to volroothead\n", + (long)ino, coda_f2s(&cii->c_fid)); +out: + return inode; +} + /* this is effectively coda_iget: - get attributes (might be cached) - get the inode for the fid using vfs iget @@ -54,16 +104,12 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) { struct coda_inode_info *cnp; - struct coda_sb_info *sbi= coda_sbp(sb); struct coda_vattr attr; int error; - ino_t ino; ENTRY; - /* - * We get inode numbers from Venus -- see venus source - */ + /* We get inode numbers from Venus -- see venus source */ error = venus_getattr(sb, fid, &attr); if ( error ) { @@ -74,53 +120,29 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) return error; } - ino = attr.va_fileid; - *inode = iget(sb, ino); - if ( !*inode ) { - printk("coda_cnode_make: iget failed\n"); + *inode = coda_iget(sb, fid, &attr); + if ( !(*inode) ) { + printk("coda_cnode_make: coda_iget failed\n"); return -ENOMEM; } cnp = ITOC(*inode); - /* see if we've got it already */ - if ( cnp->c_magic != 0 && coda_fideq(fid, &cnp->c_fid)) { + /* see if it is the right one (we might have an inode collision) */ + if ( coda_fideq(fid, &cnp->c_fid) ) { + CDEBUG(D_DOWNCALL, + "Done making inode: ino %ld, count %d with %s\n", + (*inode)->i_ino, (*inode)->i_count, + coda_f2s(&cnp->c_fid)); + EXIT; return 0; } - /* not fresh: collision */ - if ( cnp->c_magic != 0 ) { - printk("coda_cnode_make on initialized inode %ld, old %s new -%s!\n", + /* collision */ + printk("coda_cnode_make on initialized inode %ld, old %s new %s!\n", (*inode)->i_ino, coda_f2s(&cnp->c_fid), coda_f2s2(fid)); iput(*inode); - return -ENOENT; - } - - memset(cnp, 0, (int) sizeof(struct coda_inode_info)); - cnp->c_fid = *fid; - cnp->c_magic = CODA_CNODE_MAGIC; - cnp->c_flags = 0; - cnp->c_vnode = *inode; - INIT_LIST_HEAD(&(cnp->c_cnhead)); - INIT_LIST_HEAD(&(cnp->c_volrootlist)); - - /* fill in the inode attributes */ - if ( coda_f2i(fid) != ino ) { - if ( !coda_fid_is_weird(fid) ) - printk("Coda: unknown weird fid: ino %ld, fid %s." - "Tell Peter.\n", (long)ino, coda_f2s(&cnp->c_fid)); - list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead); - CDEBUG(D_UPCALL, "Added %ld ,%s to volroothead\n", - (long)ino, coda_f2s(&cnp->c_fid)); - } - - coda_fill_inode(*inode, &attr); - CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n", - (*inode)->i_ino, (*inode)->i_count, - coda_f2s(&cnp->c_fid)); - EXIT; - return 0; + return -ENOENT; } @@ -183,11 +205,13 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) coda_f2s(&cii->c_fid), cii->c_vnode->i_ino); if ( coda_fideq(&cii->c_fid, fid) ) { inode = cii->c_vnode; - CDEBUG(D_INODE, "volume root, found %ld\n", cii->c_vnode->i_ino); + CDEBUG(D_INODE, "volume root, found %ld\n", inode->i_ino); if ( cii->c_magic != CODA_CNODE_MAGIC ) printk("%s: Bad magic in inode, tell Peter.\n", __FUNCTION__); - return cii->c_vnode; + + iget(sb, inode->i_ino); + return inode; } } @@ -224,7 +248,6 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) } CDEBUG(D_INODE, "found %ld\n", inode->i_ino); - iput(inode); return inode; } diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c index 5f2f3c4674ce..4a7bebb6236c 100644 --- a/fs/coda/coda_linux.c +++ b/fs/coda/coda_linux.c @@ -102,7 +102,6 @@ int coda_fid_is_weird(struct ViceFid *fid) return 1; return 0; - } @@ -290,7 +289,6 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr) vattr->va_ctime.tv_sec = iattr->ia_ctime; vattr->va_ctime.tv_nsec = 0; } - } void print_vattr(struct coda_vattr *attr) diff --git a/fs/coda/dir.c b/fs/coda/dir.c index bfc975409e0a..3eecd4a5a95e 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -77,9 +77,6 @@ struct inode_operations coda_dir_inode_operations = coda_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ coda_permission, /* permission */ coda_revalidate_inode /* revalidate */ @@ -199,7 +196,6 @@ int coda_permission(struct inode *inode, int mask) } - /* creation routines: create, mknod, mkdir, link, symlink */ static int coda_create(struct inode *dir, struct dentry *de, int mode) @@ -260,7 +256,8 @@ static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev) coda_vfs_stat.create++; - CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",name, length, mode, rdev); + CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n", + name, length, mode, rdev); if (coda_isroot(dir) && coda_iscontrol(name, length)) return -EPERM; @@ -521,7 +518,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, } - /* file operations for directories */ int coda_readdir(struct file *file, void *dirent, filldir_t filldir) { @@ -600,11 +596,11 @@ int coda_open(struct inode *i, struct file *f) coda_load_creds(cred); f->private_data = cred; - if ( cnp->c_ovp ) { + if ( cnp->c_ovp ) iput(cnp->c_ovp); - cnp->c_ovp = NULL; - } + cnp->c_ovp = cont_inode; + i->i_mapping = cont_inode->i_mapping; cnp->c_ocount++; CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n", @@ -619,7 +615,7 @@ int coda_open(struct inode *i, struct file *f) int coda_release(struct inode *i, struct file *f) { struct coda_inode_info *cnp; - int error; + int error = 0; unsigned short flags = (f->f_flags) & (~O_EXCL); unsigned short cflags = coda_flags_to_cflags(flags); struct coda_cred *cred; @@ -645,14 +641,17 @@ int coda_release(struct inode *i, struct file *f) --cnp->c_ocount; - if (flags & (O_WRONLY | O_RDWR)) { + if ( flags & (O_WRONLY | O_RDWR) ) --cnp->c_owrite; - } + /* Venus closing a container file? don't bother making the upcall. */ + if ( current->pid != coda_upc_comm.vc_pid ) { error = venus_release(i->i_sb, &(cnp->c_fid), cflags, cred); + } - CODA_FREE(cred, sizeof(*cred)); f->private_data = NULL; + if (cred) + CODA_FREE(cred, sizeof(*cred)); CDEBUG(D_FILE, "coda_release: result: %d\n", error); return error; @@ -850,19 +849,18 @@ int coda_revalidate_inode(struct dentry *dentry) if ( cii->c_flags == 0 ) return 0; - /* Venus closed the device .... */ - if ( cii->c_flags & C_DYING ) { - make_bad_inode(inode); - return -EIO; - } + /* Venus accessing a container file, don't try to revalidate */ + if ( current->pid == coda_upc_comm.vc_pid ) + return 0; + /* Venus closed the device .... */ + if ( cii->c_flags & C_DYING ) + goto return_bad_inode; if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); - if ( error ) { - make_bad_inode(inode); - return -EIO; - } + if ( error ) + goto return_bad_inode; /* this inode may be lost if: - it's ino changed @@ -880,12 +878,9 @@ int coda_revalidate_inode(struct dentry *dentry) } /* the following can happen when a local fid is replaced - with a global one, here we lose and declar the inode bad */ - if (inode->i_ino != old_ino) { - make_bad_inode(inode); - inode->i_mode = old_mode; - return -EIO; - } + with a global one, here we lose and declare the inode bad */ + if (inode->i_ino != old_ino) + goto return_bad_inode; if ( cii->c_flags ) coda_flag_inode_children(inode, C_FLUSH); @@ -894,5 +889,14 @@ int coda_revalidate_inode(struct dentry *dentry) } return 0; + +return_bad_inode: + if ( cii->c_ovp ) { + iput(cii->c_ovp); + inode->i_mapping = &inode->i_data; + cii->c_ovp = NULL; + } + make_bad_inode(inode); + return -EIO; } diff --git a/fs/coda/file.c b/fs/coda/file.c index 054afdf2dbee..82f66111176d 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -27,9 +27,6 @@ #include /* file operations */ -static int coda_readpage(struct dentry *dentry, struct page * page); -static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off); -static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off); static int coda_file_mmap(struct file * file, struct vm_area_struct * vma); /* also exported from this file (used for dirs) */ @@ -48,50 +45,21 @@ struct inode_operations coda_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - coda_readpage, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ coda_permission, /* permission */ coda_revalidate_inode /* revalidate */ }; struct file_operations coda_file_operations = { - read: coda_file_read, - write: coda_file_write, + read: generic_file_read, + write: generic_file_write, mmap: coda_file_mmap, open: coda_open, release: coda_release, fsync: coda_fsync, }; - -/* File file operations */ -static int coda_readpage(struct dentry * dentry, struct page * page) -{ - struct inode *coda_inode = dentry->d_inode; - struct dentry cont_dentry; - struct coda_inode_info *cii; - - ENTRY; - coda_vfs_stat.readpage++; - - cii = ITOC(coda_inode); - - if ( ! cii->c_ovp ) { - printk("coda_readpage: no open inode for ino %ld, %s\n", - coda_inode->i_ino, dentry->d_name.name); - return -ENXIO; - } - - cont_dentry.d_inode = cii->c_ovp; - - CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", - coda_inode->i_ino, cii->c_ovp->i_ino, page->index); - - block_read_full_page(&cont_dentry, page); - EXIT; - return 0; -} + +/* File operations */ static int coda_file_mmap(struct file * file, struct vm_area_struct * vma) { @@ -109,89 +77,6 @@ static int coda_file_mmap(struct file * file, struct vm_area_struct * vma) return res; } -static ssize_t coda_file_read(struct file *coda_file, char *buff, - size_t count, loff_t *ppos) -{ - struct coda_inode_info *cnp; - struct inode *coda_inode = coda_file->f_dentry->d_inode; - struct inode *cont_inode = NULL; - struct file cont_file; - struct dentry cont_dentry; - int result = 0; - - ENTRY; - coda_vfs_stat.file_read++; - - cnp = ITOC(coda_inode); - CHECK_CNODE(cnp); - - cont_inode = cnp->c_ovp; - if ( cont_inode == NULL ) { - printk("coda_file_read: cached inode is 0!\n"); - return -1; - } - - coda_prepare_openfile(coda_inode, coda_file, cont_inode, - &cont_file, &cont_dentry); - - if (!cont_file.f_op || ! cont_file.f_op->read) { - printk( "container file has no read in file operations.\n"); - return -1; - } - - result = cont_file.f_op->read(&cont_file , buff, count, - &(cont_file.f_pos)); - - CDEBUG(D_FILE, "ops at %p result %d, count %ld, position: %d\n", - cont_file.f_op, result, (long)count, (int)cont_file.f_pos); - - coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file); - return result; -} - - -static ssize_t coda_file_write(struct file *coda_file, const char *buff, - size_t count, loff_t *ppos) -{ - struct coda_inode_info *cnp; - struct inode *coda_inode = coda_file->f_dentry->d_inode; - struct inode *cont_inode = NULL; - struct file cont_file; - struct dentry cont_dentry; - int result = 0; - - ENTRY; - coda_vfs_stat.file_write++; - - cnp = ITOC(coda_inode); - CHECK_CNODE(cnp); - - cont_inode = cnp->c_ovp; - if ( cont_inode == NULL ) { - printk("coda_file_write: cached inode is 0!\n"); - return -1; - } - - coda_prepare_openfile(coda_inode, coda_file, cont_inode, - &cont_file, &cont_dentry); - - if (!cont_file.f_op || !cont_file.f_op->write) { - printk("coda_file_write: container file has no file ops.\n"); - return -1; - } - - down(&cont_inode->i_sem); - result = cont_file.f_op->write(&cont_file , buff, count, - &(cont_file.f_pos)); - up(&cont_inode->i_sem); - coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file); - - if (result) - cnp->c_flags |= C_VATTR; - - return result; -} - int coda_fsync(struct file *coda_file, struct dentry *coda_dentry) { struct coda_inode_info *cnp; @@ -281,8 +166,8 @@ int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind) *ind = iget(sbptr, ino); if ( *ind == NULL ) { - printk("coda_inode_grab: iget(dev: %d, ino: %ld) - returns NULL.\n", dev, (long)ino); + printk("coda_inode_grab: iget(dev: %d, ino: %ld) " + "returns NULL.\n", dev, (long)ino); return -ENOENT; } CDEBUG(D_FILE, "ino: %ld, ops at %p\n", (long)ino, (*ind)->i_op); diff --git a/fs/coda/inode.c b/fs/coda/inode.c index e2f2931b1fb3..b389b623e3b2 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -52,7 +52,9 @@ struct super_operations coda_super_operations = coda_put_super, /* put_super */ NULL, /* write_super */ coda_statfs, /* statfs */ - NULL /* remount_fs */ + NULL, /* remount_fs */ + NULL, /* no clear inode */ + NULL /* umount attempt begin */ }; static struct super_block * coda_read_super(struct super_block *sb, @@ -163,15 +165,16 @@ static void coda_read_inode(struct inode *inode) return; } -static void coda_put_inode(struct inode *in) +static void coda_put_inode(struct inode *inode) { ENTRY; - CDEBUG(D_INODE,"ino: %ld, count %d\n", in->i_ino, in->i_count); - - if ( in->i_count == 1 ) - in->i_nlink = 0; + CDEBUG(D_INODE,"ino: %ld, count %d\n", inode->i_ino, inode->i_count); + if ( inode->i_count == 1 ) { + write_inode_now(inode); + inode->i_nlink = 0; + } } static void coda_delete_inode(struct inode *inode) @@ -189,15 +192,17 @@ static void coda_delete_inode(struct inode *inode) return; } - - if ( ! list_empty(&cii->c_volrootlist) ) + if ( ! list_empty(&cii->c_volrootlist) ) { list_del(&cii->c_volrootlist); + INIT_LIST_HEAD(&cii->c_volrootlist); + } open_inode = cii->c_ovp; if ( open_inode ) { CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n", open_inode->i_ino, open_inode->i_count); cii->c_ovp = NULL; + inode->i_mapping = &inode->i_data; iput(open_inode); } diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 3f813c2f1fcc..9a900a91aa87 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -46,9 +46,6 @@ struct inode_operations coda_ioctl_inode_operations = NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ coda_ioctl_permission, /* permission */ NULL /* revalidate */ @@ -71,7 +68,6 @@ static int coda_ioctl_permission(struct inode *inode, int mask) /* The pioctl file ops*/ int coda_ioctl_open(struct inode *i, struct file *f) { - ENTRY; CDEBUG(D_PIOCTL, "File inode number: %ld\n", diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index dbabfa9c309c..07ba223352ac 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -76,6 +76,21 @@ static unsigned int coda_psdev_poll(struct file *file, poll_table * wait) return mask; } +static int coda_psdev_ioctl(struct inode * inode, struct file * filp, + unsigned int cmd, unsigned long arg) +{ + unsigned int data; + + switch(cmd) { + case CIOC_KERNEL_VERSION: + data = CODA_KERNEL_VERSION; + return put_user(data, (int *) arg); + default: + return -ENOTTY; + } + + return 0; +} /* * Receive a message written by Venus to the psdev @@ -246,7 +261,6 @@ static int coda_psdev_open(struct inode * inode, struct file * file) vcp->vc_inuse++; MOD_INC_USE_COUNT; - if ( file->f_flags == O_RDWR ) { vcp->vc_pid = current->pid; vcp->vc_seq = 0; @@ -262,7 +276,6 @@ static int coda_psdev_open(struct inode * inode, struct file * file) } - static int coda_psdev_release(struct inode * inode, struct file * file) { struct venus_comm *vcp = &coda_upc_comm; @@ -298,6 +311,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file) CODA_FREE(req, (u_int)sizeof(struct upc_req)); continue; } + req->uc_flags |= REQ_ABORT; wake_up(&req->uc_sleep); } @@ -305,6 +319,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file) CDEBUG(D_PSDEV, "wake up processing clients\n"); while ( (lh = lh->next) != &vcp->vc_processing) { req = list_entry(lh, struct upc_req, uc_chain); + req->uc_flags |= REQ_ABORT; wake_up(&req->uc_sleep); } CDEBUG(D_PSDEV, "Done.\n"); @@ -318,6 +333,7 @@ static struct file_operations coda_psdev_fops = { read: coda_psdev_read, write: coda_psdev_write, poll: coda_psdev_poll, + ioctl: coda_psdev_ioctl, open: coda_psdev_open, release: coda_psdev_release, }; diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c index 872370cf9fcd..d44d0f7c3d2e 100644 --- a/fs/coda/symlink.c +++ b/fs/coda/symlink.c @@ -48,8 +48,6 @@ fail: return error; } -struct inode_operations coda_symlink_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, +struct address_space_operations coda_symlink_aops = { readpage: coda_symlink_filler }; diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index 0461533628e7..289f9417c38e 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -109,7 +109,8 @@ char *coda_upcall_names[] = { "open_by_path", /* 31 */ "resolve ", /* 32 */ "reintegrate ", /* 33 */ - "statfs " /* 34 */ + "statfs ", /* 34 */ + "make_cinode " /* 35 */ }; @@ -214,8 +215,8 @@ unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pen return 0; time_avg = get_time_average( pentry ); - return - sqr_root( (pentry->time_squared_sum / pentry->count) - + + return sqr_root( (pentry->time_squared_sum / pentry->count) - time_avg * time_avg ); } diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index fe86dbac9419..63586d05cb06 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -630,7 +631,7 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp) set_current_state(TASK_UNINTERRUPTIBLE); /* got a reply */ - if ( vmp->uc_flags & REQ_WRITE ) + if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) ) break; if ( !coda_hard && signal_pending(current) ) { @@ -845,7 +846,6 @@ ENTRY; int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) { - /* Handle invalidation requests. */ if ( !sb || !sb->s_root || !sb->s_root->d_inode) { printk("coda_downcall: opcode %d, no sb!\n", opcode); @@ -878,7 +878,8 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) case CODA_ZAPDIR : { struct inode *inode; ViceFid *fid = &out->coda_zapdir.CodaFid; - CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", coda_f2s(fid)); + CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", + coda_f2s(fid)); clstats(CODA_ZAPDIR); inode = coda_fid_to_inode(fid, sb); @@ -888,6 +889,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) coda_flag_inode_children(inode, C_PURGE); CDEBUG(D_DOWNCALL, "zapdir: inode = %ld cache cleared\n", inode->i_ino); coda_flag_inode(inode, C_VATTR); + iput(inode); } else CDEBUG(D_DOWNCALL, "zapdir: no inode\n"); @@ -898,11 +900,14 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) struct inode *inode; struct ViceFid *fid = &out->coda_zapfile.CodaFid; clstats(CODA_ZAPFILE); - CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid)); + CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", + coda_f2s(fid)); inode = coda_fid_to_inode(fid, sb); if ( inode ) { - CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n", inode->i_ino); + CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n", + inode->i_ino); coda_flag_inode(inode, C_VATTR); + iput(inode); } else CDEBUG(D_DOWNCALL, "zapfile: no inode\n"); return 0; @@ -911,18 +916,61 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) case CODA_PURGEFID : { struct inode *inode; ViceFid *fid = &out->coda_purgefid.CodaFid; - CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid)); + CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", + coda_f2s(fid)); clstats(CODA_PURGEFID); inode = coda_fid_to_inode(fid, sb); if ( inode ) { - CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n", inode->i_ino); + CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n", + inode->i_ino); coda_flag_inode_children(inode, C_PURGE); coda_purge_dentries(inode); + iput(inode); }else CDEBUG(D_DOWNCALL, "purgefid: no inode\n"); return 0; } + case CODA_MAKE_CINODE : { + struct inode *inode; + ViceFid *fid = &out->coda_make_cinode.CodaFid; + struct coda_vattr *attr = &out->coda_make_cinode.attr; + int fd = out->coda_make_cinode.fd; + struct file *file; + CDEBUG(D_DOWNCALL, "make_cinode: fid = %s, ino = %ld\n", + coda_f2s(fid), attr->va_fileid); + + inode = coda_iget(sb, fid, attr); + if ( !inode ) { + CDEBUG(D_DOWNCALL, "make_cinode: no inode\n"); + return -EINVAL; + } + + file = fget(fd); + if ( !file ) { + CDEBUG(D_DOWNCALL, "make_cinode: no file\n"); + iput(inode); + return -EINVAL; + } + + inode->u.coda_i.c_ovp = file->f_dentry->d_inode; + inode->i_mapping = file->f_dentry->d_inode->i_mapping; + file->f_dentry->d_inode = inode; + file->f_op = &coda_file_operations; + + /* + Unhash the dentry of the container file, as it is + still owned by the fs that stores the container + file. A more reliable solution would be to create + an new dentry owned by Coda, but that would require + knowledge of the internals of the dcache. + */ + d_drop(file->f_dentry); + + fput(file); + return 0; + } + case CODA_REPLACE : { struct inode *inode; ViceFid *oldfid = &out->coda_replace.OldFid; @@ -933,6 +981,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) if ( inode ) { CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino); coda_replace_fid(inode, oldfid, newfid); + iput(inode); }else CDEBUG(D_DOWNCALL, "purgefid: no inode\n"); @@ -942,5 +991,3 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) return 0; } - - diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 0e04600d50fa..b9ab3c4c4508 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -25,7 +25,7 @@ static struct super_operations cramfs_ops; static struct inode_operations cramfs_file_inode_operations; static struct inode_operations cramfs_dir_inode_operations; -static struct inode_operations cramfs_symlink_inode_operations; +static struct address_space_operations cramfs_aops; /* These two macros may change in future, to provide better st_ino semantics. */ @@ -51,13 +51,15 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod result in GNU find, even without -noleaf option. */ insert_inode_hash(inode); - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { inode->i_op = &cramfs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_data.a_ops = &cramfs_aops; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &cramfs_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &cramfs_symlink_inode_operations; - else { + else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &cramfs_aops; + } else { inode->i_size = 0; init_special_inode(inode, inode->i_mode, cramfs_inode->size); } @@ -344,53 +346,9 @@ static int cramfs_readpage(struct dentry *dentry, struct page * page) return 0; } -static struct page *get_symlink_page(struct dentry *dentry) -{ - return read_cache_page(&dentry->d_inode->i_data, 0, (filler_t *)cramfs_readpage, dentry); -} - -static int cramfs_readlink(struct dentry *dentry, char *buffer, int len) -{ - struct inode *inode = dentry->d_inode; - int retval; - - if (!inode || !S_ISLNK(inode->i_mode)) - return -EBADF; - - retval = inode->i_size; - if (retval) { - int len; - struct page *page = get_symlink_page(dentry); - - if (IS_ERR(page)) - return PTR_ERR(page); - wait_on_page(page); - len = retval; - retval = -EIO; - if (Page_Uptodate(page)) { - retval = -EFAULT; - if (!copy_to_user(buffer, (void *) page_address(page), len)) - retval = len; - } - page_cache_release(page); - } - return retval; -} - -static struct dentry *cramfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) -{ - struct page *page = get_symlink_page(dentry); - struct dentry *result; - - if (IS_ERR(page)) { - dput(base); - return ERR_PTR(PTR_ERR(page)); - } - - result = lookup_dentry((void *) page_address(page), base, follow); - page_cache_release(page); - return result; -} +static struct address_space_operations cramfs_aops = { + readpage: cramfs_readpage +}; /* * Our operations: @@ -411,65 +369,12 @@ static struct file_operations cramfs_directory_operations = { static struct inode_operations cramfs_file_inode_operations = { &cramfs_file_operations, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - cramfs_readpage, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static struct inode_operations cramfs_dir_inode_operations = { &cramfs_directory_operations, NULL, /* create */ cramfs_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ -}; - -static struct inode_operations cramfs_symlink_inode_operations = { - NULL, /* symlinks do not have files */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - cramfs_readlink, /* readlink */ - cramfs_follow_link, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static struct super_operations cramfs_ops = { diff --git a/fs/devpts/root.c b/fs/devpts/root.c index cb814730616a..5af3967e210e 100644 --- a/fs/devpts/root.c +++ b/fs/devpts/root.c @@ -28,21 +28,6 @@ struct inode_operations devpts_root_inode_operations = { &devpts_root_operations, /* file operations */ NULL, /* create */ devpts_root_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static struct dentry_operations devpts_dentry_operations = { diff --git a/fs/efs/dir.c b/fs/efs/dir.c index c4d17248187d..1283f9fdc64f 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c @@ -12,27 +12,10 @@ static struct file_operations efs_dir_operations = { readdir: efs_readdir, }; -extern int efs_get_block(struct inode *, long, struct buffer_head *, int); - struct inode_operations efs_dir_inode_operations = { &efs_dir_operations, /* default directory file-ops */ NULL, /* create */ efs_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - efs_get_block, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { diff --git a/fs/efs/file.c b/fs/efs/file.c index 3106e192766d..3c6de9b287c1 100644 --- a/fs/efs/file.c +++ b/fs/efs/file.c @@ -68,21 +68,4 @@ static struct file_operations efs_file_operations = { struct inode_operations efs_file_inode_operations = { &efs_file_operations, /* default file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - efs_get_block, /* get_block */ - block_read_full_page, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; diff --git a/fs/efs/inode.c b/fs/efs/inode.c index 75903be12de3..0206ae6d5238 100644 --- a/fs/efs/inode.c +++ b/fs/efs/inode.c @@ -10,6 +10,20 @@ #include #include +extern int efs_get_block(struct inode *, long, struct buffer_head *, int); +static int efs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,efs_get_block); +} +static int _efs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,efs_get_block); +} +struct address_space_operations efs_aops = { + readpage: efs_readpage, + bmap: _efs_bmap +}; + static inline void extent_copy(efs_extent *src, efs_extent *dst) { /* * this is slightly evil. it doesn't just copy @@ -126,9 +140,11 @@ void efs_read_inode(struct inode *inode) { break; case S_IFREG: inode->i_op = &efs_file_inode_operations; + inode->i_data.a_ops = &efs_aops; break; case S_IFLNK: - inode->i_op = &efs_symlink_inode_operations; + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &efs_symlink_aops; break; case S_IFCHR: case S_IFBLK: diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c index 6bfc16be75ff..66776c7e5744 100644 --- a/fs/efs/symlink.c +++ b/fs/efs/symlink.c @@ -48,8 +48,6 @@ fail: return err; } -struct inode_operations efs_symlink_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, +struct address_space_operations efs_symlink_aops = { readpage: efs_symlink_readpage }; diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index b8a5c2f9d819..1d45d3514dff 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -51,14 +51,6 @@ struct inode_operations ext2_dir_inode_operations = { ext2_rmdir, /* rmdir */ ext2_mknod, /* mknod */ ext2_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; int ext2_check_dir_entry (const char * function, struct inode * dir, diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 70864a857571..5c463917520c 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -21,13 +21,6 @@ #include #include - - -#define NBUF 32 - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - static loff_t ext2_file_lseek(struct file *, loff_t, int); static int ext2_open_file (struct inode *, struct file *); @@ -73,40 +66,6 @@ static loff_t ext2_file_lseek( return offset; } -static inline void remove_suid(struct inode *inode) -{ - unsigned int mode; - - /* set S_IGID if S_IXGRP is set, and always set S_ISUID */ - mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID; - - /* was any of the uid bits set? */ - mode &= inode->i_mode; - if (mode && !capable(CAP_FSETID)) { - inode->i_mode &= ~mode; - mark_inode_dirty(inode); - } -} - -/* - * Write to a file (through the page cache). - */ -static ssize_t -ext2_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - ssize_t retval; - - retval = generic_file_write(file, buf, count, - ppos, block_write_partial_page); - if (retval > 0) { - struct inode *inode = file->f_dentry->d_inode; - remove_suid(inode); - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - mark_inode_dirty(inode); - } - return retval; -} - /* * Called when an inode is released. Note that this is different * from ext2_file_open: open gets called at every open, but release @@ -139,7 +98,7 @@ static int ext2_open_file (struct inode * inode, struct file * filp) static struct file_operations ext2_file_operations = { llseek: ext2_file_lseek, read: generic_file_read, - write: ext2_file_write, + write: generic_file_write, ioctl: ext2_ioctl, mmap: generic_file_mmap, open: ext2_open_file, @@ -148,22 +107,6 @@ static struct file_operations ext2_file_operations = { }; struct inode_operations ext2_file_inode_operations = { - &ext2_file_operations,/* default file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - ext2_get_block, /* get_block */ - block_read_full_page, /* readpage */ - block_write_full_page, /* writepage */ - ext2_truncate, /* truncate */ - NULL, /* permission */ - NULL, /* revalidate */ + &ext2_file_operations, + truncate: ext2_truncate, }; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index e92e4080a009..ab7ac0a96719 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -408,7 +408,7 @@ out: return result; } -int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) +static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) { int ret, err, new; struct buffer_head *bh; @@ -610,6 +610,30 @@ struct buffer_head * ext2_bread (struct inode * inode, int block, return NULL; } +static int ext2_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,ext2_get_block); +} +static int ext2_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,ext2_get_block); +} +static int ext2_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return block_prepare_write(page,from,to,ext2_get_block); +} +static int ext2_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,ext2_get_block); +} +struct address_space_operations ext2_aops = { + readpage: ext2_readpage, + writepage: ext2_writepage, + prepare_write: ext2_prepare_write, + commit_write: generic_commit_write, + bmap: ext2_bmap +}; + void ext2_read_inode (struct inode * inode) { struct buffer_head * bh; @@ -719,15 +743,19 @@ void ext2_read_inode (struct inode * inode) if (inode->i_ino == EXT2_ACL_IDX_INO || inode->i_ino == EXT2_ACL_DATA_INO) /* Nothing to do */ ; - else if (S_ISREG(inode->i_mode)) + else if (S_ISREG(inode->i_mode)) { inode->i_op = &ext2_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_mapping->a_ops = &ext2_aops; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &ext2_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = inode->i_blocks - ?&ext2_symlink_inode_operations - :&ext2_fast_symlink_inode_operations; - else + else if (S_ISLNK(inode->i_mode)) { + if (!inode->i_blocks) + inode->i_op = &ext2_fast_symlink_inode_operations; + else { + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &ext2_aops; + } + } else init_special_inode(inode, inode->i_mode, le32_to_cpu(raw_inode->i_block[0])); brelse (bh); diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 08136962a305..c2e5630ca2f8 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -384,6 +384,7 @@ int ext2_create (struct inode * dir, struct dentry * dentry, int mode) return err; inode->i_op = &ext2_file_inode_operations; + inode->i_mapping->a_ops = &ext2_aops; inode->i_mode = mode; mark_inode_dirty(inode); bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); @@ -696,7 +697,8 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam inode->i_mode = S_IFLNK | S_IRWXUGO; if (l > sizeof (inode->u.ext2_i.i_data)) { - inode->i_op = &ext2_symlink_inode_operations; + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &ext2_aops; err = block_symlink(inode, symname, l); if (err) goto out_no_entry; diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index 18fbbb368b4e..d56ef4c6276e 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -1,6 +1,8 @@ /* * linux/fs/ext2/symlink.c * + * Only fast symlinks left here - the rest is done by generic code. AV, 1999 + * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal @@ -16,7 +18,6 @@ */ #include -#include static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen) { @@ -34,10 +35,3 @@ struct inode_operations ext2_fast_symlink_inode_operations = { readlink: ext2_readlink, follow_link: ext2_follow_link, }; - -struct inode_operations ext2_symlink_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, - get_block: ext2_get_block, - readpage: block_read_full_page, -}; diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 45f4a800c42b..1751829598ab 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -283,7 +283,7 @@ int default_fat_bmap(struct inode *inode,int sector) return 0; return sector+sb->dir_start; } - if (sector >= (MSDOS_I(inode)->i_realsize>>9)) + if (sector >= MSDOS_I(inode)->mmu_private>>9) return 0; cluster = sector/sb->cluster_size; offset = sector % sb->cluster_size; diff --git a/fs/fat/file.c b/fs/fat/file.c index 830bc8eda554..0c535b8da218 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -50,12 +50,7 @@ struct inode_operations fat_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - fat_get_block, /* get_block */ - block_read_full_page, /* readpage */ - NULL, /* writepage */ fat_truncate, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; ssize_t fat_file_read( @@ -81,7 +76,7 @@ int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resul } if (!create) return 0; - if (iblock<<9 != MSDOS_I(inode)->i_realsize) { + if (iblock<<9 != MSDOS_I(inode)->mmu_private) { BUG(); return -EIO; } @@ -89,7 +84,7 @@ int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resul if (fat_add_cluster(inode)) return -ENOSPC; } - MSDOS_I(inode)->i_realsize+=SECTOR_SIZE; + MSDOS_I(inode)->mmu_private += 512; phys=fat_bmap(inode, iblock); if (!phys) BUG(); @@ -100,30 +95,6 @@ int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resul return 0; } -static int fat_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) -{ - struct dentry *dentry = file->f_dentry; - struct inode *inode = dentry->d_inode; - struct page *new_page; - unsigned long pgpos; - long status; - - while((pgpos=MSDOS_I(inode)->i_realsize>>PAGE_CACHE_SHIFT)index){ - status = -ENOMEM; - new_page = grab_cache_page(&inode->i_data, pgpos); - if (!new_page) - goto out; - status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL); - UnlockPage(new_page); - page_cache_release(new_page); - if (status < 0) - goto out; - } - status = block_write_cont_page(file, page, offset, bytes, buf); -out: - return status; -} - ssize_t fat_file_write( struct file *filp, const char *buf, @@ -145,8 +116,7 @@ ssize_t default_fat_file_write( struct inode *inode = filp->f_dentry->d_inode; int retval; - retval = generic_file_write(filp, buf, count, ppos, - fat_write_partial_page); + retval = generic_file_write(filp, buf, count, ppos); if (retval > 0) { inode->i_mtime = inode->i_ctime = CURRENT_TIME; MSDOS_I(inode)->i_attrs |= ATTR_ARCH; @@ -166,7 +136,7 @@ void fat_truncate(struct inode *inode) if (IS_IMMUTABLE(inode)) return /* -EPERM */; cluster = SECTOR_SIZE*sbi->cluster_size; - MSDOS_I(inode)->i_realsize = ((inode->i_size-1) | (SECTOR_SIZE-1)) + 1; + MSDOS_I(inode)->mmu_private = inode->i_size; fat_free(inode,(inode->i_size+(cluster-1))>>sbi->cluster_bits); MSDOS_I(inode)->i_attrs |= ATTR_ARCH; inode->i_ctime = inode->i_mtime = CURRENT_TIME; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 3919f651766d..90b28883265d 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -397,7 +397,7 @@ static void fat_read_root(struct inode *inode) ((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) * sbi->cluster_size; MSDOS_I(inode)->i_logstart = 0; - MSDOS_I(inode)->i_realsize = inode->i_size; + MSDOS_I(inode)->mmu_private = inode->i_size; MSDOS_I(inode)->i_attrs = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = 0; @@ -746,6 +746,31 @@ static int is_exec(char *extension) return 0; } +static int fat_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,fat_get_block); +} +static int fat_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,fat_get_block); +} +static int fat_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return cont_prepare_write(page,from,to,fat_get_block, + &MSDOS_I((struct inode*)page->mapping->host)->mmu_private); +} +static int _fat_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,fat_get_block); +} +static struct address_space_operations fat_aops = { + readpage: fat_readpage, + writepage: fat_writepage, + prepare_write: fat_prepare_write, + commit_write: generic_commit_write, + bmap: _fat_bmap +}; + /* doesn't deal with root inode */ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) { @@ -788,7 +813,7 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) break; } } - MSDOS_I(inode)->i_realsize = inode->i_size; + MSDOS_I(inode)->mmu_private = inode->i_size; } else { /* not a directory */ inode->i_mode = MSDOS_MKMODE(de->attr, ((IS_NOEXEC(inode) || @@ -796,7 +821,6 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) !is_exec(de->ext))) ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~sbi->options.fs_umask) | S_IFREG; - inode->i_op = &fat_file_inode_operations; MSDOS_I(inode)->i_start = CF_LE_W(de->start); if (sbi->fat_bits == 32) { MSDOS_I(inode)->i_start |= @@ -805,7 +829,9 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; inode->i_nlink = 1; inode->i_size = CF_LE_L(de->size); - MSDOS_I(inode)->i_realsize = ((inode->i_size-1)|(SECTOR_SIZE-1))+1; + inode->i_op = &fat_file_inode_operations; + inode->i_mapping->a_ops = &fat_aops; + MSDOS_I(inode)->mmu_private = inode->i_size; } if(de->attr & ATTR_SYS) if (sbi->options.sys_immutable) diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 196e7aa1b883..bca75467b240 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -311,7 +311,7 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1)); ~(SECTOR_SIZE-1); } inode->i_size += SECTOR_SIZE*cluster_size; - MSDOS_I(inode)->i_realsize += SECTOR_SIZE*cluster_size; + MSDOS_I(inode)->mmu_private += SECTOR_SIZE*cluster_size; mark_inode_dirty(inode); return res; } diff --git a/fs/hfs/dir_cap.c b/fs/hfs/dir_cap.c index 78903169e68f..e0dab7583b6f 100644 --- a/fs/hfs/dir_cap.c +++ b/fs/hfs/dir_cap.c @@ -74,56 +74,18 @@ struct inode_operations hfs_cap_ndir_inode_operations = { hfs_rmdir, /* rmdir */ NULL, /* mknod */ hfs_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; struct inode_operations hfs_cap_fdir_inode_operations = { &hfs_cap_dir_operations,/* default directory file-ops */ NULL, /* create */ cap_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; struct inode_operations hfs_cap_rdir_inode_operations = { &hfs_cap_dir_operations,/* default directory file-ops */ hfs_create, /* create */ cap_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; /*================ File-local functions ================*/ diff --git a/fs/hfs/dir_dbl.c b/fs/hfs/dir_dbl.c index 70ba2926317f..f3469b402793 100644 --- a/fs/hfs/dir_dbl.c +++ b/fs/hfs/dir_dbl.c @@ -73,14 +73,6 @@ struct inode_operations hfs_dbl_dir_inode_operations = { dbl_rmdir, /* rmdir */ NULL, /* mknod */ dbl_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; diff --git a/fs/hfs/dir_nat.c b/fs/hfs/dir_nat.c index 0cd9583b42cc..05a6463840a4 100644 --- a/fs/hfs/dir_nat.c +++ b/fs/hfs/dir_nat.c @@ -79,14 +79,6 @@ struct inode_operations hfs_nat_ndir_inode_operations = { nat_rmdir, /* rmdir */ NULL, /* mknod */ hfs_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; struct inode_operations hfs_nat_hdir_inode_operations = { @@ -100,14 +92,6 @@ struct inode_operations hfs_nat_hdir_inode_operations = { NULL, /* rmdir */ NULL, /* mknod */ nat_hdr_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; /*================ File-local functions ================*/ diff --git a/fs/hfs/file.c b/fs/hfs/file.c index 1e4c046a3b11..bb0868fcabc8 100644 --- a/fs/hfs/file.c +++ b/fs/hfs/file.c @@ -28,7 +28,6 @@ static hfs_rwret_t hfs_file_read(struct file *, char *, hfs_rwarg_t, static hfs_rwret_t hfs_file_write(struct file *, const char *, hfs_rwarg_t, loff_t *); static void hfs_file_truncate(struct inode *); -static int hfs_get_block(struct inode *, long, struct buffer_head *, int); /*================ Global variables ================*/ @@ -52,12 +51,7 @@ struct inode_operations hfs_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - hfs_get_block, /* get_block */ - block_read_full_page, /* readpage */ - NULL, /* writepage */ hfs_file_truncate, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; /*================ Variable-like macros ================*/ diff --git a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c index 51f997f87dd3..77625077f884 100644 --- a/fs/hfs/file_cap.c +++ b/fs/hfs/file_cap.c @@ -65,12 +65,7 @@ struct inode_operations hfs_cap_info_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block - none */ - NULL, /* readpage */ - NULL, /* writepage */ cap_info_truncate, /* truncate */ - NULL, /* permission */ - NULL /* revalidata */ }; /*================ File-local functions ================*/ diff --git a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c index d26aab9b74ac..b0cf0291ee0d 100644 --- a/fs/hfs/file_hdr.c +++ b/fs/hfs/file_hdr.c @@ -66,13 +66,7 @@ struct inode_operations hfs_hdr_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block - XXX: not available since - header part has no disk block */ - NULL, /* readpage */ - NULL, /* writepage */ hdr_truncate, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = { diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h index 07e61f0de6f6..3819a685f480 100644 --- a/fs/hfs/hfs.h +++ b/fs/hfs/hfs.h @@ -494,6 +494,9 @@ extern int hfs_extent_map(struct hfs_fork *, int, int); extern void hfs_extent_adj(struct hfs_fork *); extern void hfs_extent_free(struct hfs_fork *); +/* file.c */ +extern int hfs_get_block(struct inode *, long, struct buffer_head *, int); + /* mdb.c */ extern struct hfs_mdb *hfs_mdb_get(hfs_sysmdb, int, hfs_s32); extern void hfs_mdb_commit(struct hfs_mdb *, int); diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index af09655a0a6d..60014426b1e2 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -184,6 +184,31 @@ int hfs_notify_change(struct dentry *dentry, struct iattr * attr) return 0; } +static int hfs_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,hfs_get_block); +} +static int hfs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,hfs_get_block); +} +static int hfs_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return cont_prepare_write(page,from,to,hfs_get_block, + &((struct inode*)page->mapping->host)->u.hfs_i.mmu_private); +} +static int hfs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,hfs_get_block); +} +struct address_space_operations hfs_aops = { + readpage: hfs_readpage, + writepage: hfs_writepage, + prepare_write: hfs_prepare_write, + commit_write: generic_commit_write, + bmap: hfs_bmap +}; + /* * __hfs_iget() * @@ -308,6 +333,8 @@ void hfs_cap_ifill(struct inode * inode, ino_t type, const int version) init_file_inode(inode, (type == HFS_CAP_DATA) ? HFS_FK_DATA : HFS_FK_RSRC); inode->i_op = &hfs_file_inode_operations; + inode->i_mapping->a_ops = &hfs_aops; + inode->u.hfs_i.mmu_private = inode->i_size; } else { /* Directory */ struct hfs_dir *hdir = &entry->u.dir; @@ -361,6 +388,8 @@ void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version) } else if (entry->type == HFS_CDR_FIL) { init_file_inode(inode, HFS_FK_DATA); inode->i_op = &hfs_file_inode_operations; + inode->i_mapping->a_ops = &hfs_aops; + inode->u.hfs_i.mmu_private = inode->i_size; } else { /* Directory */ struct hfs_dir *hdir = &entry->u.dir; @@ -402,6 +431,8 @@ void hfs_nat_ifill(struct inode * inode, ino_t type, const int version) } else if (entry->type == HFS_CDR_FIL) { init_file_inode(inode, HFS_FK_DATA); inode->i_op = &hfs_file_inode_operations; + inode->i_mapping->a_ops = &hfs_aops; + inode->u.hfs_i.mmu_private = inode->i_size; } else { /* Directory */ struct hfs_dir *hdir = &entry->u.dir; diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index cc0c4cce91bf..280c47244314 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -242,6 +242,8 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry) if (!de->directory) { if (result->i_size == -1) { result->i_size = de->file_size; + result->i_data.a_ops = &hpfs_aops; + result->u.hpfs_i.mmu_private = result->i_size; /* * i_blocks should count the fnode and any anodes. * We count 1 for the fnode and don't bother about diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 8abaf2fd39e2..710b9120b3c4 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -54,6 +54,7 @@ void hpfs_truncate(struct inode *i) if (IS_IMMUTABLE(i)) return /*-EPERM*/; i->i_hpfs_n_secs = 0; i->i_blocks = 1 + ((i->i_size + 511) >> 9); + i->u.hpfs_i.mmu_private = i->i_size; hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9)); hpfs_write_inode(i); } @@ -61,63 +62,60 @@ void hpfs_truncate(struct inode *i) int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) { secno s; - if (iblock < inode->i_blocks - 1) { - s = hpfs_bmap(inode, iblock); + s = hpfs_bmap(inode, iblock); + if (s) { bh_result->b_dev = inode->i_dev; bh_result->b_blocknr = s; bh_result->b_state |= (1UL << BH_Mapped); return 0; } if (!create) return 0; - if (iblock > inode->i_blocks - 1) { - //hpfs_error(inode->i_sb, "hpfs_get_block beyond file end (requested %08x, inode size %08x", (int)iblock, (int)inode->i_blocks - 1); - printk("HPFS: could not write beyond file end. This is known bug.\n"); - return -EFSERROR; + if (iblock<<9 != inode->u.hpfs_i.mmu_private) { + BUG(); + return -EIO; } if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) { hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); return -ENOSPC; } inode->i_blocks++; + inode->u.hpfs_i.mmu_private += 512; bh_result->b_dev = inode->i_dev; bh_result->b_blocknr = s; bh_result->b_state |= (1UL << BH_Mapped) | (1UL << BH_New); return 0; } -static int hpfs_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) +static int hpfs_writepage(struct dentry *dentry, struct page *page) { - struct dentry *dentry = file->f_dentry; - struct inode *inode = dentry->d_inode; - struct page *new_page; - unsigned long pgpos; - long status; - - pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT; - while (pgpos < page->index) { - status = -ENOMEM; - new_page = grab_cache_page(&inode->i_data, pgpos); - if (!new_page) - goto out; - status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL); - UnlockPage(new_page); - page_cache_release(new_page); - if (status < 0) - goto out; - pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT; - } - status = block_write_cont_page(file, page, offset, bytes, buf); -out: - return status; + return block_write_full_page(page,hpfs_get_block); } - +static int hpfs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,hpfs_get_block); +} +static int hpfs_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return cont_prepare_write(page,from,to,hpfs_get_block, + &((struct inode*)page->mapping->host)->u.hpfs_i.mmu_private); +} +static int _hpfs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,hpfs_get_block); +} +struct address_space_operations hpfs_aops = { + readpage: hpfs_readpage, + writepage: hpfs_writepage, + prepare_write: hpfs_prepare_write, + commit_write: generic_commit_write, + bmap: _hpfs_bmap +}; ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { ssize_t retval; - retval = generic_file_write(file, buf, count, - ppos, hpfs_write_partial_page); + retval = generic_file_write(file, buf, count, ppos); if (retval > 0) { struct inode *inode = file->f_dentry->d_inode; inode->i_mtime = CURRENT_TIME; diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 38c47116c72e..f0324cffa15f 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h @@ -314,3 +314,5 @@ void hpfs_put_super(struct super_block *); unsigned hpfs_count_one_bitmap(struct super_block *, secno); int hpfs_statfs(struct super_block *, struct statfs *, int); struct super_block *hpfs_read_super(struct super_block *, void *, int); + +extern struct address_space_operations hpfs_aops; diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 68f5f9c3cb86..2fa2d0dd44a4 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -32,12 +32,7 @@ static const struct inode_operations hpfs_file_iops = NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - &hpfs_get_block, /* get_block */ - block_read_full_page, /* readpage */ - block_write_full_page, /* writepage */ hpfs_truncate, /* truncate */ - NULL, /* permission */ - NULL, /* revalidate */ }; static const struct file_operations hpfs_dir_ops = @@ -62,20 +57,9 @@ static const struct inode_operations hpfs_dir_iops = hpfs_rmdir, /* rmdir */ hpfs_mknod, /* mknod */ hpfs_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; -const struct inode_operations hpfs_symlink_iops = -{ - readlink: page_readlink, - follow_link: page_follow_link, +struct address_space_operations hpfs_symlink_aops = { readpage: hpfs_symlink_readpage }; @@ -150,7 +134,8 @@ void hpfs_read_inode(struct inode *i) if ((ea = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &ea_size))) { kfree(ea); i->i_mode = S_IFLNK | 0777; - i->i_op = (struct inode_operations *) &hpfs_symlink_iops; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &hpfs_symlink_aops; i->i_nlink = 1; i->i_size = ea_size; i->i_blocks = 1; @@ -205,6 +190,8 @@ void hpfs_read_inode(struct inode *i) i->i_nlink = 1; i->i_size = fnode->file_size; i->i_blocks = ((i->i_size + 511) >> 9) + 1; + i->i_data.a_ops = &hpfs_aops; + i->u.hpfs_i.mmu_private = i->i_size; } brelse(bh); } diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 85ce143dbd83..3ca25fedf081 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -138,7 +138,11 @@ int hpfs_create(struct inode *dir, struct dentry *dentry, int mode) result->i_hpfs_ea_size = 0; if (dee.read_only) result->i_mode &= ~0222; if (result->i_blocks == -1) result->i_blocks = 1; - if (result->i_size == -1) result->i_size = 0; + if (result->i_size == -1) { + result->i_size = 0; + result->i_data.a_ops = &hpfs_aops; + result->u.hpfs_i.mmu_private = 0; + } if (result->i_uid != current->fsuid || result->i_gid != current->fsgid || result->i_mode != (mode | S_IFREG)) { @@ -221,7 +225,7 @@ int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) return -ENOSPC; } -extern const struct inode_operations hpfs_symlink_iops; +extern struct address_space_operations hpfs_symlink_aops; int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink) { @@ -268,7 +272,8 @@ int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink) result->i_gid = current->fsgid; result->i_blocks = 1; result->i_size = strlen(symlink); - result->i_op = (struct inode_operations *) &hpfs_symlink_iops; + result->i_op = &page_symlink_inode_operations; + result->i_data.a_ops = &hpfs_symlink_aops; if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) { hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink)); mark_buffer_dirty(bh, 1); diff --git a/fs/inode.c b/fs/inode.c index 4145a2d9182e..ccc1a62f318d 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -474,6 +474,8 @@ static void clean_inode(struct inode *inode) memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); inode->i_pipe = NULL; inode->i_bdev = NULL; + inode->i_mapping = &inode->i_data; + inode->i_mapping->host = (void*)inode; } /* @@ -719,15 +721,10 @@ kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count)); int bmap(struct inode * inode, int block) { - struct buffer_head tmp; - - if (inode->i_op && inode->i_op->get_block) { - tmp.b_state = 0; - tmp.b_blocknr = 0; - inode->i_op->get_block(inode, block, &tmp, 0); - return tmp.b_blocknr; - } - return 0; + int res = 0; + if (inode->i_mapping->a_ops->bmap) + res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block); + return res; } /* diff --git a/fs/ioctl.c b/fs/ioctl.c index e7e22605651c..a02bbec67ab2 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -19,21 +19,18 @@ static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) switch (cmd) { case FIBMAP: { - struct buffer_head tmp; - - if (inode->i_op == NULL) - return -EBADF; - if (inode->i_op->get_block == NULL) + struct address_space *mapping = inode->i_mapping; + int res; + /* do we support this mess? */ + if (!mapping->a_ops->bmap) return -EINVAL; if (!capable(CAP_SYS_RAWIO)) return -EPERM; if ((error = get_user(block, (int *) arg)) != 0) return error; - tmp.b_state = 0; - tmp.b_blocknr = 0; - inode->i_op->get_block(inode, block, &tmp, 0); - return put_user(tmp.b_blocknr, (int *) arg); + res = mapping->a_ops->bmap(mapping, block); + return put_user(res, (int *) arg); } case FIGETBSZ: if (inode->i_sb == NULL) diff --git a/fs/isofs/Makefile b/fs/isofs/Makefile index 11c3402846b4..2b2af2ade6e7 100644 --- a/fs/isofs/Makefile +++ b/fs/isofs/Makefile @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile. O_TARGET := isofs.o -O_OBJS := namei.o inode.o file.o dir.o util.o rock.o symlink.o +O_OBJS := namei.o inode.o file.o dir.o util.o rock.o ifdef CONFIG_JOLIET O_OBJS += joliet.o diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 6081179c9233..35f37a1bf17a 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -39,21 +39,6 @@ struct inode_operations isofs_dir_inode_operations = &isofs_dir_operations, /* default directory file-ops */ NULL, /* create */ isofs_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static int isofs_name_translate(char * old, int len, char * new) diff --git a/fs/isofs/file.c b/fs/isofs/file.c index db491343a099..9de31e0247f1 100644 --- a/fs/isofs/file.c +++ b/fs/isofs/file.c @@ -28,21 +28,4 @@ static struct file_operations isofs_file_operations = { struct inode_operations isofs_file_inode_operations = { &isofs_file_operations, /* default file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - isofs_get_block, /* get_block */ - block_read_full_page, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index d14c18071ed1..2c67d9e5a165 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -1006,6 +1006,19 @@ int isofs_bmap(struct inode *inode, int block) return 0; } +static int isofs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,isofs_get_block); +} +static int _isofs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,isofs_get_block); +} +static struct address_space_operations isofs_aops = { + readpage: isofs_readpage, + bmap: _isofs_bmap +}; + static void test_and_set_uid(uid_t *p, uid_t value) { if(value) { @@ -1254,13 +1267,15 @@ static void isofs_read_inode(struct inode * inode) } else #endif IGNORE_WRONG_MULTI_VOLUME_SPECS { - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { inode->i_op = &isofs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_data.a_ops = &isofs_aops; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &isofs_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &isofs_symlink_inode_operations; - else + else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &isofs_symlink_aops; + } else /* XXX - parse_rock_ridge_inode() had already set i_rdev. */ init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev)); } diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 814d90b3c63e..71be5edd1ae4 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -445,7 +445,7 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr) /* readpage() for symlinks: reads symlink contents into the page and either makes it uptodate and returns 0 or returns error (-EIO) */ -int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page) +static int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page) { struct inode *inode = dentry->d_inode; char *link = (char*)kmap(page); @@ -540,3 +540,7 @@ int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page) UnlockPage(page); return -EIO; } + +struct address_space_operations isofs_symlink_aops = { + readpage: rock_ridge_symlink_readpage +}; diff --git a/fs/isofs/symlink.c b/fs/isofs/symlink.c deleted file mode 100644 index 219a4b9ac998..000000000000 --- a/fs/isofs/symlink.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * linux/fs/isofs/symlink.c - * - * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem. - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * isofs symlink handling code. This is only used with the Rock Ridge - * extensions to iso9660 - */ - -#include -#include -#include -#include -#include -#include -#include - -/* - * symlinks can't do much... - */ -struct inode_operations isofs_symlink_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, - readpage: rock_ridge_symlink_readpage -}; diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 878797b8adaa..e22007445264 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -308,13 +308,13 @@ out: #ifdef MODULE /* New module support in 2.1.18 */ -#if LINUX_VERSION_CODE >= 0x020112 - EXPORT_NO_SYMBOLS; - MODULE_AUTHOR("Olaf Kirch "); - MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION "."); - MODULE_PARM(nlm_grace_period, "10-240l"); - MODULE_PARM(nlm_timeout, "3-20l"); -#endif + +EXPORT_NO_SYMBOLS; +MODULE_AUTHOR("Olaf Kirch "); +MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION "."); +MODULE_PARM(nlm_grace_period, "10-240l"); +MODULE_PARM(nlm_timeout, "3-20l"); + int init_module(void) { diff --git a/fs/minix/Makefile b/fs/minix/Makefile index 537127b2d9fe..c3aee4fe3b3f 100644 --- a/fs/minix/Makefile +++ b/fs/minix/Makefile @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile. O_TARGET := minix.o -O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o symlink.o fsync.o +O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o fsync.o M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff --git a/fs/minix/dir.c b/fs/minix/dir.c index 56344946d744..02bde162d3fe 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c @@ -42,14 +42,6 @@ struct inode_operations minix_dir_inode_operations = { minix_rmdir, /* rmdir */ minix_mknod, /* mknod */ minix_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static int minix_readdir(struct file * filp, diff --git a/fs/minix/file.c b/fs/minix/file.c index a821a6522eb8..61d0e3f023ef 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -18,52 +18,21 @@ #include #include -#define NBUF 32 - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - #include #include -/* - * Write to a file (through the page cache). - */ -static ssize_t -minix_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - return generic_file_write(file, buf, count, - ppos, block_write_partial_page); -} - /* * We have mostly NULLs here: the current defaults are OK for * the minix filesystem. */ static struct file_operations minix_file_operations = { read: generic_file_read, - write: minix_file_write, + write: generic_file_write, mmap: generic_file_mmap, fsync: minix_sync_file, }; struct inode_operations minix_file_inode_operations = { - &minix_file_operations, /* default file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - minix_get_block, /* get_block */ - block_read_full_page, /* readpage */ - block_write_full_page, /* writepage */ - minix_truncate, /* truncate */ - NULL, /* permission */ - NULL, /* revalidate */ + &minix_file_operations, + truncate: minix_truncate, }; diff --git a/fs/minix/inode.c b/fs/minix/inode.c index de093d02f1ca..e33fe9787799 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -968,7 +968,7 @@ abort_too_big: goto abort; } -int minix_get_block(struct inode *inode, long block, +static int minix_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create) { if (INODE_VERSION(inode) == MINIX_V1) @@ -1016,6 +1016,30 @@ struct buffer_head * minix_bread(struct inode * inode, int block, int create) return NULL; } +static int minix_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,minix_get_block); +} +static int minix_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,minix_get_block); +} +static int minix_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return block_prepare_write(page,from,to,minix_get_block); +} +static int minix_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,minix_get_block); +} +struct address_space_operations minix_aops = { + readpage: minix_readpage, + writepage: minix_writepage, + prepare_write: minix_prepare_write, + commit_write: generic_commit_write, + bmap: minix_bmap +}; + /* * The minix V1 function to read an inode. */ @@ -1053,13 +1077,15 @@ static void V1_minix_read_inode(struct inode * inode) inode->i_blocks = inode->i_blksize = 0; for (block = 0; block < 9; block++) inode->u.minix_i.u.i1_data[block] = raw_inode->i_zone[block]; - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { inode->i_op = &minix_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_mapping->a_ops = &minix_aops; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &minix_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &minix_symlink_inode_operations; - else + else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &minix_aops; + } else init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]); brelse(bh); } @@ -1103,13 +1129,15 @@ static void V2_minix_read_inode(struct inode * inode) inode->i_blocks = inode->i_blksize = 0; for (block = 0; block < 10; block++) inode->u.minix_i.u.i2_data[block] = raw_inode->i_zone[block]; - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { inode->i_op = &minix_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_mapping->a_ops = &minix_aops; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &minix_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &minix_symlink_inode_operations; - else + else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &minix_aops; + } else init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]); brelse(bh); } diff --git a/fs/minix/namei.c b/fs/minix/namei.c index a3e73dbcdfb5..de2d0f2795c3 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -219,6 +219,7 @@ int minix_create(struct inode * dir, struct dentry *dentry, int mode) if (!inode) return -ENOSPC; inode->i_op = &minix_file_inode_operations; + inode->i_mapping->a_ops = &minix_aops; inode->i_mode = mode; mark_inode_dirty(inode); error = minix_add_entry(dir, dentry->d_name.name, @@ -477,7 +478,8 @@ int minix_symlink(struct inode * dir, struct dentry *dentry, goto out; inode->i_mode = S_IFLNK | 0777; - inode->i_op = &minix_symlink_inode_operations; + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &minix_aops; err = block_symlink(inode, symname, i); if (err) goto fail; diff --git a/fs/minix/symlink.c b/fs/minix/symlink.c deleted file mode 100644 index 7e1d03a10c23..000000000000 --- a/fs/minix/symlink.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * linux/fs/minix/symlink.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * minix symlink handling code - * - * Code removed. 1999, AV ;-) - */ - -#include -#include - -/* - * symlinks can't do much... - */ -struct inode_operations minix_symlink_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, - get_block: minix_get_block, - readpage: block_read_full_page -}; diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index ea0b0561620d..1554890729d9 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -595,14 +595,6 @@ struct inode_operations msdos_dir_inode_operations = { msdos_rmdir, /* rmdir */ NULL, /* mknod */ msdos_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* revalidate */ }; static void msdos_put_super_callback(struct super_block *sb) diff --git a/fs/namei.c b/fs/namei.c index 3b0b73686ae7..102f0e43276b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1386,8 +1386,8 @@ unsigned int follow, const char *link) static char *page_getlink(struct dentry * dentry, struct page **ppage) { struct page * page; - page = read_cache_page(&dentry->d_inode->i_data, 0, - (filler_t *)dentry->d_inode->i_op->readpage, + struct address_space *mapping = dentry->d_inode->i_mapping; + page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, dentry); if (IS_ERR(page)) goto sync_fail; @@ -1429,3 +1429,8 @@ page_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow } return res; } + +struct inode_operations page_symlink_inode_operations = { + readlink: page_readlink, + follow_link: page_follow_link, +}; diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 20b44a9b20f0..e5e91a24c029 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -70,9 +70,6 @@ struct inode_operations ncp_dir_inode_operations = ncp_rename, /* rename */ NULL, /* readlink */ NULL, /* follow link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ NULL, /* permission */ NULL, /* revalidate */ diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 50e24bd01111..09b95cd4fbe0 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -298,9 +298,6 @@ struct inode_operations ncp_file_inode_operations = NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ NULL, /* permission */ NULL /* revalidate */ diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 84b9e56432a9..5a4e790a7989 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -51,7 +51,7 @@ static struct super_operations ncp_sops = extern struct dentry_operations ncp_dentry_operations; #ifdef CONFIG_NCPFS_EXTRAS -extern struct inode_operations ncp_symlink_inode_operations; +extern struct address_space_operations ncp_symlink_aops; extern int ncp_symlink(struct inode*, struct dentry*, const char*); #endif @@ -226,7 +226,8 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info) inode->i_op = &ncp_dir_inode_operations; #ifdef CONFIG_NCPFS_EXTRAS } else if (S_ISLNK(inode->i_mode)) { - inode->i_op = &ncp_symlink_inode_operations; + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &ncp_symlink_aops; #endif } insert_inode_hash(inode); diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c index 5e5bf2fbddb4..b0bc34b226bb 100644 --- a/fs/ncpfs/symlink.c +++ b/fs/ncpfs/symlink.c @@ -96,9 +96,7 @@ fail: /* * symlinks can't do much... */ -struct inode_operations ncp_symlink_inode_operations={ - readlink: page_readlink, - follow_link: page_follow_link, +struct address_space_operations ncp_symlink_aops = { readpage: ncp_symlink_readpage, }; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 4341547f7eff..82d3f5bc35ff 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -71,9 +71,6 @@ struct inode_operations nfs_dir_inode_operations = { nfs_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ NULL, /* permission */ nfs_revalidate, /* revalidate */ diff --git a/fs/nfs/file.c b/fs/nfs/file.c index c883545d310d..2135ece68f98 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -64,9 +64,6 @@ struct inode_operations nfs_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - nfs_readpage, /* readpage */ - nfs_writepage, /* writepage */ NULL, /* truncate */ NULL, /* permission */ nfs_revalidate, /* revalidate */ @@ -160,21 +157,29 @@ nfs_fsync(struct file *file, struct dentry *dentry) * If the writer ends up delaying the write, the writer needs to * increment the page use counts until he is done with the page. */ -static int nfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) +static int nfs_prepare_write(struct page *page, unsigned offset, unsigned to) +{ + kmap(page); + return 0; +} +static int nfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) { long status; - bytes -= copy_from_user((u8*)kmap(page) + offset, buf, bytes); kunmap(page); - status = -EFAULT; - if (bytes) { - lock_kernel(); - status = nfs_updatepage(file, page, offset, bytes); - unlock_kernel(); - } + lock_kernel(); + status = nfs_updatepage(file, page, offset, to-offset); + unlock_kernel(); return status; } +struct address_space_operations nfs_file_aops = { + readpage: nfs_readpage, + writepage: nfs_writepage, + prepare_write: nfs_prepare_write, + commit_write: nfs_commit_write +}; + /* * Write to a file (through the page cache). */ @@ -200,7 +205,7 @@ nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) if (!count) goto out; - result = generic_file_write(file, buf, count, ppos, nfs_write_one_page); + result = generic_file_write(file, buf, count, ppos); out: return result; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index aae8d3d0ab5d..c8d42adfee2d 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -473,9 +473,10 @@ nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr) NFS_FILEID(inode) = fattr->fileid; NFS_FSID(inode) = fattr->fsid; inode->i_mode = fattr->mode; - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { inode->i_op = &nfs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_data.a_ops = &nfs_file_aops; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &nfs_dir_inode_operations; else if (S_ISLNK(inode->i_mode)) inode->i_op = &nfs_symlink_inode_operations; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 09a16b302212..a13e26fd0171 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -479,7 +479,7 @@ updated: if (req->wb_bytes == PAGE_SIZE) SetPageUptodate(page); - retval = count; + retval = 0; if (synchronous) { int status = wait_on_write_request(req); if (status) { diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 68e7a1dacdd8..b0aac328009d 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -29,13 +29,7 @@ #include #include -#if LINUX_VERSION_CODE >= 0x020100 #include -#else -# define copy_from_user memcpy_fromfs -# define copy_to_user memcpy_tofs -# define access_ok !verify_area -#endif #include #include @@ -249,10 +243,8 @@ done: #ifdef MODULE /* New-style module support since 2.1.18 */ -#if LINUX_VERSION_CODE >= 131346 EXPORT_NO_SYMBOLS; MODULE_AUTHOR("Olaf Kirch "); -#endif extern int (*do_nfsservctl)(int, void *, void *); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 95bec2fc511f..b1af9399ea47 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -39,9 +39,7 @@ #include #include -#if LINUX_VERSION_CODE >= 0x020100 #include -#endif #define NFSDDBG_FACILITY NFSDDBG_FILEOP #define NFSD_PARANOIA diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index a5f378c66da3..fff05ca9b72c 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -413,23 +413,6 @@ static struct file_operations ntfs_file_operations_nommap = { static struct inode_operations ntfs_inode_operations_nobmap = { &ntfs_file_operations_nommap, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* revalidate */ }; #ifdef CONFIG_NTFS_RW @@ -570,6 +553,14 @@ ntfs_bmap(struct inode *ino,int block) return (ret==-1) ? 0:ret; } +/* It's fscking broken. */ + +static int ntfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create) +{ + BUG(); + return -1; +} + static struct file_operations ntfs_file_operations = { read: ntfs_read, mmap: generic_file_mmap, @@ -580,23 +571,6 @@ static struct file_operations ntfs_file_operations = { static struct inode_operations ntfs_inode_operations = { &ntfs_file_operations, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - ntfs_bmap, /* get_block */ - block_read_full_page, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* revalidate */ }; static struct file_operations ntfs_dir_operations = { @@ -622,16 +596,32 @@ static struct inode_operations ntfs_dir_inode_operations = { NULL, /* rmdir */ NULL, /* mknod */ NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* revalidate */ }; +static int ntfs_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,ntfs_get_block); +} +static int ntfs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,ntfs_get_block); +} +static int ntfs_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return cont_prepare_write(page,from,to,ntfs_get_block, + &((struct inode*)page->mapping->host)->u.ntfs_i.mmu_private); +} +static int _ntfs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,ntfs_get_block); +} +struct address_space_operations ntfs_aops = { + readpage: ntfs_readpage, + writepage: ntfs_writepage, + prepare_write: ntfs_prepare_write, + commit_write: generic_commit_write, + bmap: _ntfs_bmap +}; /* ntfs_read_inode is called by the Virtual File System (the kernel layer that * deals with filesystems) when iget is called requesting an inode not already * present in the inode table. Typically filesystems have separate @@ -707,8 +697,13 @@ static void ntfs_read_inode(struct inode* inode) } else { - inode->i_op=can_mmap ? &ntfs_inode_operations : - &ntfs_inode_operations_nobmap; + if (can_mmap) { + inode->i_op = &ntfs_inode_operations; + inode->i_mapping->a_ops = &ntfs_aops; + inode->u.ntfs_i.mmu_private = inode->i_size; + } else { + inode->i_op=&ntfs_inode_operations_nobmap; + } inode->i_mode=S_IFREG|S_IRUGO; } #ifdef CONFIG_NTFS_RW diff --git a/fs/open.c b/fs/open.c index 8aa8280881fd..159b08bf7ddb 100644 --- a/fs/open.c +++ b/fs/open.c @@ -898,16 +898,9 @@ asmlinkage long sys_close(unsigned int fd) */ asmlinkage long sys_vhangup(void) { - int ret = -EPERM; - - if (!capable(CAP_SYS_TTY_CONFIG)) - goto out; - /* If there is a controlling tty, hang it up */ - lock_kernel(); - if (current->tty) + if (capable(CAP_SYS_TTY_CONFIG)) { tty_vhangup(current->tty); - unlock_kernel(); - ret = 0; -out: - return ret; + return 0; + } + return -EPERM; } diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index c5d0c479706d..710c8a7dd549 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -580,19 +580,6 @@ static struct inode_operations openprom_alias_inode_operations = { openpromfs_lookup, /* lookup */ NULL, /* link */ openpromfs_unlink, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; extern struct inode_operations openprom_inode_operations; diff --git a/fs/proc/array.c b/fs/proc/array.c index 16e9d4b6677f..3774308608d2 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -133,8 +133,7 @@ static inline const char * get_task_state(struct task_struct *tsk) TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE | TASK_ZOMBIE | - TASK_STOPPED | - TASK_SWAPPING); + TASK_STOPPED); const char **p = &task_state_array[0]; while (state) { diff --git a/fs/proc/base.c b/fs/proc/base.c index 693ad70caa94..cdd2116b2f15 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -362,9 +362,6 @@ static struct inode_operations proc_mem_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ proc_permission, /* permission */ NULL /* revalidate */ @@ -452,18 +449,8 @@ out: } static struct inode_operations proc_pid_link_inode_operations = { - NULL, /* file-operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - proc_pid_readlink, /* readlink */ - proc_pid_follow_link, /* follow_link */ + readlink: proc_pid_readlink, + follow_link: proc_pid_follow_link }; /* reading from directory - bad */ @@ -777,9 +764,6 @@ static struct inode_operations proc_fd_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ proc_permission, /* permission */ }; diff --git a/fs/qnx4/Makefile b/fs/qnx4/Makefile index 1988bb8fff42..943eb122361a 100644 --- a/fs/qnx4/Makefile +++ b/fs/qnx4/Makefile @@ -8,8 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := qnx4.o -O_OBJS := inode.o dir.o namei.o file.o bitmap.o symlinks.o truncate.o \ -fsync.o +O_OBJS := inode.o dir.o namei.o file.o bitmap.o truncate.o fsync.o M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index 80ab1f5909a7..6eb3ca0a57a4 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c @@ -17,130 +17,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - - -#ifdef CONFIG_QNX4FS_RW -static ssize_t qnx4_file_write(struct file *filp, const char *buf, - size_t count, loff_t * ppos) -{ - struct dentry *dentry = filp->f_dentry; - struct inode *inode = dentry->d_inode; - struct qnx4_inode_info *qnx4_ino; - struct buffer_head *bh; - ssize_t result = -EBUSY, c; - off_t pos; - unsigned long start, block, extent_end; - char *p; - - QNX4DEBUG(("qnx4: file_write(%s/%s (%d), %lu@%lu)\n", - dentry->d_parent->d_name.name, dentry->d_name.name, - inode->i_count, (unsigned long) count, (unsigned long) *ppos)); - if (inode == NULL) { - printk("qnx4: NULL inode for file_write\n"); - return -EINVAL; - } - qnx4_ino = &inode->u.qnx4_i; - if (S_ISREG(inode->i_mode) == 0) { - printk("qnx4: write to non-file, mode %07o\n", inode->i_mode); - return -EINVAL; - } - if (count == 0) { - goto out; - } - if (filp->f_flags & O_APPEND) { - pos = inode->i_size; - } else { - pos = *ppos; - } - start = qnx4_ino->i_first_xtnt.xtnt_blk + ((pos >> 9) * 0) - 1; - result = 0; - extent_end = start + qnx4_ino->i_first_xtnt.xtnt_size - 1; - QNX4DEBUG(("qnx4: extent length : [%lu] bytes\n", - qnx4_ino->i_first_xtnt.xtnt_size)); - while (result < count) { - block = start + pos / QNX4_BLOCK_SIZE; - if (block > extent_end) { - if (qnx4_is_free(inode->i_sb, block) <= 0) { - printk("qnx4: next inode is busy -> write aborted.\n"); - result = -ENOSPC; - break; - } - } - if ((bh = bread(inode->i_dev, block, - QNX4_BLOCK_SIZE)) == NULL) { - printk("qnx4: I/O error on write.\n"); - result = -EIO; - goto out; - } - if (bh == NULL) { - if (result != 0) { - result = -ENOSPC; - } - break; - } - if (block > extent_end) { - qnx4_set_bitmap(inode->i_sb, block, 1); - extent_end++; - qnx4_ino->i_first_xtnt.xtnt_size = extent_end - start + 1; - } - c = QNX4_BLOCK_SIZE - (pos % QNX4_BLOCK_SIZE); - if (c > count - result) { - c = count - result; - } - if (c != QNX4_BLOCK_SIZE && buffer_uptodate(bh) == 0) { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); - if (buffer_uptodate(bh) == 0) { - brelse(bh); - if (result != 0) { - result = -EIO; - } - break; - } - } - p = bh->b_data + (pos % QNX4_BLOCK_SIZE); - c -= copy_from_user(p, buf, c); - if (c == 0) { - brelse(bh); - if (result == 0) { - result = -EFAULT; - } - break; - } -// update_vm_cache(inode, pos, p, c); - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 0); - brelse(bh); - pos += c; - buf += c; - result += c; - } - if (pos > inode->i_size) { - inode->i_size = pos; - } - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - *ppos = pos; - mark_inode_dirty(inode); - - out: - return result; -} -#endif /* * We have mostly NULL's here: the current defaults are ok for @@ -150,7 +26,7 @@ static struct file_operations qnx4_file_operations = { read: generic_file_read, #ifdef CONFIG_QNX4FS_RW - write: qnx4_file_write, + write: generic_file_write, #endif mmap: generic_file_mmap, #ifdef CONFIG_QNX4FS_RW @@ -161,10 +37,7 @@ static struct file_operations qnx4_file_operations = struct inode_operations qnx4_file_inode_operations = { default_file_ops: &qnx4_file_operations, - get_block: qnx4_get_block, - readpage: block_read_full_page, #ifdef CONFIG_QNX4FS_RW - writepage: block_write_full_page, truncate: qnx4_truncate, #endif }; diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 5b70d5211deb..abb6d8260f20 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -423,6 +423,31 @@ static void qnx4_put_super(struct super_block *sb) return; } +static int qnx4_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,qnx4_get_block); +} +static int qnx4_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,qnx4_get_block); +} +static int qnx4_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return cont_prepare_write(page,from,to,qnx4_get_block, + &((struct inode*)page->mapping->host)->u.qnx4_i.mmu_private); +} +static int qnx4_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,qnx4_get_block); +} +struct address_space_operations qnx4_aops = { + readpage: qnx4_readpage, + writepage: qnx4_writepage, + prepare_write: qnx4_prepare_write, + commit_write: generic_commit_write, + bmap: qnx4_bmap +}; + static void qnx4_read_inode(struct inode *inode) { struct buffer_head *bh; @@ -461,14 +486,17 @@ static void qnx4_read_inode(struct inode *inode) inode->i_blksize = QNX4_DIR_ENTRY_SIZE; memcpy(&inode->u.qnx4_i, (struct qnx4_inode_info *) raw_inode, QNX4_DIR_ENTRY_SIZE); - inode->i_op = &qnx4_file_inode_operations; - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { inode->i_op = &qnx4_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_mapping->a_ops = &qnx4_aops; + inode->u.qnx4_i.mmu_private = inode->i_size; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &qnx4_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &qnx4_symlink_inode_operations; - else + else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &qnx4_aops; + inode->u.qnx4_i.mmu_private = inode->i_size; + } else /* HUH??? Where is device number? Oh, well... */ init_special_inode(inode, inode->i_mode, 0); diff --git a/fs/qnx4/symlinks.c b/fs/qnx4/symlinks.c deleted file mode 100644 index 4eaf270349ce..000000000000 --- a/fs/qnx4/symlinks.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * QNX4 file system, Linux implementation. - * - * Version : 0.2.1 - * - * Using parts of the xiafs filesystem. - * - * History : - * - * 28-05-1998 by Richard Frowijn : first release. - * 21-06-1998 by Frank Denis : ugly changes to make it compile on Linux 2.1.99+ - */ - -#include -#include - -/* - * symlinks can't do much... - */ -struct inode_operations qnx4_symlink_inode_operations = -{ - readlink: page_readlink, - follow_link: page_follow_link, - get_block: qnx4_get_block, - readpage: block_read_full_page, -}; diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 45fdc4fe3bf7..ab5972591a7d 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -446,6 +446,10 @@ romfs_readpage(struct dentry * dentry, struct page * page) /* Mapping from our types to the kernel */ +static struct address_space_operations romfs_aops = { + readpage: romfs_readpage +}; + static struct file_operations romfs_file_operations = { read: generic_file_read, mmap: generic_file_mmap, @@ -453,23 +457,6 @@ static struct file_operations romfs_file_operations = { static struct inode_operations romfs_file_inode_operations = { &romfs_file_operations, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block -- not really */ - romfs_readpage, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static struct file_operations romfs_dir_operations = { @@ -484,27 +471,6 @@ static struct inode_operations romfs_dir_inode_operations = { &romfs_dir_operations, NULL, /* create */ romfs_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ -}; - -static struct inode_operations romfs_link_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, - readpage: romfs_readpage }; static mode_t romfs_modemap[] = @@ -518,7 +484,7 @@ static struct inode_operations *romfs_inoops[] = NULL, /* hardlink, handled elsewhere */ &romfs_dir_inode_operations, &romfs_file_inode_operations, - &romfs_link_inode_operations, + &page_symlink_inode_operations, NULL, /* device/fifo/socket nodes, */ NULL, /* set by init_special_inode */ NULL, @@ -574,6 +540,8 @@ romfs_read_inode(struct inode *i) i->i_mode = ino; if (S_ISDIR(ino)) i->i_size = i->u.romfs_i.i_metasize; + else + i->i_data.a_ops = &romfs_aops; } else { /* depending on MBZ for sock/fifos */ nextfh = ntohl(ri.spec); diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index dd0efd7253c2..68351b4b41c2 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -52,9 +52,6 @@ struct inode_operations smb_dir_inode_operations = smb_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ NULL, /* permission */ smb_revalidate_inode, /* revalidate */ diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index 649ea76094e2..a62de125635d 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -260,20 +260,31 @@ out: * If the writer ends up delaying the write, the writer needs to * increment the page use counts until he is done with the page. */ -static int smb_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) +static int smb_prepare_write(struct page *page, unsigned offset, unsigned to) +{ + kmap(page); + return 0; +} + +static int smb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) { int status; - bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes); status = -EFAULT; - if (bytes) { - lock_kernel(); - status = smb_updatepage(file, page, offset, bytes); - unlock_kernel(); - } + lock_kernel(); + status = smb_updatepage(file, page, offset, to-offset); + unlock_kernel(); + kunmap(page); return status; } +struct address_space_operations smb_file_aops = { + readpage: smb_readpage, + writepage: smb_writepage, + prepare_write: smb_prepare_write, + commit_write: smb_commit_write +}; + /* * Write to a file (through the page cache). */ @@ -305,7 +316,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, result); if (count > 0) { - result = generic_file_write(file, buf, count, ppos, smb_write_one_page); + result = generic_file_write(file, buf, count, ppos); #ifdef SMBFS_DEBUG_VERBOSE printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n", (long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime, @@ -390,9 +401,6 @@ struct inode_operations smb_file_inode_operations = NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - smb_readpage, /* readpage */ - smb_writepage, /* writepage */ NULL, /* truncate */ smb_file_permission, /* permission */ smb_revalidate_inode, /* revalidate */ diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index b4dcc2a32085..c071263ff52f 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -82,9 +82,10 @@ smb_iget(struct super_block *sb, struct smb_fattr *fattr) result->i_ino = fattr->f_ino; memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i)); smb_set_inode_attr(result, fattr); - if (S_ISREG(result->i_mode)) + if (S_ISREG(result->i_mode)) { result->i_op = &smb_file_inode_operations; - else if (S_ISDIR(result->i_mode)) + result->i_data.a_ops = &smb_file_aops; + } else if (S_ISDIR(result->i_mode)) result->i_op = &smb_dir_inode_operations; else result->i_op = NULL; diff --git a/fs/sysv/Makefile b/fs/sysv/Makefile index 6c31360fd6e4..394af0b4d1db 100644 --- a/fs/sysv/Makefile +++ b/fs/sysv/Makefile @@ -8,8 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile. O_TARGET := sysv.o -O_OBJS := ialloc.o balloc.o inode.o file.o dir.o symlink.o namei.o \ - fsync.o truncate.o +O_OBJS := ialloc.o balloc.o inode.o file.o dir.o namei.o fsync.o truncate.o M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index 08517166c09c..f21a475783b5 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c @@ -49,14 +49,6 @@ struct inode_operations sysv_dir_inode_operations = { sysv_rmdir, /* rmdir */ sysv_mknod, /* mknod */ sysv_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) diff --git a/fs/sysv/file.c b/fs/sysv/file.c index 6b827cbb4806..b60a1d02e635 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -23,51 +23,18 @@ #include #include -#include - -#define NBUF 32 - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - -/* - * Write to a file (through the page cache). - */ -static ssize_t -sysv_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - return generic_file_write(file, buf, count, - ppos, block_write_partial_page); -} - /* * We have mostly NULLs here: the current defaults are OK for * the coh filesystem. */ static struct file_operations sysv_file_operations = { read: generic_file_read, - write: sysv_file_write, + write: generic_file_write, mmap: generic_file_mmap, fsync: sysv_sync_file, }; struct inode_operations sysv_file_inode_operations = { - &sysv_file_operations, /* default file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - sysv_get_block, /* get_block */ - block_read_full_page, /* readpage */ - block_write_full_page, /* writepage */ - sysv_truncate, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ + &sysv_file_operations, + truncate: sysv_truncate, }; diff --git a/fs/sysv/fsync.c b/fs/sysv/fsync.c index c2ba82b0b3fa..3c9871be6c92 100644 --- a/fs/sysv/fsync.c +++ b/fs/sysv/fsync.c @@ -16,10 +16,9 @@ #include #include -#include - #include #include +#include /* return values: 0 means OK/done, 1 means redo, -1 means I/O error. */ diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index cfe0167287c5..6580b6125aa9 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -832,7 +832,7 @@ out: return result; } -int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) +static int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) { struct super_block *sb; int ret, err, new; @@ -961,6 +961,30 @@ struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create) return NULL; } +static int sysv_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,sysv_get_block); +} +static int sysv_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,sysv_get_block); +} +static int sysv_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return block_prepare_write(page,from,to,sysv_get_block); +} +static int sysv_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,sysv_get_block); +} +struct address_space_operations sysv_aops = { + readpage: sysv_readpage, + writepage: sysv_writepage, + prepare_write: sysv_prepare_write, + commit_write: generic_commit_write, + bmap: sysv_bmap +}; + #ifdef __BIG_ENDIAN static inline unsigned long read3byte (unsigned char * p) @@ -1059,13 +1083,15 @@ static void sysv_read_inode(struct inode *inode) for (block = 0; block < 10+1+1+1; block++) inode->u.sysv_i.i_data[block] = read3byte(&raw_inode->i_a.i_addb[3*block]); - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { inode->i_op = &sysv_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_mapping->a_ops = &sysv_aops; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &sysv_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &sysv_symlink_inode_operations; - else + else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &sysv_aops; + } else init_special_inode(inode, inode->i_mode,raw_inode->i_a.i_rdev); brelse(bh); } diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index 844912898920..9661af99c832 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -204,6 +204,7 @@ int sysv_create(struct inode * dir, struct dentry * dentry, int mode) if (!inode) return -ENOSPC; inode->i_op = &sysv_file_inode_operations; + inode->i_mapping->a_ops = &sysv_aops; inode->i_mode = mode; mark_inode_dirty(inode); error = sysv_add_entry(dir, dentry->d_name.name, @@ -455,7 +456,8 @@ int sysv_symlink(struct inode * dir, struct dentry * dentry, goto out; inode->i_mode = S_IFLNK | 0777; - inode->i_op = &sysv_symlink_inode_operations; + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &sysv_aops; err = block_symlink(inode, symname, l); if (err) goto out_no_entry; diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c deleted file mode 100644 index 3f77f831e910..000000000000 --- a/fs/sysv/symlink.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * linux/fs/sysv/symlink.c - * - * minix/symlink.c - * Copyright (C) 1991, 1992 Linus Torvalds - * - * coh/symlink.c - * Copyright (C) 1993 Pascal Haible, Bruno Haible - * - * sysv/symlink.c - * Copyright (C) 1993 Bruno Haible - * - * SystemV/Coherent symlink handling code - */ - -#include - -/* - * symlinks can't do much... - */ -struct inode_operations sysv_symlink_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, - get_block: sysv_get_block, - readpage: block_read_full_page -}; diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 3843571aa14b..963d20344596 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -80,14 +80,6 @@ struct inode_operations udf_dir_inode_operations = { NULL, /* mknod */ NULL, /* rename */ #endif - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; /* diff --git a/fs/udf/file.c b/fs/udf/file.c index 28b83b18da92..5cf51cd0ed92 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -72,110 +72,119 @@ static loff_t udf_file_llseek(struct file * file, loff_t offset, int origin) return offset; } -static inline void remove_suid(struct inode * inode) +static int udf_adinicb_readpage(struct dentry *dentry, struct page * page) { - unsigned int mode; + struct inode *inode = dentry->d_inode; - /* set S_IGID if S_IXGRP is set, and always set S_ISUID */ - mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID; - - /* was any of the uid bits set? */ - mode &= inode->i_mode; - if (mode && !capable(CAP_FSETID)) - { - inode->i_mode &= ~mode; - mark_inode_dirty(inode); - } -} - -static ssize_t udf_file_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - ssize_t retval; - struct inode *inode = file->f_dentry->d_inode; + struct buffer_head *bh; + unsigned long kaddr = 0; - retval = generic_file_write(file, buf, count, ppos, block_write_partial_page); + if (!PageLocked(page)) + PAGE_BUG(page); - if (retval > 0) - { - remove_suid(inode); - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME; - mark_inode_dirty(inode); - } - return retval; + kaddr = kmap(page); + memset((char *)kaddr, 0, PAGE_CACHE_SIZE); + bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize); + ll_rw_block (READ, 1, &bh); + wait_on_buffer(bh); + memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode), + inode->i_size); + brelse(bh); + SetPageUptodate(page); + kunmap(page); + UnlockPage(page); + return 0; } -int udf_write_partial_page_adinicb(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) +static int udf_adinicb_writepage(struct dentry *dentry, struct page *page) { - struct inode *inode = file->f_dentry->d_inode; - int err = 0, block; + struct inode *inode = dentry->d_inode; + struct buffer_head *bh; unsigned long kaddr = 0; if (!PageLocked(page)) BUG(); - if (offset < 0 || offset >= (inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode))) - BUG(); - if (bytes+offset < 0 || bytes+offset > (inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode))) - BUG(); kaddr = kmap(page); - block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); - bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize); + bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize); if (!buffer_uptodate(bh)) { ll_rw_block (READ, 1, &bh); wait_on_buffer(bh); } - err = copy_from_user((char *)kaddr + offset, buf, bytes); + memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr, + inode->i_size); + ll_rw_block (WRITE, 1, &bh); + wait_on_buffer(bh); + brelse(bh); + SetPageUptodate(page); + kunmap(page); + return 0; +} + +static int udf_adinicb_prepare_write(struct page *page, unsigned offset, unsigned to) +{ + kmap(page); + return 0; +} + +static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) +{ + struct inode *inode = file->f_dentry->d_inode; + struct buffer_head *bh; + char *kaddr = (char*)page_address(page); + bh = bread (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize); + if (!buffer_uptodate(bh)) { + ll_rw_block (READ, 1, &bh); + wait_on_buffer(bh); + } memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset, - (char *)kaddr + offset, bytes); + kaddr + offset, to-offset); mark_buffer_dirty(bh, 0); brelse(bh); kunmap(page); SetPageUptodate(page); - return bytes; + return 0; } -static ssize_t udf_file_write_adinicb(struct file * file, const char * buf, +struct address_space_operations udf_adinicb_aops = { + readpage: udf_adinicb_readpage, + writepage: udf_adinicb_writepage, + prepare_write: udf_adinicb_prepare_write, + commit_write: udf_adinicb_commit_write +}; + +static ssize_t udf_file_write(struct file * file, const char * buf, size_t count, loff_t *ppos) { ssize_t retval; struct inode *inode = file->f_dentry->d_inode; int err, pos; - if (file->f_flags & O_APPEND) - pos = inode->i_size; - else - pos = *ppos; - - if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + - pos + count)) - { - udf_expand_file_adinicb(file, pos + count, &err); - if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) - { - udf_debug("udf_expand_adinicb: err=%d\n", err); - return err; - } + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) { + if (file->f_flags & O_APPEND) + pos = inode->i_size; else - return udf_file_write(file, buf, count, ppos); - } - else - { - if (pos + count > inode->i_size) - UDF_I_LENALLOC(inode) = pos + count; - else - UDF_I_LENALLOC(inode) = inode->i_size; + pos = *ppos; + + if (inode->i_sb->s_blocksize < + (udf_file_entry_alloc_offset(inode) + pos + count)) { + udf_expand_file_adinicb(file, pos + count, &err); + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) { + udf_debug("udf_expand_adinicb: err=%d\n", err); + return err; + } + } else { + if (pos + count > inode->i_size) + UDF_I_LENALLOC(inode) = pos + count; + else + UDF_I_LENALLOC(inode) = inode->i_size; + } } - retval = generic_file_write(file, buf, count, ppos, udf_write_partial_page_adinicb); - - if (retval > 0) - { - remove_suid(inode); - inode->i_ctime = inode->i_mtime = CURRENT_TIME; + retval = generic_file_write(file, buf, count, ppos); + if (retval > 0) { UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME; mark_inode_dirty(inode); } @@ -350,59 +359,7 @@ static struct file_operations udf_file_operations = { struct inode_operations udf_file_inode_operations = { &udf_file_operations, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - udf_get_block, /* get_block */ - block_read_full_page, /* readpage */ - block_write_full_page, /* writepage */ -#if CONFIG_UDF_RW == 1 - udf_truncate, /* truncate */ -#else - NULL, /* truncate */ -#endif - NULL, /* permission */ - NULL /* revalidate */ -}; - -static struct file_operations udf_file_operations_adinicb = { - llseek: udf_file_llseek, - read: generic_file_read, - write: udf_file_write_adinicb, - ioctl: udf_ioctl, - release: udf_release_file, - fsync: udf_sync_file_adinicb, -}; - -struct inode_operations udf_file_inode_operations_adinicb = { - &udf_file_operations_adinicb, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - udf_get_block, /* get_block */ - udf_readpage_adinicb, /* readpage */ - udf_writepage_adinicb, /* writepage */ #if CONFIG_UDF_RW == 1 - udf_truncate_adinicb, /* truncate */ -#else - NULL, /* truncate */ + truncate: udf_truncate, #endif - NULL, /* permission */ - NULL /* revalidate */ }; diff --git a/fs/udf/fsync.c b/fs/udf/fsync.c index 1b7a0a4591ba..e7d067e62e89 100644 --- a/fs/udf/fsync.c +++ b/fs/udf/fsync.c @@ -121,13 +121,3 @@ skip: unlock_kernel(); return err ? -EIO : 0; } - -int udf_sync_file_adinicb(struct file * file, struct dentry *dentry) -{ - int ret; - - lock_kernel(); - ret = udf_sync_inode(dentry->d_inode) ? -EIO : 0; - unlock_kernel(); - return ret; -} diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 2ea1f980b95b..752a00339349 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -56,6 +56,7 @@ static void udf_merge_extents(struct inode *, static void udf_update_extents(struct inode *, long_ad [EXTENT_MERGE_SIZE], int, int, lb_addr, Uint32, struct buffer_head **); +static int udf_get_block(struct inode *, long, struct buffer_head *, int); /* * udf_put_inode @@ -96,7 +97,7 @@ void udf_delete_inode(struct inode * inode) { inode->i_size = 0; if (inode->i_blocks) - inode->i_op->truncate(inode); + udf_truncate(inode); udf_free_inode(inode); } @@ -117,6 +118,30 @@ static int udf_alloc_block(struct inode *inode, Uint16 partition, return result; } +static int udf_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,udf_get_block); +} +static int udf_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,udf_get_block); +} +static int udf_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return block_prepare_write(page,from,to,udf_get_block); +} +static int udf_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,udf_get_block); +} +static struct address_space_operations udf_aops = { + readpage: udf_readpage, + writepage: udf_writepage, + prepare_write: udf_prepare_write, + commit_write: generic_commit_write, + bmap: udf_bmap +}; + void udf_expand_file_adinicb(struct file * filp, int newsize, int * err) { struct inode * inode = filp->f_dentry->d_inode; @@ -124,12 +149,13 @@ void udf_expand_file_adinicb(struct file * filp, int newsize, int * err) struct page *page; unsigned long kaddr = 0; + /* from now on we have normal address_space methods */ + inode->i_data.a_ops = &udf_aops; + if (!UDF_I_LENALLOC(inode)) { UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG; mark_inode_dirty(inode); - inode->i_op = &udf_file_inode_operations; - filp->f_op = inode->i_op->default_file_ops; return; } @@ -156,14 +182,12 @@ void udf_expand_file_adinicb(struct file * filp, int newsize, int * err) mark_buffer_dirty(bh, 1); udf_release_data(bh); - block_write_full_page(filp->f_dentry, page); + inode->i_data.a_ops->writepage(filp->f_dentry, page); UnlockPage(page); page_cache_release(page); mark_inode_dirty(inode); inode->i_version ++; - inode->i_op = &udf_file_inode_operations; - filp->f_op = inode->i_op->default_file_ops; } struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err) @@ -251,34 +275,7 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int return dbh; } -struct buffer_head * udf_getblk(struct inode * inode, long block, - int create, int * err) -{ - struct buffer_head dummy; - int error; - - dummy.b_state = 0; - dummy.b_blocknr = -1000; - error = udf_get_block(inode, block, &dummy, create); - *err = error; - if (!error & buffer_mapped(&dummy)) - { - struct buffer_head *bh; - bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); - if (buffer_new(&dummy)) - { - if (!buffer_uptodate(bh)) - wait_on_buffer(bh); - memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); - } - return bh; - } - return NULL; -} - -int udf_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create) +static int udf_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create) { int err, new; struct buffer_head *bh; @@ -335,6 +332,33 @@ abort_negative: goto abort; } +struct buffer_head * udf_getblk(struct inode * inode, long block, + int create, int * err) +{ + struct buffer_head dummy; + int error; + + dummy.b_state = 0; + dummy.b_blocknr = -1000; + error = udf_get_block(inode, block, &dummy, create); + *err = error; + if (!error & buffer_mapped(&dummy)) + { + struct buffer_head *bh; + bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); + if (buffer_new(&dummy)) + { + if (!buffer_uptodate(bh)) + wait_on_buffer(bh); + memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); + mark_buffer_uptodate(bh, 1); + mark_buffer_dirty(bh, 1); + } + return bh; + } + return NULL; +} + static struct buffer_head * inode_getblk(struct inode * inode, long block, int *err, long *phys, int *new) { @@ -1061,9 +1085,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) case FILE_TYPE_NONE: { if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) - inode->i_op = &udf_file_inode_operations_adinicb; + inode->i_data.a_ops = &udf_adinicb_aops; else - inode->i_op = &udf_file_inode_operations; + inode->i_data.a_ops = &udf_aops; + inode->i_op = &udf_file_inode_operations; inode->i_mode |= S_IFREG; break; } @@ -1084,7 +1109,8 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) } case FILE_TYPE_SYMLINK: { - inode->i_op = &udf_symlink_inode_operations; + inode->i_data.a_ops = &udf_symlink_aops; + inode->i_op = &page_symlink_inode_operations; inode->i_mode = S_IFLNK|S_IRWXUGO; break; } @@ -1953,58 +1979,3 @@ long udf_block_map(struct inode *inode, long block) unlock_kernel(); return ret; } - -int udf_readpage_adinicb (struct dentry *dentry, struct page * page) -{ - struct inode *inode = dentry->d_inode; - - struct buffer_head *bh; - int block; - unsigned long kaddr = 0; - - if (!PageLocked(page)) - PAGE_BUG(page); - - kaddr = kmap(page); - memset((char *)kaddr, 0, PAGE_CACHE_SIZE); - block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); - bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize); - ll_rw_block (READ, 1, &bh); - wait_on_buffer(bh); - memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode), - inode->i_size); - brelse(bh); - SetPageUptodate(page); - kunmap(page); - UnlockPage(page); - return 0; -} - -int udf_writepage_adinicb (struct dentry *dentry, struct page *page) -{ - struct inode *inode = dentry->d_inode; - - struct buffer_head *bh; - int block; - unsigned long kaddr = 0; - - if (!PageLocked(page)) - BUG(); - - kaddr = kmap(page); - block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); - bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize); - if (!buffer_uptodate(bh)) - { - ll_rw_block (READ, 1, &bh); - wait_on_buffer(bh); - } - memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr, - inode->i_size); - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer(bh); - brelse(bh); - SetPageUptodate(page); - kunmap(page); - return 0; -} diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 1f54833e42dc..aff491ef5483 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -642,7 +642,8 @@ int udf_create(struct inode *dir, struct dentry *dentry, int mode) if (!inode) return err; - inode->i_op = &udf_file_inode_operations_adinicb; + inode->i_data.a_ops = &udf_adinicb_aops; + inode->i_op = &udf_file_inode_operations; inode->i_mode = mode; mark_inode_dirty(inode); @@ -970,7 +971,8 @@ int udf_symlink(struct inode * dir, struct dentry * dentry, const char * symname goto out; inode->i_mode = S_IFLNK | S_IRWXUGO; - inode->i_op = &udf_symlink_inode_operations; + inode->i_data.a_ops = &udf_symlink_aops; + inode->i_op = &page_symlink_inode_operations; bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize); ea = bh->b_data + udf_file_entry_alloc_offset(inode); diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 6e5dd233ab04..5a286ce8408d 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -121,23 +121,6 @@ out: /* * symlinks can't do much... */ -struct inode_operations udf_symlink_inode_operations = { - NULL, /* no file-operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - page_readlink, /* readlink */ - page_follow_link, /* follow_link */ - NULL, /* get_block */ - udf_symlink_filler, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ +struct address_space_operations udf_symlink_aops = { + readpage: udf_symlink_filler, }; diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 4054da721e21..f5602dc0e663 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c @@ -188,21 +188,10 @@ void udf_truncate(struct inode * inode) if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return; - udf_trunc(inode); - - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); -} - -void udf_truncate_adinicb(struct inode * inode) -{ - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - - UDF_I_LENALLOC(inode) = inode->i_size; + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) + UDF_I_LENALLOC(inode) = inode->i_size; + else + udf_trunc(inode); inode->i_mtime = inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 171cd0d75c75..39418f73019b 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -63,8 +63,8 @@ struct super_block; extern struct inode_operations udf_dir_inode_operations; extern struct inode_operations udf_file_inode_operations; -extern struct inode_operations udf_file_inode_operations_adinicb; -extern struct inode_operations udf_symlink_inode_operations; +extern struct address_space_operations udf_adinicb_aops; +extern struct address_space_operations udf_symlink_aops; struct udf_fileident_bh { @@ -137,9 +137,6 @@ extern int udf_sync_inode(struct inode *); extern void udf_expand_file_adinicb(struct file *, int, int *); extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *); extern struct buffer_head * udf_getblk(struct inode *, long, int, int *); -extern int udf_get_block(struct inode *, long, struct buffer_head *, int); -extern int udf_readpage_adinicb (struct dentry *, struct page *); -extern int udf_writepage_adinicb (struct dentry *, struct page *); extern struct buffer_head * udf_bread(struct inode *, int, int, int *); extern void udf_read_inode(struct inode *); extern void udf_put_inode(struct inode *); @@ -187,14 +184,12 @@ extern struct inode * udf_new_inode (const struct inode *, int, int *); /* truncate.c */ extern void udf_trunc(struct inode *); extern void udf_truncate(struct inode *); -extern void udf_truncate_adinicb(struct inode *); /* balloc.c */ extern void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32); extern int udf_alloc_blocks(const struct inode *, Uint16, Uint32, Uint32); extern int udf_new_block(const struct inode *, Uint16, Uint32, int *); extern int udf_sync_file(struct file *, struct dentry *); -extern int udf_sync_file_adinicb(struct file *, struct dentry *); /* directory.c */ extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *); diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index d9701af9247f..0e4e3a72027f 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -195,9 +195,6 @@ struct inode_operations ufs_dir_inode_operations = { ufs_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ ufs_permission, /* permission */ NULL /* revalidate */ diff --git a/fs/ufs/file.c b/fs/ufs/file.c index 277586de8bfc..384774cc5326 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c @@ -36,11 +36,6 @@ #include #include -#define NBUF 32 - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - /* * Make sure the offset never goes beyond the 32-bit mark.. */ @@ -72,50 +67,6 @@ static long long ufs_file_lseek( return retval; } -static inline void remove_suid(struct inode *inode) -{ - unsigned int mode; - - /* set S_IGID if S_IXGRP is set, and always set S_ISUID */ - mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID; - - /* was any of the uid bits set? */ - mode &= inode->i_mode; - if (mode && !suser()) { - inode->i_mode &= ~mode; - mark_inode_dirty(inode); - } -} - -/* - * Write to a file (through the page cache). - */ -static ssize_t -ufs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - ssize_t retval; - - retval = generic_file_write(file, buf, count, - ppos, block_write_partial_page); - if (retval > 0) { - struct inode *inode = file->f_dentry->d_inode; - remove_suid(inode); - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - mark_inode_dirty(inode); - } - return retval; -} - -/* - * Called when an inode is released. Note that this is different - * from ufs_open: open gets called at every open, but release - * gets called only when /all/ the files are closed. - */ -static int ufs_release_file (struct inode * inode, struct file * filp) -{ - return 0; -} - /* * We have mostly NULL's here: the current defaults are ok for * the ufs filesystem. @@ -123,28 +74,11 @@ static int ufs_release_file (struct inode * inode, struct file * filp) static struct file_operations ufs_file_operations = { llseek: ufs_file_lseek, read: generic_file_read, - write: ufs_file_write, + write: generic_file_write, mmap: generic_file_mmap, - release: ufs_release_file, }; struct inode_operations ufs_file_inode_operations = { - &ufs_file_operations,/* default file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - ufs_getfrag_block, /* get_block */ - block_read_full_page, /* readpage */ - block_write_full_page, /* writepage */ - ufs_truncate, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ + &ufs_file_operations, + truncate: ufs_truncate, }; diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 333186247ad5..de2eec9a84c0 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -395,7 +395,7 @@ out: return result; } -int ufs_getfrag_block (struct inode *inode, long fragment, struct buffer_head *bh_result, int create) +static int ufs_getfrag_block (struct inode *inode, long fragment, struct buffer_head *bh_result, int create) { struct super_block * sb; struct ufs_sb_private_info * uspi; @@ -540,6 +540,30 @@ struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment, return NULL; } +static int ufs_writepage(struct dentry *dentry, struct page *page) +{ + return block_write_full_page(page,ufs_getfrag_block); +} +static int ufs_readpage(struct dentry *dentry, struct page *page) +{ + return block_read_full_page(page,ufs_getfrag_block); +} +static int ufs_prepare_write(struct page *page, unsigned from, unsigned to) +{ + return block_prepare_write(page,from,to,ufs_getfrag_block); +} +static int ufs_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,ufs_getfrag_block); +} +struct address_space_operations ufs_aops = { + readpage: ufs_readpage, + writepage: ufs_writepage, + prepare_write: ufs_prepare_write, + commit_write: generic_commit_write, + bmap: ufs_bmap +}; + void ufs_read_inode (struct inode * inode) { struct super_block * sb; @@ -619,15 +643,19 @@ void ufs_read_inode (struct inode * inode) inode->i_op = NULL; - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { inode->i_op = &ufs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) + inode->i_mapping->a_ops = &ufs_aops; + } else if (S_ISDIR(inode->i_mode)) inode->i_op = &ufs_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = inode->i_blocks - ?&ufs_symlink_inode_operations - :&ufs_fast_symlink_inode_operations; - else + else if (S_ISLNK(inode->i_mode)) { + if (!inode->i_blocks) + inode->i_op = &ufs_fast_symlink_inode_operations; + else { + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &ufs_aops; + } + } else init_special_inode(inode, inode->i_mode, SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0])); diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 33413b8cd0d3..71198abc4a55 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -424,6 +424,7 @@ int ufs_create (struct inode * dir, struct dentry * dentry, int mode) if (!inode) return err; inode->i_op = &ufs_file_inode_operations; + inode->i_mapping->a_ops = &ufs_aops; inode->i_mode = mode; mark_inode_dirty(inode); bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); @@ -776,7 +777,8 @@ int ufs_symlink (struct inode * dir, struct dentry * dentry, if (l > sb->u.ufs_sb.s_uspi->s_maxsymlinklen) { /* slow symlink */ - inode->i_op = &ufs_symlink_inode_operations; + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &ufs_aops; err = block_symlink(inode, symname, l); if (err) goto out_no_entry; diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c index 06ee827402d5..4550f44cfd6a 100644 --- a/fs/ufs/symlink.c +++ b/fs/ufs/symlink.c @@ -1,6 +1,8 @@ /* * linux/fs/ufs/symlink.c * + * Only fast symlinks left here - the rest is done by generic code. AV, 1999 + * * Copyright (C) 1998 * Daniel Pirkl * Charles University, Faculty of Mathematics and Physics @@ -24,7 +26,6 @@ */ #include -#include static int ufs_readlink(struct dentry *dentry, char *buffer, int buflen) { @@ -42,10 +43,3 @@ struct inode_operations ufs_fast_symlink_inode_operations = { readlink: ufs_readlink, follow_link: ufs_follow_link, }; - -struct inode_operations ufs_symlink_inode_operations = { - readlink: page_readlink, - follow_link: page_follow_link, - get_block: ufs_getfrag_block, - readpage: block_read_full_page -}; diff --git a/fs/umsdos/Makefile b/fs/umsdos/Makefile index 8856feba7680..f1b7b3ed4159 100644 --- a/fs/umsdos/Makefile +++ b/fs/umsdos/Makefile @@ -8,8 +8,7 @@ # Note 2: the CFLAGS definitions are now in the main makefile. O_TARGET := umsdos.o -O_OBJS := dir.o inode.o ioctl.o mangle.o namei.o \ - rdir.o symlink.o emd.o check.o +O_OBJS := dir.o inode.o ioctl.o mangle.o namei.o rdir.o emd.o check.o M_OBJS := $(O_TARGET) diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index b3effd28511e..366657ae62d5 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -819,12 +819,4 @@ struct inode_operations umsdos_dir_inode_operations = UMSDOS_rmdir, /* rmdir */ UMSDOS_mknod, /* mknod */ UMSDOS_rename, /* rename */ - NULL, /* readlink */ - NULL, /* followlink */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index 252f8a48b747..fb8dc03ff990 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -155,7 +155,8 @@ dentry, f_pos)); } else if (S_ISDIR (inode->i_mode)) { umsdos_setup_dir(dentry); } else if (S_ISLNK (inode->i_mode)) { - inode->i_op = &umsdos_symlink_inode_operations; + /* address_space operations already set */ + inode->i_op = &page_symlink_inode_operations; } else init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev)); diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c index 003f9b9c4b0b..a466a9396113 100644 --- a/fs/umsdos/rdir.c +++ b/fs/umsdos/rdir.c @@ -237,12 +237,4 @@ struct inode_operations umsdos_rdir_inode_operations = UMSDOS_rrmdir, /* rmdir */ NULL, /* mknod */ msdos_rename, /* rename */ - NULL, /* readlink */ - NULL, /* followlink */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* get_block */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; diff --git a/fs/umsdos/symlink.c b/fs/umsdos/symlink.c deleted file mode 100644 index 7bcd09e4421f..000000000000 --- a/fs/umsdos/symlink.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * linux/fs/umsdos/file.c - * - * Written 1992 by Jacques Gelinas - * inspired from linux/fs/msdos/file.c Werner Almesberger - * - * Extended MS-DOS regular file handling primitives - * - * Wow. It looks like we could support them on FAT with little (if any) - * problems. Oh, well... - */ - -#include -#include - -struct inode_operations umsdos_symlink_inode_operations = -{ - readlink: page_readlink, - follow_link: page_follow_link, - get_block: fat_get_block, - readpage: block_read_full_page -}; diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 0dea64e75f5f..0aced9465726 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -1276,14 +1276,6 @@ struct inode_operations vfat_dir_inode_operations = { vfat_rmdir, /* rmdir */ NULL, /* mknod */ vfat_rename, /* rename */ - NULL, /* readlink */ - NULL, /* followlink */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ }; struct super_block *vfat_read_super(struct super_block *sb,void *data, diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h index 7a4e9facc0d4..4ec380c2d753 100644 --- a/include/asm-i386/io.h +++ b/include/asm-i386/io.h @@ -195,15 +195,15 @@ extern void iounmap(void *addr); */ #define __ISA_IO_base ((char *)(PAGE_OFFSET)) -#define isa_readb(a) readb(__ISA_IO_base + (a)) -#define isa_readw(a) readw(__ISA_IO_base + (a)) -#define isa_readl(a) readl(__ISA_IO_base + (a)) -#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (a)) -#define isa_writew(w,a) writew(w,__ISA_IO_base + (a)) -#define isa_writel(l,a) writel(l,__ISA_IO_base + (a)) -#define isa_memset_io(a,b,c) memset_io(__ISA_IO_base + (a),(b),(c)) -#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),__ISA_IO_base + (b),(c)) -#define isa_memcpy_toio(a,b,c) memcpy_toio(__ISA_IO_base + (a),(b),(c)) +#define isa_readb(a) readb(__ISA_IO_base + (unsigned long)(a)) +#define isa_readw(a) readw(__ISA_IO_base + (unsigned long)(a)) +#define isa_readl(a) readl(__ISA_IO_base + (unsigned long)(a)) +#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (unsigned long)(a)) +#define isa_writew(w,a) writew(w,__ISA_IO_base + (unsigned long)(a)) +#define isa_writel(l,a) writel(l,__ISA_IO_base + (unsigned long)(a)) +#define isa_memset_io(a,b,c) memset_io(__ISA_IO_base + (unsigned long)(a),(b),(c)) +#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),__ISA_IO_base + (unsigned long)(b),(c)) +#define isa_memcpy_toio(a,b,c) memcpy_toio(__ISA_IO_base + (unsigned long)(a),(b),(c)) /* @@ -211,7 +211,7 @@ extern void iounmap(void *addr); */ #define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(b),(c),(d)) -#define isa_eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d)) +#define isa_eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (unsigned long)(b)),(c),(d)) static inline int check_signature(unsigned long io_addr, const unsigned char *signature, int length) diff --git a/include/asm-ia64/atomic.h b/include/asm-ia64/atomic.h index 105eea2c28aa..a1ec41e3bd69 100644 --- a/include/asm-ia64/atomic.h +++ b/include/asm-ia64/atomic.h @@ -12,7 +12,6 @@ * Copyright (C) 1998, 1999 Hewlett-Packard Co * Copyright (C) 1998, 1999 David Mosberger-Tang */ -#include #include #include diff --git a/include/linux/adfs_fs_i.h b/include/linux/adfs_fs_i.h index 71633319fe72..94d5607bfa54 100644 --- a/include/linux/adfs_fs_i.h +++ b/include/linux/adfs_fs_i.h @@ -11,6 +11,7 @@ * adfs file system inode data in memory */ struct adfs_inode_info { + unsigned long mmu_private; unsigned long parent_id; /* object id of parent */ __u32 loadaddr; /* RISC OS load address */ __u32 execaddr; /* RISC OS exec address */ diff --git a/include/linux/affs_fs.h b/include/linux/affs_fs.h index 342ac2648c30..90e5a3dd24a3 100644 --- a/include/linux/affs_fs.h +++ b/include/linux/affs_fs.h @@ -105,11 +105,11 @@ extern void affs_dir_truncate(struct inode *); extern struct inode_operations affs_file_inode_operations; extern struct inode_operations affs_file_inode_operations_ofs; extern struct inode_operations affs_dir_inode_operations; -extern struct inode_operations affs_symlink_inode_operations; -extern struct inode_operations affs_chrdev_inode_operations; -extern struct inode_operations affs_blkdev_inode_operations; +extern struct address_space_operations affs_symlink_aops; +extern struct address_space_operations affs_aops; extern struct dentry_operations affs_dentry_operations; extern struct dentry_operations affs_dentry_operations_intl; +extern int affs_bmap(struct inode *, int); #endif diff --git a/include/linux/affs_fs_i.h b/include/linux/affs_fs_i.h index beeabb0de9c8..a55951fbf837 100644 --- a/include/linux/affs_fs_i.h +++ b/include/linux/affs_fs_i.h @@ -29,6 +29,7 @@ struct ext_cache { * affs fs inode data in memory */ struct affs_inode_info { + unsigned long mmu_private; u32 i_protect; /* unused attribute bits */ s32 i_parent; /* parent ino */ s32 i_original; /* if != 0, this is the key of the original */ diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h index eaa8bd1be6e5..3c8c7e01ff71 100644 --- a/include/linux/agp_backend.h +++ b/include/linux/agp_backend.h @@ -48,6 +48,7 @@ enum chipset_type { VIA_GENERIC, VIA_VP3, VIA_MVP3, + VIA_MVP4, VIA_APOLLO_PRO, SIS_GENERIC, AMD_GENERIC, diff --git a/include/linux/bfs_fs.h b/include/linux/bfs_fs.h index 880ac7f0baf0..7e7de106ab83 100644 --- a/include/linux/bfs_fs.h +++ b/include/linux/bfs_fs.h @@ -83,6 +83,7 @@ extern int init_bfs_fs(void); /* file.c */ extern struct inode_operations bfs_file_inops; +extern struct address_space_operations bfs_aops; /* dir.c */ extern struct inode_operations bfs_dir_inops; diff --git a/include/linux/coda.h b/include/linux/coda.h index 8cb3ff46b25b..6e1a939bedba 100644 --- a/include/linux/coda.h +++ b/include/linux/coda.h @@ -305,33 +305,35 @@ struct coda_statfs { #define CODA_INACTIVE 21 #define CODA_VGET 22 #define CODA_SIGNAL 23 -#define CODA_REPLACE 24 -#define CODA_FLUSH 25 -#define CODA_PURGEUSER 26 -#define CODA_ZAPFILE 27 -#define CODA_ZAPDIR 28 -#define CODA_PURGEFID 30 +#define CODA_REPLACE 24 /* DOWNCALL */ +#define CODA_FLUSH 25 /* DOWNCALL */ +#define CODA_PURGEUSER 26 /* DOWNCALL */ +#define CODA_ZAPFILE 27 /* DOWNCALL */ +#define CODA_ZAPDIR 28 /* DOWNCALL */ +#define CODA_PURGEFID 30 /* DOWNCALL */ #define CODA_OPEN_BY_PATH 31 #define CODA_RESOLVE 32 #define CODA_REINTEGRATE 33 #define CODA_STATFS 34 -#define CODA_NCALLS 35 +#define CODA_MAKE_CINODE 35 /* DOWNCALL */ +#define CODA_NCALLS 36 -#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID) +#define DOWNCALL(opcode) \ + ((opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID) || \ + opcode == CODA_MAKE_CINODE) #define VC_MAXDATASIZE 8192 #define VC_MAXMSGSIZE sizeof(union inputArgs)+sizeof(union outputArgs) +\ VC_MAXDATASIZE #define CIOC_KERNEL_VERSION _IOWR('c', 10, sizeof (int)) + #if 0 - /* don't care about kernel version number */ -#define CODA_KERNEL_VERSION 0 - /* The old venus 4.6 compatible interface */ -#define CODA_KERNEL_VERSION 1 +#define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */ +#define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */ +#define CODA_KERNEL_VERSION 2 /* venus_lookup gets an extra parameter */ #endif - /* venus_lookup gets an extra parameter to aid windows.*/ -#define CODA_KERNEL_VERSION 2 +#define CODA_KERNEL_VERSION 3 /* added CODA_MAKE_CINODE downcall */ /* * Venus <-> Coda RPC arguments @@ -650,6 +652,13 @@ struct coda_purgefid_out { ViceFid CodaFid; }; +struct coda_make_cinode_out { + struct coda_out_hdr oh; + ViceFid CodaFid; + struct coda_vattr attr; + int fd; +}; + /* coda_rdwr: */ struct coda_rdwr_in { struct coda_in_hdr ih; @@ -751,6 +760,7 @@ union outputArgs { struct coda_purgefid_out coda_purgefid; struct coda_rdwr_out coda_rdwr; struct coda_replace_out coda_replace; + struct coda_make_cinode_out coda_make_cinode; struct coda_open_by_path_out coda_open_by_path; struct coda_statfs_out coda_statfs; }; diff --git a/include/linux/coda_fs_i.h b/include/linux/coda_fs_i.h index baa136b97b01..302a715b9c65 100644 --- a/include/linux/coda_fs_i.h +++ b/include/linux/coda_fs_i.h @@ -40,6 +40,8 @@ struct coda_inode_info { #define C_INITED 0x20 #define C_FLUSH 0x2 /* used after a flush */ +struct inode *coda_iget(struct super_block * sb, ViceFid * fid, + struct coda_vattr * attr); int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *); int coda_cnode_makectl(struct inode **inode, struct super_block *sb); struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb); diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h index cd0e46cea303..59cd5da3c39d 100644 --- a/include/linux/coda_linux.h +++ b/include/linux/coda_linux.h @@ -26,7 +26,9 @@ extern struct inode_operations coda_dir_inode_operations; extern struct inode_operations coda_file_inode_operations; extern struct inode_operations coda_ioctl_inode_operations; -extern struct inode_operations coda_symlink_inode_operations; + +extern struct address_space_operations coda_file_aops; +extern struct address_space_operations coda_symlink_aops; extern struct file_operations coda_dir_operations; extern struct file_operations coda_file_operations; diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h index f23a8e9b9c82..2b6bbadd7673 100644 --- a/include/linux/coda_psdev.h +++ b/include/linux/coda_psdev.h @@ -101,6 +101,7 @@ struct upc_req { #define REQ_ASYNC 0x1 #define REQ_READ 0x2 #define REQ_WRITE 0x4 +#define REQ_ABORT 0x8 /* diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h index a36f9d6fdc96..f422f4e51648 100644 --- a/include/linux/efs_fs.h +++ b/include/linux/efs_fs.h @@ -47,7 +47,7 @@ static const char cprt[] = "EFS: "EFS_VERSION" - (c) 1999 Al Smith b_page->flags) + #include #include #include @@ -332,10 +333,23 @@ struct iattr { * oh the beauties of C type declarations. */ struct page; +struct address_space; + +struct address_space_operations { + int (*writepage) (struct dentry *, struct page *); + int (*readpage)(struct dentry *, struct page *); + int (*prepare_write)(struct page *, unsigned, unsigned); + int (*commit_write)(struct file *, struct page *, unsigned, unsigned); + /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ + int (*bmap)(struct address_space *, long); +}; struct address_space { - struct list_head pages; - unsigned long nrpages; + struct list_head pages; /* list of pages */ + unsigned long nrpages; /* number of pages */ + struct address_space_operations *a_ops; /* methods */ + void *host; /* owner: inode, block_device */ + void *private; /* private data */ }; struct block_device { @@ -374,6 +388,7 @@ struct inode { wait_queue_head_t i_wait; struct file_lock *i_flock; struct vm_area_struct *i_mmap; + struct address_space *i_mapping; struct address_space i_data; spinlock_t i_shared_lock; struct dquot *i_dquot[MAXQUOTAS]; @@ -655,24 +670,6 @@ struct inode_operations { struct inode *, struct dentry *); int (*readlink) (struct dentry *, char *,int); struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int); - /* - * the order of these functions within the VFS template has been - * changed because SMP locking has changed: from now on all get_block, - * readpage and writepage functions are supposed to do - * whatever locking they need to get proper SMP operation - for - * now in most cases this means a lock/unlock_kernel at entry/exit. - * [The new order is also slightly more logical :)] - */ - /* - * Generic block allocator exported by the lowlevel fs. All metadata - * details are handled by the lowlevel fs, all 'logical data content' - * details are handled by the highlevel block layer. - */ - int (*get_block) (struct inode *, long, struct buffer_head *, int); - - int (*readpage) (struct dentry *, struct page *); - int (*writepage) (struct dentry *, struct page *); - void (*truncate) (struct inode *); int (*permission) (struct inode *, int); int (*revalidate) (struct dentry *); @@ -779,7 +776,6 @@ extern int blkdev_put(struct block_device *, int); extern int register_chrdev(unsigned int, const char *, struct file_operations *); extern int unregister_chrdev(unsigned int, const char *); extern int chrdev_open(struct inode *, struct file *); -extern struct file_operations def_chr_fops; extern const char * bdevname(kdev_t); extern const char * cdevname(kdev_t); extern const char * kdevname(kdev_t); @@ -975,30 +971,29 @@ extern void wakeup_bdflush(int wait); extern int brw_page(int, struct page *, kdev_t, int [], int); typedef int (*writepage_t)(struct file *, struct page *, unsigned long, unsigned long, const char *); +typedef int (get_block_t)(struct inode*,long,struct buffer_head*,int); /* Generic buffer handling for block filesystems.. */ -extern int block_read_full_page(struct dentry *, struct page *); -extern int block_write_full_page (struct dentry *, struct page *); -extern int block_write_partial_page (struct file *, struct page *, unsigned long, unsigned long, const char *); -extern int block_write_cont_page (struct file *, struct page *, unsigned long, unsigned long, const char *); -extern int block_write_zero_range(struct inode *, struct page *, unsigned, unsigned, unsigned, const char *); -extern inline int block_write_range(struct inode *inode, struct page *page, - unsigned from, unsigned len,const char *buf) -{ - return block_write_zero_range(inode, page, from, from, from+len, buf); -} extern int block_flushpage(struct page *, unsigned long); extern int block_symlink(struct inode *, const char *, int); +extern int block_write_full_page(struct page*, get_block_t*); +extern int block_read_full_page(struct page*, get_block_t*); +extern int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); +extern int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*, + unsigned long *); +int generic_block_bmap(struct address_space *, long, get_block_t *); +int generic_commit_write(struct file *, struct page *, unsigned, unsigned); extern int generic_file_mmap(struct file *, struct vm_area_struct *); extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *); -extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *, writepage_t); +extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *); extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t); extern int vfs_readlink(struct dentry *, char *, int, const char *); extern struct dentry *vfs_follow_link(struct dentry *, struct dentry *, unsigned, const char *); extern int page_readlink(struct dentry *, char *, int); extern struct dentry *page_follow_link(struct dentry *, struct dentry *, unsigned); +struct inode_operations page_symlink_inode_operations; extern struct super_block *get_super(kdev_t); struct super_block *get_empty_super(void); diff --git a/include/linux/hfs_fs_i.h b/include/linux/hfs_fs_i.h index 03585a08644a..4416d7837751 100644 --- a/include/linux/hfs_fs_i.h +++ b/include/linux/hfs_fs_i.h @@ -19,6 +19,7 @@ struct hfs_inode_info { int magic; /* A magic number */ + unsigned long mmu_private; struct hfs_cat_entry *entry; /* For a regular or header file */ diff --git a/include/linux/hpfs_fs_i.h b/include/linux/hpfs_fs_i.h index 8263bf2d7178..56a758b1627a 100644 --- a/include/linux/hpfs_fs_i.h +++ b/include/linux/hpfs_fs_i.h @@ -2,6 +2,7 @@ #define _HPFS_FS_I struct hpfs_inode_info { + unsigned long mmu_private; ino_t i_parent_dir; /* (directories) gives fnode of parent dir */ unsigned i_dno; /* (directories) root dnode */ unsigned i_dpos; /* (directories) temp for readdir */ diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h index 80a8b27f42aa..59da5b123553 100644 --- a/include/linux/iso_fs.h +++ b/include/linux/iso_fs.h @@ -178,7 +178,6 @@ extern int iso_date(char *, int); extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); -extern int rock_ridge_symlink_readpage(struct dentry *, struct page *); extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *); int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *); @@ -192,10 +191,7 @@ extern int isofs_lookup_grandparent(struct inode *, int); extern struct inode_operations isofs_file_inode_operations; extern struct inode_operations isofs_dir_inode_operations; -extern struct inode_operations isofs_symlink_inode_operations; -extern struct inode_operations isofs_chrdev_inode_operations; -extern struct inode_operations isofs_blkdev_inode_operations; -extern struct inode_operations isofs_fifo_inode_operations; +extern struct address_space_operations isofs_symlink_aops; /* The following macros are used to check for memory leaks. */ #ifdef LEAK_CHECK diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h index dcfbca271719..c1d661460d54 100644 --- a/include/linux/minix_fs.h +++ b/include/linux/minix_fs.h @@ -107,10 +107,7 @@ extern int minix_new_block(struct inode * inode); extern void minix_free_block(struct inode * inode, int block); extern unsigned long minix_count_free_blocks(struct super_block *sb); -extern int minix_bmap(struct inode *,int); - extern struct buffer_head * minix_getblk(struct inode *, int, int); -extern int minix_get_block(struct inode *, long, struct buffer_head *, int); extern struct buffer_head * minix_bread(struct inode *, int, int); extern void minix_truncate(struct inode *); @@ -118,9 +115,9 @@ extern int init_minix_fs(void); extern int minix_sync_inode(struct inode *); extern int minix_sync_file(struct file *, struct dentry *); +extern struct address_space_operations minix_aops; extern struct inode_operations minix_file_inode_operations; extern struct inode_operations minix_dir_inode_operations; -extern struct inode_operations minix_symlink_inode_operations; extern struct dentry_operations minix_dentry_operations; #endif /* __KERNEL__ */ diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 3a7f286228c4..54c1cbd55361 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -271,11 +271,6 @@ extern ssize_t fat_file_read(struct file *, char *, size_t, loff_t *); extern ssize_t fat_file_write(struct file *, const char *, size_t, loff_t *); extern void fat_truncate(struct inode *inode); -/* mmap.c */ -extern int fat_mmap(struct file *, struct vm_area_struct *); -extern int fat_readpage(struct file *, struct page *); - - /* vfat.c */ extern int init_vfat_fs(void); diff --git a/include/linux/msdos_fs_i.h b/include/linux/msdos_fs_i.h index bcb37bb80ef1..8d66550d2a62 100644 --- a/include/linux/msdos_fs_i.h +++ b/include/linux/msdos_fs_i.h @@ -6,6 +6,7 @@ */ struct msdos_inode_info { + unsigned long mmu_private; int i_start; /* first cluster or 0 */ int i_logstart; /* logical first cluster */ int i_attrs; /* unused attribute bits */ @@ -13,7 +14,6 @@ struct msdos_inode_info { int i_location; /* on-disk position of directory entry or 0 */ struct inode *i_fat_inode; /* struct inode of this one */ struct list_head i_fat_hash; /* hash by i_location */ - int i_realsize; }; #endif diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index f2a114a58fc8..26fb2de7f480 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -190,6 +190,7 @@ extern int __nfs_revalidate_inode(struct nfs_server *, struct dentry *); * linux/fs/nfs/file.c */ extern struct inode_operations nfs_file_inode_operations; +extern struct address_space_operations nfs_file_aops; /* * linux/fs/nfs/dir.c diff --git a/include/linux/ntfs_fs_i.h b/include/linux/ntfs_fs_i.h index 0bc8d780665b..3ac18ea47e07 100644 --- a/include/linux/ntfs_fs_i.h +++ b/include/linux/ntfs_fs_i.h @@ -62,6 +62,7 @@ typedef unsigned int ntfs_cluster_t; /* Definition of NTFS in-memory inode structure */ struct ntfs_inode_info{ + unsigned long mmu_private; struct ntfs_sb_info *vol; int i_number; /* should be really 48 bits */ unsigned sequence_number; diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 53bc365d28d5..813dd78ea25b 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -83,7 +83,7 @@ extern void add_to_page_cache(struct page * page, struct address_space *mapping, extern inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long index) { - __add_page_to_hash_queue(page, page_hash(&inode->i_data,index)); + __add_page_to_hash_queue(page, page_hash(inode->i_mapping,index)); } extern inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page) diff --git a/include/linux/pci.h b/include/linux/pci.h index 15b1d900a9c7..8fae97e9b050 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -572,6 +572,19 @@ extern inline int pci_enable_device(struct pci_dev *dev) { return 0; } #endif /* !CONFIG_PCI */ +/* these helpers provide future and backwards compatibility + * for accessing popular PCI BAR info */ +#define pci_resource_start(dev,bar) ((dev)->resource[(bar)].start) +#define pci_resource_end(dev,bar) ((dev)->resource[(bar)].end) +#define pci_resource_flags(dev,bar) ((dev)->resource[(bar)].flags) +#define pci_resource_len(dev,bar) \ + ((pci_resource_start((dev),(bar)) == 0 && \ + pci_resource_end((dev),(bar)) == \ + pci_resource_start((dev),(bar))) ? 0 : \ + \ + (pci_resource_end((dev),(bar)) - \ + pci_resource_start((dev),(bar)) + 1)) + /* * The world is not perfect and supplies us with broken PCI devices. * For at least a part of these bugs we need a work-around, so both diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h index e340e3dfef34..d831875bbbd5 100644 --- a/include/linux/qnx4_fs.h +++ b/include/linux/qnx4_fs.h @@ -108,7 +108,6 @@ extern int init_qnx4_fs(void); extern int qnx4_create(struct inode *dir, struct dentry *dentry, int mode); extern struct inode_operations qnx4_file_inode_operations; extern struct inode_operations qnx4_dir_inode_operations; -extern struct inode_operations qnx4_symlink_inode_operations; extern int qnx4_is_free(struct super_block *sb, long block); extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy); extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode); diff --git a/include/linux/qnx4_fs_i.h b/include/linux/qnx4_fs_i.h index 57439fe57a6d..b0fe8463e7e1 100644 --- a/include/linux/qnx4_fs_i.h +++ b/include/linux/qnx4_fs_i.h @@ -33,6 +33,7 @@ struct qnx4_inode_info { __u8 i_zero[4]; /* 4 */ qnx4_ftype_t i_type; /* 1 */ __u8 i_status; /* 1 */ + unsigned long mmu_private; }; #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index 08fbf2e6f535..41efb2e8c88f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -80,7 +80,6 @@ extern int last_pid; #define TASK_UNINTERRUPTIBLE 2 #define TASK_ZOMBIE 4 #define TASK_STOPPED 8 -#define TASK_SWAPPING 16 #define TASK_EXCLUSIVE 32 #define __set_task_state(tsk, state_value) \ diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h index 451ff761a86e..52c3d7f33a81 100644 --- a/include/linux/smb_fs.h +++ b/include/linux/smb_fs.h @@ -101,6 +101,7 @@ int smb_mmap(struct file *, struct vm_area_struct *); /* linux/fs/smbfs/file.c */ extern struct inode_operations smb_file_inode_operations; +extern struct address_space_operations smb_file_aops; /* linux/fs/smbfs/dir.c */ extern struct inode_operations smb_dir_inode_operations; diff --git a/include/linux/sysv_fs.h b/include/linux/sysv_fs.h index 5168218e00e3..4f65ba7dd365 100644 --- a/include/linux/sysv_fs.h +++ b/include/linux/sysv_fs.h @@ -384,7 +384,6 @@ extern int sysv_new_block(struct super_block * sb); extern void sysv_free_block(struct super_block * sb, unsigned int block); extern unsigned long sysv_count_free_blocks(struct super_block *sb); -extern int sysv_get_block(struct inode *, long, struct buffer_head *, int); extern struct buffer_head * sysv_file_bread(struct inode *, int, int); extern void sysv_truncate(struct inode *); @@ -394,9 +393,8 @@ extern int sysv_sync_inode(struct inode *); extern int sysv_sync_file(struct file *, struct dentry *); extern struct inode_operations sysv_file_inode_operations; -extern struct inode_operations sysv_file_inode_operations_with_bmap; extern struct inode_operations sysv_dir_inode_operations; -extern struct inode_operations sysv_symlink_inode_operations; +extern struct address_space_operations sysv_aops; #endif /* __KERNEL__ */ diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index b650d7897f14..83a6a69e7022 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h @@ -525,6 +525,8 @@ extern int ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_ent extern struct inode_operations ufs_file_inode_operations; extern struct file_operations ufs_file_operations; +extern struct address_space_operations ufs_aops; + /* ialloc.c */ extern void ufs_free_inode (struct inode *inode); extern struct inode * ufs_new_inode (const struct inode *, int, int *); @@ -538,7 +540,6 @@ extern int ufs_sync_inode (struct inode *); extern void ufs_write_inode (struct inode *); extern void ufs_delete_inode (struct inode *); extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *); -extern int ufs_getfrag_block (struct inode *, long, struct buffer_head *, int); extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); /* namei.c */ @@ -562,7 +563,6 @@ extern int init_ufs_fs(void); extern void ufs_write_super (struct super_block *); /* symlink.c */ -extern struct inode_operations ufs_symlink_inode_operations; extern struct inode_operations ufs_fast_symlink_inode_operations; /* truncate.c */ diff --git a/include/linux/umsdos_fs.h b/include/linux/umsdos_fs.h index 56ebe78aac11..1e7a0beada0a 100644 --- a/include/linux/umsdos_fs.h +++ b/include/linux/umsdos_fs.h @@ -174,7 +174,6 @@ struct umsdos_ioctl { #endif extern struct inode_operations umsdos_dir_inode_operations; -extern struct inode_operations umsdos_symlink_inode_operations; extern int init_umsdos_fs (void); #include diff --git a/kernel/Makefile b/kernel/Makefile index 270692eb2b84..cce15a5240cb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -29,6 +29,14 @@ ifeq ($(CONFIG_MODULES),y) OX_OBJS += ksyms.o endif +ifdef CONFIG_ACPI +OX_OBJS += pm.o +else + ifdef CONFIG_APM + OX_OBJS += pm.o + endif +endif + CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer include $(TOPDIR)/Rules.make diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c index c31678a4e2c0..1ee1eee4d9d3 100644 --- a/kernel/exec_domain.c +++ b/kernel/exec_domain.c @@ -103,12 +103,11 @@ asmlinkage long sys_personality(unsigned long personality) unsigned long old_personality; int ret; - lock_kernel(); - ret = current->personality; if (personality == 0xffffffff) - goto out; + return current->personality; ret = -EINVAL; + lock_kernel(); it = lookup_exec_domain(personality); if (!it) goto out; diff --git a/kernel/ksyms.c b/kernel/ksyms.c index e34d941759f7..3672877a93e1 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -184,11 +184,12 @@ EXPORT_SYMBOL(__bforget); EXPORT_SYMBOL(ll_rw_block); EXPORT_SYMBOL(__wait_on_buffer); EXPORT_SYMBOL(___wait_on_page); -EXPORT_SYMBOL(block_read_full_page); EXPORT_SYMBOL(block_write_full_page); -EXPORT_SYMBOL(block_write_partial_page); -EXPORT_SYMBOL(block_write_cont_page); -EXPORT_SYMBOL(block_write_zero_range); +EXPORT_SYMBOL(block_read_full_page); +EXPORT_SYMBOL(block_prepare_write); +EXPORT_SYMBOL(cont_prepare_write); +EXPORT_SYMBOL(generic_commit_write); +EXPORT_SYMBOL(generic_block_bmap); EXPORT_SYMBOL(generic_file_read); EXPORT_SYMBOL(do_generic_file_read); EXPORT_SYMBOL(generic_file_write); @@ -223,6 +224,7 @@ EXPORT_SYMBOL(vfs_readlink); EXPORT_SYMBOL(vfs_follow_link); EXPORT_SYMBOL(page_readlink); EXPORT_SYMBOL(page_follow_link); +EXPORT_SYMBOL(page_symlink_inode_operations); EXPORT_SYMBOL(block_symlink); /* for stackable file systems (lofs, wrapfs, etc.) */ diff --git a/arch/i386/kernel/pm.c b/kernel/pm.c similarity index 100% rename from arch/i386/kernel/pm.c rename to kernel/pm.c diff --git a/kernel/sched.c b/kernel/sched.c index 61fc91a6143b..03c05e7c36a2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1145,7 +1145,6 @@ void daemonize(void) void __init init_idle(void) { - cycles_t t; struct schedule_data * sched_data; sched_data = &aligned_data[smp_processor_id()].schedule_data; @@ -1154,9 +1153,8 @@ void __init init_idle(void) smp_processor_id(), current->pid); del_from_runqueue(current); } - t = get_cycles(); sched_data->curr = current; - sched_data->last_schedule = t; + sched_data->last_schedule = get_cycles(); } void __init sched_init(void) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3ab91f36e3c4..9a6a7a74d0b4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -129,9 +129,6 @@ struct inode_operations proc_sys_inode_operations = NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ proc_sys_permission, /* permission */ NULL /* revalidate */ diff --git a/kernel/timer.c b/kernel/timer.c index fbe98e48b93a..f087d239fc90 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -594,8 +594,7 @@ static unsigned long count_active_tasks(void) read_lock(&tasklist_lock); for_each_task(p) { if ((p->state == TASK_RUNNING || - (p->state & TASK_UNINTERRUPTIBLE) || - (p->state & TASK_SWAPPING))) + (p->state & TASK_UNINTERRUPTIBLE))) nr += FIXED_1; } read_unlock(&tasklist_lock); diff --git a/mm/filemap.c b/mm/filemap.c index 29e5947d7e3e..4772ed2544f8 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -98,7 +98,7 @@ void invalidate_inode_pages(struct inode * inode) struct list_head *head, *curr; struct page * page; - head = &inode->i_data.pages; + head = &inode->i_mapping->pages; spin_lock(&pagecache_lock); curr = head->next; @@ -134,7 +134,7 @@ void truncate_inode_pages(struct inode * inode, loff_t lstart) start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; repeat: - head = &inode->i_data.pages; + head = &inode->i_mapping->pages; spin_lock(&pagecache_lock); curr = head->next; while (curr != head) { @@ -423,7 +423,7 @@ static int do_buffer_fdatasync(struct inode *inode, unsigned long start, unsigne struct page *page; int retval = 0; - head = &inode->i_data.pages; + head = &inode->i_mapping->pages; spin_lock(&pagecache_lock); curr = head->next; @@ -525,11 +525,12 @@ static int add_to_page_cache_unique(struct page * page, static inline int page_cache_read(struct file * file, unsigned long offset) { struct inode *inode = file->f_dentry->d_inode; - struct page **hash = page_hash(&inode->i_data, offset); + struct address_space *mapping = inode->i_mapping; + struct page **hash = page_hash(mapping, offset); struct page *page; spin_lock(&pagecache_lock); - page = __find_page_nolock(&inode->i_data, offset, *hash); + page = __find_page_nolock(mapping, offset, *hash); spin_unlock(&pagecache_lock); if (page) return 0; @@ -538,8 +539,8 @@ static inline int page_cache_read(struct file * file, unsigned long offset) if (!page) return -ENOMEM; - if (!add_to_page_cache_unique(page, &inode->i_data, offset, hash)) { - int error = inode->i_op->readpage(file->f_dentry, page); + if (!add_to_page_cache_unique(page, mapping, offset, hash)) { + int error = mapping->a_ops->readpage(file->f_dentry, page); page_cache_release(page); return error; } @@ -955,6 +956,7 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * { struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; + struct address_space *mapping = inode->i_mapping; unsigned long index, offset; struct page *cached_page; int reada_ok; @@ -1023,10 +1025,10 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * /* * Try to find the data in the page cache.. */ - hash = page_hash(&inode->i_data, index); + hash = page_hash(mapping, index); spin_lock(&pagecache_lock); - page = __find_page_nolock(&inode->i_data, index, *hash); + page = __find_page_nolock(mapping, index, *hash); if (!page) goto no_cached_page; found_page: @@ -1074,7 +1076,7 @@ page_not_up_to_date: readpage: /* ... and start the actual read. The read will unlock the page. */ - error = inode->i_op->readpage(filp->f_dentry, page); + error = mapping->a_ops->readpage(filp->f_dentry, page); if (!error) { if (Page_Uptodate(page)) @@ -1113,7 +1115,7 @@ no_cached_page: * dropped the page cache lock. Check for that. */ spin_lock(&pagecache_lock); - page = __find_page_nolock(&inode->i_data, index, *hash); + page = __find_page_nolock(mapping, index, *hash); if (page) goto found_page; } @@ -1122,7 +1124,7 @@ no_cached_page: * Ok, add the new page to the hash-queues... */ page = cached_page; - __add_to_page_cache(page, &inode->i_data, index, hash); + __add_to_page_cache(page, mapping, index, hash); spin_unlock(&pagecache_lock); cached_page = NULL; @@ -1233,7 +1235,7 @@ asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t cou in_inode = in_file->f_dentry->d_inode; if (!in_inode) goto fput_in; - if (!in_inode->i_op || !in_inode->i_op->readpage) + if (!in_inode->i_mapping->a_ops->readpage) goto fput_in; retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count); if (retval) @@ -1307,6 +1309,7 @@ struct page * filemap_nopage(struct vm_area_struct * area, struct file *file = area->vm_file; struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; + struct address_space *mapping = inode->i_mapping; struct page *page, **hash, *old_page; unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; @@ -1325,9 +1328,9 @@ struct page * filemap_nopage(struct vm_area_struct * area, /* * Do we have something in the page cache already? */ - hash = page_hash(&inode->i_data, pgoff); + hash = page_hash(mapping, pgoff); retry_find: - page = __find_get_page(&inode->i_data, pgoff, hash); + page = __find_get_page(mapping, pgoff, hash); if (!page) goto no_cached_page; @@ -1396,7 +1399,7 @@ page_not_uptodate: goto success; } - if (!inode->i_op->readpage(file->f_dentry, page)) { + if (!mapping->a_ops->readpage(file->f_dentry, page)) { wait_on_page(page); if (Page_Uptodate(page)) goto success; @@ -1414,7 +1417,7 @@ page_not_uptodate: goto success; } ClearPageError(page); - if (!inode->i_op->readpage(file->f_dentry, page)) { + if (!mapping->a_ops->readpage(file->f_dentry, page)) { wait_on_page(page); if (Page_Uptodate(page)) goto success; @@ -1446,7 +1449,7 @@ static inline int do_write_page(struct inode * inode, struct file * file, if (size_idx <= index) return -EIO; } - writepage = inode->i_op->writepage; + writepage = inode->i_mapping->a_ops->writepage; lock_page(page); retval = writepage(file->f_dentry, page); @@ -1658,13 +1661,13 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma) ops = &file_private_mmap; if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) { - if (!inode->i_op || !inode->i_op->writepage) + if (!inode->i_mapping->a_ops->writepage) return -EINVAL; ops = &file_shared_mmap; } if (!inode->i_sb || !S_ISREG(inode->i_mode)) return -EACCES; - if (!inode->i_op || !inode->i_op->readpage) + if (!inode->i_mapping->a_ops->readpage) return -ENOEXEC; UPDATE_ATIME(inode); vma->vm_ops = ops; @@ -1816,6 +1819,21 @@ struct page *grab_cache_page(struct address_space *mapping, unsigned long index) return page; } +static inline void remove_suid(struct inode *inode) +{ + unsigned int mode; + + /* set S_IGID if S_IXGRP is set, and always set S_ISUID */ + mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID; + + /* was any of the uid bits set? */ + mode &= inode->i_mode; + if (mode && !capable(CAP_FSETID)) { + inode->i_mode &= ~mode; + mark_inode_dirty(inode); + } +} + /* * Write to a file through the page cache. This is mainly for the * benefit of NFS and possibly other network-based file systems. @@ -1833,12 +1851,11 @@ struct page *grab_cache_page(struct address_space *mapping, unsigned long index) * okir@monad.swb.de */ ssize_t -generic_file_write(struct file *file, const char *buf, - size_t count, loff_t *ppos, - writepage_t write_one_page) +generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos) { struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; + struct address_space *mapping = inode->i_mapping; unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; loff_t pos; struct page *page, *cached_page; @@ -1882,9 +1899,15 @@ generic_file_write(struct file *file, const char *buf, } status = 0; + if (count) { + remove_suid(inode); + inode->i_ctime = inode->i_mtime = CURRENT_TIME; + mark_inode_dirty(inode); + } while (count) { unsigned long bytes, index, offset; + char *kaddr; /* * Try to find the page in the cache. If it isn't there, @@ -1897,7 +1920,7 @@ generic_file_write(struct file *file, const char *buf, bytes = count; status = -ENOMEM; /* we'll assign it later anyway */ - page = __grab_cache_page(&inode->i_data, index, &cached_page); + page = __grab_cache_page(mapping, index, &cached_page); if (!page) break; @@ -1906,7 +1929,16 @@ generic_file_write(struct file *file, const char *buf, PAGE_BUG(page); } - status = write_one_page(file, page, offset, bytes, buf); + status = mapping->a_ops->prepare_write(page, offset, offset+bytes); + if (status) + goto unlock; + kaddr = (char*)page_address(page); + status = copy_from_user(kaddr+offset, buf, bytes); + if (status) + goto fail_write; + status = mapping->a_ops->commit_write(file, page, offset, offset+bytes); + if (!status) + status = bytes; if (status >= 0) { written += status; @@ -1916,6 +1948,7 @@ generic_file_write(struct file *file, const char *buf, if (pos > inode->i_size) inode->i_size = pos; } +unlock: /* Mark it unlocked again and drop the page.. */ UnlockPage(page); page_cache_release(page); @@ -1932,6 +1965,11 @@ generic_file_write(struct file *file, const char *buf, out: up(&inode->i_sem); return err; +fail_write: + status = -EFAULT; + ClearPageUptodate(page); + kunmap(page); + goto unlock; } void __init page_cache_init(unsigned long mempages) diff --git a/net/khttpd/datasending.c b/net/khttpd/datasending.c index 058b308dcfce..a26afe191a7a 100644 --- a/net/khttpd/datasending.c +++ b/net/khttpd/datasending.c @@ -114,8 +114,7 @@ int DataSending(const int CPUNR) inode = CurrentRequest->filp->f_dentry->d_inode; - if ( (inode!=NULL)&&(inode->i_op!=NULL)&&(inode->i_op->readpage!=NULL)) - { + if (inode && inode->i_mapping->a_ops->readpage) { /* This does the actual transfer using sendfile */ read_descriptor_t desc; loff_t *ppos; diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 34ea71e122c1..131f37f46cc0 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -33,15 +33,20 @@ #include #include #include -#if LINUX_VERSION_CODE >= 0x020100 #include -#endif #include #include #include #include +/* SMP locking strategy: + * + * svc_sock->sk_lock and svc_serv->sv_lock protect their + * respective structures. + * + * Antideadlock ordering is sk_lock --> sv_lock. + */ #define RPCDBG_FACILITY RPCDBG_SVCSOCK @@ -54,20 +59,22 @@ static int svc_udp_sendto(struct svc_rqst *); /* - * Queue up an idle server thread. + * Queue up an idle server thread. Must have serv->sv_lock held. */ static inline void svc_serv_enqueue(struct svc_serv *serv, struct svc_rqst *rqstp) { + BUG_TRAP(spin_is_locked(&serv->sv_lock)); rpc_append_list(&serv->sv_threads, rqstp); } /* - * Dequeue an nfsd thread. + * Dequeue an nfsd thread. Must have serv->sv_lock held. */ static inline void svc_serv_dequeue(struct svc_serv *serv, struct svc_rqst *rqstp) { + BUG_TRAP(spin_is_locked(&serv->sv_lock)); rpc_remove_list(&serv->sv_threads, rqstp); } @@ -90,8 +97,8 @@ svc_release_skb(struct svc_rqst *rqstp) /* * Queue up a socket with data pending. If there are idle nfsd * processes, wake 'em up. - * When calling this function, you should make sure it can't be interrupted - * by the network bottom half. + * + * This must be called with svsk->sk_lock held. */ static void svc_sock_enqueue(struct svc_sock *svsk) @@ -101,6 +108,9 @@ svc_sock_enqueue(struct svc_sock *svsk) BUG_TRAP(spin_is_locked(&svsk->sk_lock)); + /* NOTE: Local BH is already disabled by our caller. */ + spin_lock(&serv->sv_lock); + if (serv->sv_threads && serv->sv_sockets) printk(KERN_ERR "svc_sock_enqueue: threads and sockets both waiting??\n"); @@ -108,7 +118,7 @@ svc_sock_enqueue(struct svc_sock *svsk) if (svsk->sk_busy) { /* Don't enqueue socket while daemon is receiving */ dprintk("svc: socket %p busy, not enqueued\n", svsk->sk_sk); - return; + goto out_unlock; } /* Mark socket as busy. It will remain in this state until the @@ -133,20 +143,23 @@ svc_sock_enqueue(struct svc_sock *svsk) rpc_append_list(&serv->sv_sockets, svsk); svsk->sk_qued = 1; } + +out_unlock: + spin_unlock(&serv->sv_lock); } /* - * Dequeue the first socket. + * Dequeue the first socket. Must be called with the serv->sv_lock held. */ static inline struct svc_sock * svc_sock_dequeue(struct svc_serv *serv) { struct svc_sock *svsk; - spin_lock_bh(&serv->sv_lock); + BUG_TRAP(spin_is_locked(&serv->sv_lock)); + if ((svsk = serv->sv_sockets) != NULL) rpc_remove_list(&serv->sv_sockets, svsk); - spin_unlock_bh(&serv->sv_lock); if (svsk) { dprintk("svc: socket %p dequeued, inuse=%d\n", @@ -223,6 +236,7 @@ svc_wake_up(struct svc_serv *serv) { struct svc_rqst *rqstp; + spin_lock_bh(&serv->sv_lock); if ((rqstp = serv->sv_threads) != NULL) { dprintk("svc: daemon %p woken up.\n", rqstp); /* @@ -231,6 +245,7 @@ svc_wake_up(struct svc_serv *serv) */ wake_up(&rqstp->rq_wait); } + spin_unlock_bh(&serv->sv_lock); } /* @@ -254,19 +269,11 @@ svc_sendto(struct svc_rqst *rqstp, struct iovec *iov, int nr) msg.msg_control = NULL; msg.msg_controllen = 0; -#if LINUX_VERSION_CODE >= 0x020100 msg.msg_flags = MSG_DONTWAIT; oldfs = get_fs(); set_fs(KERNEL_DS); len = sock_sendmsg(sock, &msg, buflen); set_fs(oldfs); -#else - msg.msg_flags = 0; - - oldfs = get_fs(); set_fs(KERNEL_DS); - len = sock->ops->sendmsg(sock, &msg, buflen, 1, 0); - set_fs(oldfs); -#endif dprintk("svc: socket %p sendto([%p %Zu... ], %d, %d) = %d\n", rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, nr, buflen, len); @@ -312,19 +319,11 @@ svc_recvfrom(struct svc_rqst *rqstp, struct iovec *iov, int nr, int buflen) msg.msg_control = NULL; msg.msg_controllen = 0; -#if LINUX_VERSION_CODE >= 0x020100 msg.msg_flags = MSG_DONTWAIT; oldfs = get_fs(); set_fs(KERNEL_DS); len = sock_recvmsg(sock, &msg, buflen, MSG_DONTWAIT); set_fs(oldfs); -#else - msg.msg_flags = 0; - - oldfs = get_fs(); set_fs(KERNEL_DS); - len = sock->ops->recvmsg(sock, &msg, buflen, 0, 1, &rqstp->rq_addrlen); - set_fs(oldfs); -#endif dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len); @@ -387,11 +386,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) /* Get sender address */ rqstp->rq_addr.sin_family = AF_INET; rqstp->rq_addr.sin_port = skb->h.uh->source; -#if LINUX_VERSION_CODE >= 0x020100 rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr; -#else - rqstp->rq_addr.sin_addr.s_addr = skb->saddr; -#endif if (serv->sv_stats) serv->sv_stats->netudpcnt++; @@ -878,11 +873,7 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock, } memset(svsk, 0, sizeof(*svsk)); -#if LINUX_VERSION_CODE >= 0x020100 inet = sock->sk; -#else - inet = (struct sock *) sock->data; -#endif inet->user_data = svsk; svsk->sk_sock = sock; svsk->sk_sk = inet; @@ -909,8 +900,10 @@ if (svsk->sk_sk == NULL) return NULL; } + spin_lock_bh(&serv->sv_lock); svsk->sk_list = serv->sv_allsocks; serv->sv_allsocks = svsk; + spin_unlock_bh(&serv->sv_lock); dprintk("svc: svc_setup_socket created %p (inet %p)\n", svsk, svsk->sk_sk); @@ -983,16 +976,22 @@ svc_delete_socket(struct svc_sock *svsk) sk->state_change = svsk->sk_ostate; sk->data_ready = svsk->sk_odata; + spin_lock_bh(&serv->sv_lock); + for (rsk = &serv->sv_allsocks; *rsk; rsk = &(*rsk)->sk_list) { if (*rsk == svsk) break; } - if (!*rsk) + if (!*rsk) { + spin_unlock_bh(&serv->sv_lock); return; + } *rsk = svsk->sk_list; - if (svsk->sk_qued) rpc_remove_list(&serv->sv_sockets, svsk); + + spin_unlock_bh(&serv->sv_lock); + svsk->sk_dead = 1; if (!svsk->sk_inuse) { diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 6535e0f0a4c3..6219c37209c1 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -76,13 +76,8 @@ proc_dodebug(ctl_table *table, int write, struct file *file, if (!access_ok(VERIFY_READ, buffer, left)) return -EFAULT; p = (char *) buffer; -#if LINUX_VERSION_CODE >= 0x020100 while (left && __get_user(c, p) >= 0 && isspace(c)) left--, p++; -#else - while (left && (c = get_fs_byte(p)) >= 0 && isspace(c)) - left--, p++; -#endif if (!left) goto done; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 9a22a63c3e4d..48dd5623d543 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -65,17 +65,9 @@ #include -#define SOCK_HAS_USER_DATA /* Following value should be > 32k + RPC overhead */ #define XPRT_MIN_WRITE_SPACE 35000 -/* - * Local variables - */ -#ifndef SOCK_HAS_USER_DATA -static struct rpc_xprt * sock_list = NULL; -#endif - /* Spinlock for critical sections in the code. */ spinlock_t xprt_lock = SPIN_LOCK_UNLOCKED; @@ -140,15 +132,7 @@ xprt_pktdump(char *msg, u32 *packet, unsigned int count) static inline struct rpc_xprt * xprt_from_sock(struct sock *sk) { -#ifndef SOCK_HAS_USER_DATA - struct rpc_xprt *xprt; - - for (xprt = sock_list; xprt && sk != xprt->inet; xprt = xprt->link) - ; - return xprt; -#else return (struct rpc_xprt *) sk->user_data; -#endif } /* @@ -352,9 +336,7 @@ xprt_close(struct rpc_xprt *xprt) xprt_disconnect(xprt); -#ifdef SOCK_HAS_USER_DATA sk->user_data = NULL; -#endif sk->data_ready = xprt->old_data_ready; sk->state_change = xprt->old_state_change; sk->write_space = xprt->old_write_space; @@ -433,9 +415,7 @@ xprt_reconnect(struct rpc_task *task) inet->data_ready = xprt->inet->data_ready; inet->state_change = xprt->inet->state_change; inet->write_space = xprt->inet->write_space; -#ifdef SOCK_HAS_USER_DATA inet->user_data = xprt; -#endif dprintk("RPC: %4d closing old socket\n", task->tk_pid); xprt_close(xprt); @@ -1456,12 +1436,7 @@ xprt_setup(struct socket *sock, int proto, xprt->stream = (proto == IPPROTO_TCP)? 1 : 0; xprt->congtime = jiffies; init_waitqueue_head(&xprt->cong_wait); -#ifdef SOCK_HAS_USER_DATA inet->user_data = xprt; -#else - xprt->link = sock_list; - sock_list = xprt; -#endif xprt->old_data_ready = inet->data_ready; xprt->old_state_change = inet->state_change; xprt->old_write_space = inet->write_space; @@ -1627,18 +1602,6 @@ xprt_clear_backlog(struct rpc_xprt *xprt) { int xprt_destroy(struct rpc_xprt *xprt) { -#ifndef SOCK_HAS_USER_DATA - struct rpc_xprt **q; - - for (q = &sock_list; *q && *q != xprt; q = &((*q)->link)) - ; - if (!*q) { - printk(KERN_WARNING "xprt_destroy: unknown socket!\n"); - return -EIO; /* why is there no EBUGGYSOFTWARE */ - } - *q = xprt->link; -#endif - dprintk("RPC: destroying transport %p\n", xprt); xprt_close(xprt); kfree(xprt); diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index e0b8feba76a1..cb84199901e2 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -107,9 +107,6 @@ static struct inode_operations router_inode = NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ router_proc_perms, /* permission */ NULL /* revalidate */ @@ -139,9 +136,6 @@ static struct inode_operations wandev_inode = NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ NULL, /* truncate */ router_proc_perms, /* permission */ NULL /* revalidate */ -- 2.39.5