diff options
278 files changed, 4666 insertions, 5139 deletions
diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt index d279875f452a..d932f686b203 100644 --- a/Documentation/crypto/api-intro.txt +++ b/Documentation/crypto/api-intro.txt @@ -215,6 +215,8 @@ AES algorithm contributors: Herbert Valerio Riedel Kyle McMartin Adam J. Richter + Fruhwirth Clemens (i586) + Linus Torvalds (i586) CAST5 algorithm contributors: Kartikey Mahendra Bhatt (original developers unknown, FSF copyright). diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index b7554bd47703..5ead20c6c744 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -19,23 +19,18 @@ fmask=### -- The permission mask for files. codepage=### -- Sets the codepage number for converting to shortname characters on FAT filesystem. - - NOTE: If this option was not specified, the file name - may not be read/written rightly, also filesystem is - mounted as read-only. + By default, FAT_DEFAULT_CODEPAGE setting is used. iocharset=name -- Character set to use for converting between the encoding is used for user visible filename and 16 bit Unicode characters. Long filenames are stored on disk in Unicode format, but Unix for the most part doesn't know how to deal with Unicode. + By default, FAT_DEFAULT_IOCHARSET setting is used. + There is also an option of doing UTF8 translations with the utf8 option. - NOTE: If this option was not specified, the file name - may not be read/written rightly, also filesystem is - mounted as read-only. - NOTE: "iocharset=utf8" is not recommended. If unsure, you should consider the following option instead. diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index e384c9f5f5ee..fae0c98cfdca 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -5182,7 +5182,7 @@ struct _snd_pcm_runtime { The callback is much more complicated than the text-file version. You need to use a low-level i/o functions such as <function>copy_from/to_user()</function> to transfer the - data. Also, you have to keep tracking the file position, too. + data. <informalexample> <programlisting> @@ -5190,14 +5190,15 @@ struct _snd_pcm_runtime { static long my_file_io_read(snd_info_entry_t *entry, void *file_private_data, struct file *file, - char *buf, long count) + char *buf, + unsigned long count, + unsigned long pos) { long size = count; - if (file->f_pos + size > local_max_size) - size = local_max_size - file->f_pos; - if (copy_to_user(buf, local_data + file->f_pos, size)) + if (pos + size > local_max_size) + size = local_max_size - pos; + if (copy_to_user(buf, local_data + pos, size)) return -EFAULT; - file->f_pos += size; return size; } ]]> @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 8 -EXTRAVERSION =-rc3 +EXTRAVERSION =-rc4 NAME=Zonked Quokka # *DOCUMENTATION* @@ -619,12 +619,7 @@ $(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(vmlinux-dirs) ; .PHONY: $(vmlinux-dirs) $(vmlinux-dirs): prepare-all scripts - $(Q)if [ ! -z $$LC_ALL ]; then \ - export LANG=$$LC_ALL; \ - export LC_ALL= ; \ - fi; \ - export LC_COLLATE=C; export LC_CTYPE=C; \ - $(MAKE) $(build)=$@ + $(Q)$(MAKE) $(build)=$@ # Things we need to do before we recursively start building the kernel # or the modules are listed in "prepare-all". diff --git a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile index 6318bc963d96..8e8879b6b3d7 100644 --- a/arch/arm/boot/bootp/Makefile +++ b/arch/arm/boot/bootp/Makefile @@ -7,10 +7,10 @@ LDFLAGS_bootp :=-p --no-undefined -X \ --defsym params_phys=$(PARAMS_PHYS) -T AFLAGS_initrd.o :=-DINITRD=\"$(INITRD)\" -targets := bootp bootp.lds init.o kernel.o initrd.o +targets := bootp init.o kernel.o initrd.o # Note that bootp.lds picks up kernel.o and initrd.o -$(obj)/bootp: $(addprefix $(obj)/,bootp.lds init.o kernel.o initrd.o) FORCE +$(obj)/bootp: $(src)/bootp.lds $(addprefix $(obj)/,init.o kernel.o initrd.o) FORCE $(call if_changed,ld) @: diff --git a/arch/arm/boot/bootp/init.S b/arch/arm/boot/bootp/init.S index fc4cc2fb1e1b..df7bc7068d0f 100644 --- a/arch/arm/boot/bootp/init.S +++ b/arch/arm/boot/bootp/init.S @@ -20,8 +20,10 @@ .type _start, #function .globl _start -_start: adr r13, data +_start: add lr, pc, #-0x8 @ lr = current load addr + adr r13, data ldmia r13!, {r4-r6} @ r5 = dest, r6 = length + add r4, r4, lr @ r4 = initrd_start + load addr bl move @ move the initrd /* diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 4b5a13f93b6b..951fbf6e81f8 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -101,7 +101,7 @@ $(obj)/piggy.o: $(obj)/piggy.gz FORCE CFLAGS_font.o := -Dstatic= $(obj)/font.o: $(FONTC) -$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in Makefile arch/arm/boot/Makefile .config +$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config @sed "$(SEDFLAGS)" < $< > $@ $(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 052cef493743..797292aa0805 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -11,7 +11,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set -CONFIG_STANDALONE=y CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y @@ -20,17 +19,24 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # # Loadable module support @@ -44,58 +50,32 @@ CONFIG_KMOD=y # # System Type # -# CONFIG_ARCH_ADIFCC is not set -# CONFIG_ARCH_ANAKIN is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set CONFIG_ARCH_S3C2410=y - -# -# CLPS711X/EP721X Implementations -# - -# -# Epxa10db -# - -# -# Footbridge Implementations -# - -# -# IOP3xx Implementation Options -# -# CONFIG_ARCH_IOP310 is not set -# CONFIG_ARCH_IOP321 is not set - -# -# IOP3xx Chipset Features -# - -# -# Intel PXA250/210 Implementations -# - -# -# SA11x0 Implementations -# +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE_PB is not set # # S3C2410 Implementations # CONFIG_ARCH_BAST=y CONFIG_ARCH_H1940=y +CONFIG_ARCH_SMDK2410=y +CONFIG_MACH_VR1000=y # # Processor Type @@ -120,9 +100,8 @@ CONFIG_CPU_TLB_V4WBI=y # General setup # # CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 -# CONFIG_HOTPLUG is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 # # At least one math emulation must be selected @@ -130,6 +109,7 @@ CONFIG_ZBOOT_ROM_BSS=0 CONFIG_FPE_NWFPE=y CONFIG_FPE_NWFPE_XP=y # CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -137,6 +117,9 @@ CONFIG_BINFMT_AOUT=y # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set # CONFIG_PM is not set # CONFIG_PREEMPT is not set # CONFIG_ARTHUR is not set @@ -149,7 +132,6 @@ CONFIG_ALIGNMENT_TRAP=y CONFIG_PARPORT=y CONFIG_PARPORT_PC=y CONFIG_PARPORT_PC_CML1=y -# CONFIG_PARPORT_SERIAL is not set CONFIG_PARPORT_PC_FIFO=y CONFIG_PARPORT_PC_SUPERIO=y # CONFIG_PARPORT_ARC is not set @@ -180,9 +162,20 @@ CONFIG_MTD_CFI=y # CONFIG_MTD_JEDECPROBE is not set CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set # CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set @@ -200,6 +193,7 @@ CONFIG_MTD_CFI_INTELEXT=y # Self-contained MTD device drivers # # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set @@ -218,7 +212,6 @@ CONFIG_MTD_CFI_INTELEXT=y # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -259,23 +252,21 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -291,11 +282,17 @@ CONFIG_IPV6_SCTP__=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -316,40 +313,25 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set -# CONFIG_HOSTAP is not set # -# Token Ring devices +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ATA/ATAPI/MFM/RLL support @@ -360,9 +342,9 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=m CONFIG_BLK_DEV_IDEFLOPPY=m @@ -372,10 +354,10 @@ CONFIG_BLK_DEV_IDEFLOPPY=m # # IDE chipset support/bugfixes # -CONFIG_BLK_DEV_IDE_BAST=y +CONFIG_IDE_GENERIC=y +# CONFIG_IDE_ARM is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set # CONFIG_BLK_DEV_HD is not set # @@ -384,13 +366,22 @@ CONFIG_BLK_DEV_IDE_BAST=y # CONFIG_SCSI is not set # +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# # I2O device support # # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Input device support @@ -406,7 +397,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_TSLIBDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -427,12 +417,13 @@ CONFIG_SERIO_SERPORT=y CONFIG_INPUT_KEYBOARD=y CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y -# CONFIG_MOUSE_PS2_SYNAPTICS is not set # CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -451,8 +442,6 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_DIGI is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set # CONFIG_RISCOM8 is not set @@ -480,15 +469,37 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_S3C2410=y CONFIG_SERIAL_S3C2410_CONSOLE=y CONFIG_SERIAL_BAST_SIO=y -# CONFIG_SERIAL_DZ is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 CONFIG_PRINTER=y # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=y # CONFIG_TIPAR is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # # I2C support @@ -507,55 +518,46 @@ CONFIG_I2C_ALGOBIT=m # # CONFIG_I2C_AMD756 is not set # CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_PHILIPSPAR is not set +# CONFIG_I2C_ISA is not set +# CONFIG_I2C_PARPORT is not set +# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_SCx200_ACB is not set # -# I2C Hardware Sensors Chip support +# Hardware Sensors Chip support # CONFIG_I2C_SENSOR=m # CONFIG_SENSORS_ADM1021 is not set -CONFIG_SENSORS_EEPROM=m +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set CONFIG_SENSORS_LM75=m +# CONFIG_SENSORS_LM77 is not set CONFIG_SENSORS_LM78=m +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set CONFIG_SENSORS_LM85=m -# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set # -# L3 serial bus support -# -# CONFIG_L3 is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver +# Other I2C Chip support # -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set +CONFIG_SENSORS_EEPROM=m +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set # # Multimedia devices @@ -568,11 +570,6 @@ CONFIG_RTC=y # CONFIG_DVB is not set # -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# # File systems # CONFIG_EXT2_FS=y @@ -611,8 +608,8 @@ CONFIG_VFAT_FS=y # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLBFS is not set @@ -625,14 +622,20 @@ CONFIG_RAMFS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set CONFIG_JFFS_FS=y CONFIG_JFFS_FS_VERBOSE=0 +# CONFIG_JFFS_PROC_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 # CONFIG_JFFS2_FS_NAND is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -652,12 +655,11 @@ CONFIG_ROOT_NFS=y CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -675,16 +677,15 @@ CONFIG_BSD_DISKLABEL=y CONFIG_SOLARIS_X86_PARTITION=y # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set -CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set @@ -709,6 +710,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -725,6 +727,11 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_UTF8 is not set # +# Profiling support +# +# CONFIG_PROFILING is not set + +# # Graphics support # CONFIG_FB=y @@ -744,21 +751,20 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_LOGO is not set # -# Misc devices +# Sound # +# CONFIG_SOUND is not set # -# Multimedia Capabilities Port drivers +# Misc devices # -# CONFIG_MCP is not set # -# Console Switches +# USB support # -# CONFIG_SWITCHES is not set # -# USB support +# USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -776,7 +782,6 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_PRINTK=y # CONFIG_DEBUG_ICEDCC is not set CONFIG_DEBUG_S3C2410_PORT=y CONFIG_DEBUG_S3C2410_UART=0 @@ -794,6 +799,8 @@ CONFIG_DEBUG_S3C2410_UART=0 # # Library routines # +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c index 34d6a867e368..9e8868bc55d4 100644 --- a/arch/arm/kernel/io.c +++ b/arch/arm/kernel/io.c @@ -7,12 +7,13 @@ * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */ -void _memcpy_fromio(void * to, unsigned long from, size_t count) +void _memcpy_fromio(void *to, unsigned long from, size_t count) { + unsigned char *t = to; while (count) { count--; - *(char *) to = readb(from); - ((char *) to)++; + *t = readb(from); + t++; from++; } } @@ -21,12 +22,13 @@ void _memcpy_fromio(void * to, unsigned long from, size_t count) * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */ -void _memcpy_toio(unsigned long to, const void * from, size_t count) +void _memcpy_toio(unsigned long to, const void *from, size_t count) { + const unsigned char *f = from; while (count) { count--; - writeb(*(char *) from, to); - ((char *) from)++; + writeb(*f, to); + f++; to++; } } diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index b71f89e11a73..40e78bc4460a 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -23,9 +23,12 @@ config ARCH_SMDK2410 <http://www.fsforth.de> config MACH_VR1000 - bool "Simtec VR1000" + bool "Thorcom VR1000" help - Say Y here if you are using the Simtec VR1000 board. + Say Y here if you are using the Thorcom VR1000 board. + + This linux port is currently being maintained by Simtec, on behalf + of Thorcom. Any queries, please contact Thorcom first. endmenu diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index fb180732b860..bfadbd4254f8 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -101,7 +101,7 @@ void __init smdk2410_init_irq(void) void __init smdk2410_init_time(void) { - s3c2401_init_time(); + s3c2410_init_time(); } MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 2246a30cea54..aae341c6908f 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -11,6 +11,7 @@ * published by the Free Software Foundation. * * Modifications: + * 06-Aug-2004 BJD Fixed call to time initialisation * 12-Jul-2004 BJD Renamed machine * 16-May-2003 BJD Created initial version * 16-Aug-2003 BJD Fixed header files and copyright, added URL @@ -159,7 +160,7 @@ void __init vr1000_init_irq(void) void __init vr1000_init_time(void) { - s3c2401_init_time(); + s3c2410_init_time(); } MACHINE_START(VR1000, "Thorcom-VR1000") diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index a38a1ffecbee..29be1c018949 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -66,9 +66,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) /* We must not map this if we have highmem enabled */ pte = pte_offset_map(pmd, addr); printk(", *pte=%08lx", pte_val(*pte)); -#ifdef CONFIG_CPU_32 printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE])); -#endif pte_unmap(pte); #endif } while(0); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index db6ebc236727..060fea2e10cb 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -24,13 +24,7 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> -#ifdef CONFIG_CPU_32 -#define TABLE_OFFSET (PTRS_PER_PTE) -#else -#define TABLE_OFFSET 0 -#endif - -#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(pte_t)) +#define TABLE_SIZE (2 * PTRS_PER_PTE * sizeof(pte_t)) DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -289,14 +283,13 @@ static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot */ reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext); -#ifdef CONFIG_CPU_32 /* * Reserve the page tables. These are already in use, * and can only be in node 0. */ reserve_bootmem_node(pgdat, __pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t)); -#endif + /* * And don't forget to reserve the allocator bitmap, * which will be freed later. diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index c3f14c7aa9c9..45cc65426a22 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -29,7 +29,7 @@ * stack+task struct. Use the same method as 'current' uses to * reach them. */ -register unsigned int *user_registers asm("sl"); +register unsigned long *user_registers asm("sl"); #define GET_USERREG() (user_registers) diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index 59e3197d6d54..2ad457558681 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -29,14 +29,14 @@ #include <asm/uaccess.h> -static inline void loadSingle(const unsigned int Fn, const unsigned int *pMem) +static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); fpa11->fType[Fn] = typeSingle; get_user(fpa11->fpreg[Fn].fSingle, pMem); } -static inline void loadDouble(const unsigned int Fn, const unsigned int *pMem) +static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); unsigned int *p; @@ -47,7 +47,7 @@ static inline void loadDouble(const unsigned int Fn, const unsigned int *pMem) } #ifdef CONFIG_FPE_NWFPE_XP -static inline void loadExtended(const unsigned int Fn, const unsigned int *pMem) +static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); unsigned int *p; @@ -59,7 +59,7 @@ static inline void loadExtended(const unsigned int Fn, const unsigned int *pMem) } #endif -static inline void loadMultiple(const unsigned int Fn, const unsigned int *pMem) +static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); register unsigned int *p; @@ -91,7 +91,7 @@ static inline void loadMultiple(const unsigned int Fn, const unsigned int *pMem) } } -static inline void storeSingle(const unsigned int Fn, unsigned int *pMem) +static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -117,7 +117,7 @@ static inline void storeSingle(const unsigned int Fn, unsigned int *pMem) put_user(val.i[0], pMem); } -static inline void storeDouble(const unsigned int Fn, unsigned int *pMem) +static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -145,7 +145,7 @@ static inline void storeDouble(const unsigned int Fn, unsigned int *pMem) } #ifdef CONFIG_FPE_NWFPE_XP -static inline void storeExtended(const unsigned int Fn, unsigned int *pMem) +static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -172,7 +172,7 @@ static inline void storeExtended(const unsigned int Fn, unsigned int *pMem) } #endif -static inline void storeMultiple(const unsigned int Fn, unsigned int *pMem) +static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); register unsigned int nType, *p; @@ -204,10 +204,10 @@ static inline void storeMultiple(const unsigned int Fn, unsigned int *pMem) unsigned int PerformLDF(const unsigned int opcode) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1, - write_back = WRITE_BACK(opcode); + unsigned int __user *pBase, *pAddress, *pFinal; + unsigned int nRc = 1, write_back = WRITE_BACK(opcode); - pBase = (unsigned int *) readRegister(getRn(opcode)); + pBase = (unsigned int __user *) readRegister(getRn(opcode)); if (REG_PC == getRn(opcode)) { pBase += 2; write_back = 0; @@ -241,18 +241,18 @@ unsigned int PerformLDF(const unsigned int opcode) } if (write_back) - writeRegister(getRn(opcode), (unsigned int) pFinal); + writeRegister(getRn(opcode), (unsigned long) pFinal); return nRc; } unsigned int PerformSTF(const unsigned int opcode) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1, - write_back = WRITE_BACK(opcode); + unsigned int __user *pBase, *pAddress, *pFinal; + unsigned int nRc = 1, write_back = WRITE_BACK(opcode); SetRoundingMode(ROUND_TO_NEAREST); - pBase = (unsigned int *) readRegister(getRn(opcode)); + pBase = (unsigned int __user *) readRegister(getRn(opcode)); if (REG_PC == getRn(opcode)) { pBase += 2; write_back = 0; @@ -286,16 +286,16 @@ unsigned int PerformSTF(const unsigned int opcode) } if (write_back) - writeRegister(getRn(opcode), (unsigned int) pFinal); + writeRegister(getRn(opcode), (unsigned long) pFinal); return nRc; } unsigned int PerformLFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal, - write_back = WRITE_BACK(opcode); + unsigned int __user *pBase, *pAddress, *pFinal; + unsigned int i, Fd, write_back = WRITE_BACK(opcode); - pBase = (unsigned int *) readRegister(getRn(opcode)); + pBase = (unsigned int __user *) readRegister(getRn(opcode)); if (REG_PC == getRn(opcode)) { pBase += 2; write_back = 0; @@ -322,16 +322,16 @@ unsigned int PerformLFM(const unsigned int opcode) } if (write_back) - writeRegister(getRn(opcode), (unsigned int) pFinal); + writeRegister(getRn(opcode), (unsigned long) pFinal); return 1; } unsigned int PerformSFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal, - write_back = WRITE_BACK(opcode); + unsigned int __user *pBase, *pAddress, *pFinal; + unsigned int i, Fd, write_back = WRITE_BACK(opcode); - pBase = (unsigned int *) readRegister(getRn(opcode)); + pBase = (unsigned int __user *) readRegister(getRn(opcode)); if (REG_PC == getRn(opcode)) { pBase += 2; write_back = 0; @@ -358,7 +358,7 @@ unsigned int PerformSFM(const unsigned int opcode) } if (write_back) - writeRegister(getRn(opcode), (unsigned int) pFinal); + writeRegister(getRn(opcode), (unsigned long) pFinal); return 1; } diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index 7c417158d6b2..a806fea5c3ed 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -131,7 +131,7 @@ void float_raise(signed char flags) #ifdef CONFIG_DEBUG_USER printk(KERN_DEBUG - "NWFPE: %s[%d] takes exception %08x at %p from %08x\n", + "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", current->comm, current->pid, flags, __builtin_return_address(0), GET_USERREG()[15]); #endif diff --git a/arch/arm/nwfpe/fpmodule.inl b/arch/arm/nwfpe/fpmodule.inl index 119fb3f48ec0..e5f59e9a3022 100644 --- a/arch/arm/nwfpe/fpmodule.inl +++ b/arch/arm/nwfpe/fpmodule.inl @@ -19,8 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -extern __inline__ -unsigned int readRegister(const unsigned int nReg) +static inline unsigned long readRegister(const unsigned int nReg) { /* Note: The CPU thinks it has dealt with the current instruction. As a result the program counter has been advanced to the next @@ -29,34 +28,31 @@ unsigned int readRegister(const unsigned int nReg) for this in this routine. LDF/STF instructions with Rn = PC depend on the PC being correct, as they use PC+8 in their address calculations. */ - unsigned int *userRegisters = GET_USERREG(); + unsigned long *userRegisters = GET_USERREG(); unsigned int val = userRegisters[nReg]; if (REG_PC == nReg) val -= 4; return val; } -extern __inline__ -void writeRegister(const unsigned int nReg, const unsigned int val) +static inline void +writeRegister(const unsigned int nReg, const unsigned long val) { - unsigned int *userRegisters = GET_USERREG(); + unsigned long *userRegisters = GET_USERREG(); userRegisters[nReg] = val; } -extern __inline__ -unsigned int readCPSR(void) +static inline unsigned long readCPSR(void) { return (readRegister(REG_CPSR)); } -extern __inline__ -void writeCPSR(const unsigned int val) +static inline void writeCPSR(const unsigned long val) { writeRegister(REG_CPSR, val); } -extern __inline__ -unsigned int readConditionCodes(void) +static inline unsigned long readConditionCodes(void) { #ifdef __FPEM_TEST__ return (0); @@ -65,11 +61,10 @@ unsigned int readConditionCodes(void) #endif } -extern __inline__ -void writeConditionCodes(const unsigned int val) +static inline void writeConditionCodes(const unsigned long val) { - unsigned int *userRegisters = GET_USERREG(); - unsigned int rval; + unsigned long *userRegisters = GET_USERREG(); + unsigned long rval; /* * Operate directly on userRegisters since * the CPSR may be the PC register itself. @@ -77,9 +72,3 @@ void writeConditionCodes(const unsigned int val) rval = userRegisters[REG_CPSR] & ~CC_MASK; userRegisters[REG_CPSR] = rval | (val & CC_MASK); } - -extern __inline__ -unsigned int readMemoryInt(unsigned int *pMem) -{ - return *pMem; -} diff --git a/arch/i386/Makefile b/arch/i386/Makefile index d83df8b413c5..1e446b2340a5 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -104,7 +104,8 @@ head-y := arch/i386/kernel/head.o arch/i386/kernel/init_task.o libs-y += arch/i386/lib/ core-y += arch/i386/kernel/ \ arch/i386/mm/ \ - arch/i386/$(mcore-y)/ + arch/i386/$(mcore-y)/ \ + arch/i386/crypto/ drivers-$(CONFIG_MATH_EMULATION) += arch/i386/math-emu/ drivers-$(CONFIG_PCI) += arch/i386/pci/ # must be linked after kernel/ diff --git a/arch/i386/crypto/Makefile b/arch/i386/crypto/Makefile new file mode 100644 index 000000000000..103c353d0a63 --- /dev/null +++ b/arch/i386/crypto/Makefile @@ -0,0 +1,9 @@ +# +# i386/crypto/Makefile +# +# Arch-specific CryptoAPI modules. +# + +obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o + +aes-i586-y := aes-i586-asm.o aes.o diff --git a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S new file mode 100644 index 000000000000..e8a04713df26 --- /dev/null +++ b/arch/i386/crypto/aes-i586-asm.S @@ -0,0 +1,341 @@ +// ------------------------------------------------------------------------- +// Copyright (c) 2001, Dr Brian Gladman < >, Worcester, UK. +// All rights reserved. +// +// LICENSE TERMS +// +// The free distribution and use of this software in both source and binary +// form is allowed (with or without changes) provided that: +// +// 1. distributions of this source code include the above copyright +// notice, this list of conditions and the following disclaimer// +// +// 2. distributions in binary form include the above copyright +// notice, this list of conditions and the following disclaimer +// in the documentation and/or other associated materials// +// +// 3. the copyright holder's name is not used to endorse products +// built using this software without specific written permission. +// +// +// ALTERNATIVELY, provided that this notice is retained in full, this product +// may be distributed under the terms of the GNU General Public License (GPL), +// in which case the provisions of the GPL apply INSTEAD OF those given above. +// +// Copyright (c) 2004 Linus Torvalds <torvalds@osdl.org> +// Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> + +// DISCLAIMER +// +// This software is provided 'as is' with no explicit or implied warranties +// in respect of its properties including, but not limited to, correctness +// and fitness for purpose. +// ------------------------------------------------------------------------- +// Issue Date: 29/07/2002 + +.file "aes-i586-asm.S" +.text + +// aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])// +// aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])// + +#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words) + +// offsets to parameters with one register pushed onto stack + +#define in_blk 8 // input byte array address parameter +#define out_blk 12 // output byte array address parameter +#define ctx 16 // AES context structure + +// offsets in context structure + +#define ekey 0 // encryption key schedule base address +#define nrnd 256 // number of rounds +#define dkey 260 // decryption key schedule base address + +// register mapping for encrypt and decrypt subroutines + +#define r0 eax +#define r1 ebx +#define r2 ecx +#define r3 edx +#define r4 esi +#define r5 edi +#define r6 ebp + +#define eaxl al +#define eaxh ah +#define ebxl bl +#define ebxh bh +#define ecxl cl +#define ecxh ch +#define edxl dl +#define edxh dh + +#define _h(reg) reg##h +#define h(reg) _h(reg) + +#define _l(reg) reg##l +#define l(reg) _l(reg) + +// This macro takes a 32-bit word representing a column and uses +// each of its four bytes to index into four tables of 256 32-bit +// words to obtain values that are then xored into the appropriate +// output registers r0, r1, r4 or r5. + +// Parameters: +// %1 out_state[0] +// %2 out_state[1] +// %3 out_state[2] +// %4 out_state[3] +// %5 table base address +// %6 input register for the round (destroyed) +// %7 scratch register for the round + +#define do_col(a1, a2, a3, a4, a5, a6, a7) \ + movzx %l(a6),%a7; \ + xor a5(,%a7,4),%a1; \ + movzx %h(a6),%a7; \ + shr $16,%a6; \ + xor a5+tlen(,%a7,4),%a2; \ + movzx %l(a6),%a7; \ + movzx %h(a6),%a6; \ + xor a5+2*tlen(,%a7,4),%a3; \ + xor a5+3*tlen(,%a6,4),%a4; + +// initialise output registers from the key schedule + +#define do_fcol(a1, a2, a3, a4, a5, a6, a7, a8) \ + mov 0 a8,%a1; \ + movzx %l(a6),%a7; \ + mov 12 a8,%a2; \ + xor a5(,%a7,4),%a1; \ + mov 4 a8,%a4; \ + movzx %h(a6),%a7; \ + shr $16,%a6; \ + xor a5+tlen(,%a7,4),%a2; \ + movzx %l(a6),%a7; \ + movzx %h(a6),%a6; \ + xor a5+3*tlen(,%a6,4),%a4; \ + mov %a3,%a6; \ + mov 8 a8,%a3; \ + xor a5+2*tlen(,%a7,4),%a3; + +// initialise output registers from the key schedule + +#define do_icol(a1, a2, a3, a4, a5, a6, a7, a8) \ + mov 0 a8,%a1; \ + movzx %l(a6),%a7; \ + mov 4 a8,%a2; \ + xor a5(,%a7,4),%a1; \ + mov 12 a8,%a4; \ + movzx %h(a6),%a7; \ + shr $16,%a6; \ + xor a5+tlen(,%a7,4),%a2; \ + movzx %l(a6),%a7; \ + movzx %h(a6),%a6; \ + xor a5+3*tlen(,%a6,4),%a4; \ + mov %a3,%a6; \ + mov 8 a8,%a3; \ + xor a5+2*tlen(,%a7,4),%a3; + + +// original Gladman had conditional saves to MMX regs. +#define save(a1, a2) \ + mov %a2,4*a1(%esp) + +#define restore(a1, a2) \ + mov 4*a2(%esp),%a1 + +// This macro performs a forward encryption cycle. It is entered with +// the first previous round column values in r0, r1, r4 and r5 and +// exits with the final values in the same registers, using the MMX +// registers mm0-mm1 or the stack for temporary storage + +// mov current column values into the MMX registers +#define fwd_rnd(arg, table) \ + /* mov current column values into the MMX registers */ \ + mov %r0,%r2; \ + save (0,r1); \ + save (1,r5); \ + \ + /* compute new column values */ \ + do_fcol(r0,r5,r4,r1,table, r2,r3, arg); \ + do_col (r4,r1,r0,r5,table, r2,r3); \ + restore(r2,0); \ + do_col (r1,r0,r5,r4,table, r2,r3); \ + restore(r2,1); \ + do_col (r5,r4,r1,r0,table, r2,r3); + +// This macro performs an inverse encryption cycle. It is entered with +// the first previous round column values in r0, r1, r4 and r5 and +// exits with the final values in the same registers, using the MMX +// registers mm0-mm1 or the stack for temporary storage + +#define inv_rnd(arg, table) \ + /* mov current column values into the MMX registers */ \ + mov %r0,%r2; \ + save (0,r1); \ + save (1,r5); \ + \ + /* compute new column values */ \ + do_icol(r0,r1,r4,r5, table, r2,r3, arg); \ + do_col (r4,r5,r0,r1, table, r2,r3); \ + restore(r2,0); \ + do_col (r1,r4,r5,r0, table, r2,r3); \ + restore(r2,1); \ + do_col (r5,r0,r1,r4, table, r2,r3); + +// AES (Rijndael) Encryption Subroutine + +.global aes_enc_blk + +.extern ft_tab +.extern fl_tab + +.align 4 + +aes_enc_blk: + push %ebp + mov ctx(%esp),%ebp // pointer to context + xor %eax,%eax + +// CAUTION: the order and the values used in these assigns +// rely on the register mappings + +1: push %ebx + mov in_blk+4(%esp),%r2 + push %esi + mov nrnd(%ebp),%r3 // number of rounds + push %edi + lea ekey(%ebp),%r6 // key pointer + +// input four columns and xor in first round key + + mov (%r2),%r0 + mov 4(%r2),%r1 + mov 8(%r2),%r4 + mov 12(%r2),%r5 + xor (%r6),%r0 + xor 4(%r6),%r1 + xor 8(%r6),%r4 + xor 12(%r6),%r5 + + sub $8,%esp // space for register saves on stack + add $16,%r6 // increment to next round key + sub $10,%r3 + je 4f // 10 rounds for 128-bit key + add $32,%r6 + sub $2,%r3 + je 3f // 12 rounds for 128-bit key + add $32,%r6 + +2: fwd_rnd( -64(%r6) ,ft_tab) // 14 rounds for 128-bit key + fwd_rnd( -48(%r6) ,ft_tab) +3: fwd_rnd( -32(%r6) ,ft_tab) // 12 rounds for 128-bit key + fwd_rnd( -16(%r6) ,ft_tab) +4: fwd_rnd( (%r6) ,ft_tab) // 10 rounds for 128-bit key + fwd_rnd( +16(%r6) ,ft_tab) + fwd_rnd( +32(%r6) ,ft_tab) + fwd_rnd( +48(%r6) ,ft_tab) + fwd_rnd( +64(%r6) ,ft_tab) + fwd_rnd( +80(%r6) ,ft_tab) + fwd_rnd( +96(%r6) ,ft_tab) + fwd_rnd(+112(%r6) ,ft_tab) + fwd_rnd(+128(%r6) ,ft_tab) + fwd_rnd(+144(%r6) ,fl_tab) // last round uses a different table + +// move final values to the output array. CAUTION: the +// order of these assigns rely on the register mappings + + add $8,%esp + mov out_blk+12(%esp),%r6 + mov %r5,12(%r6) + pop %edi + mov %r4,8(%r6) + pop %esi + mov %r1,4(%r6) + pop %ebx + mov %r0,(%r6) + pop %ebp + mov $1,%eax + ret + +// AES (Rijndael) Decryption Subroutine + +.global aes_dec_blk + +.extern it_tab +.extern il_tab + +.align 4 + +aes_dec_blk: + push %ebp + mov ctx(%esp),%ebp // pointer to context + xor %eax,%eax + +// CAUTION: the order and the values used in these assigns +// rely on the register mappings + +1: push %ebx + mov in_blk+4(%esp),%r2 + push %esi + mov nrnd(%ebp),%r3 // number of rounds + push %edi + lea dkey(%ebp),%r6 // key pointer + mov %r3,%r0 + shl $4,%r0 + add %r0,%r6 + +// input four columns and xor in first round key + + mov (%r2),%r0 + mov 4(%r2),%r1 + mov 8(%r2),%r4 + mov 12(%r2),%r5 + xor (%r6),%r0 + xor 4(%r6),%r1 + xor 8(%r6),%r4 + xor 12(%r6),%r5 + + sub $8,%esp // space for register saves on stack + sub $16,%r6 // increment to next round key + sub $10,%r3 + je 4f // 10 rounds for 128-bit key + sub $32,%r6 + sub $2,%r3 + je 3f // 12 rounds for 128-bit key + sub $32,%r6 + +2: inv_rnd( +64(%r6), it_tab) // 14 rounds for 128-bit key + inv_rnd( +48(%r6), it_tab) +3: inv_rnd( +32(%r6), it_tab) // 12 rounds for 128-bit key + inv_rnd( +16(%r6), it_tab) +4: inv_rnd( (%r6), it_tab) // 10 rounds for 128-bit key + inv_rnd( -16(%r6), it_tab) + inv_rnd( -32(%r6), it_tab) + inv_rnd( -48(%r6), it_tab) + inv_rnd( -64(%r6), it_tab) + inv_rnd( -80(%r6), it_tab) + inv_rnd( -96(%r6), it_tab) + inv_rnd(-112(%r6), it_tab) + inv_rnd(-128(%r6), it_tab) + inv_rnd(-144(%r6), il_tab) // last round uses a different table + +// move final values to the output array. CAUTION: the +// order of these assigns rely on the register mappings + + add $8,%esp + mov out_blk+12(%esp),%r6 + mov %r5,12(%r6) + pop %edi + mov %r4,8(%r6) + pop %esi + mov %r1,4(%r6) + pop %ebx + mov %r0,(%r6) + pop %ebp + mov $1,%eax + ret + diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c new file mode 100644 index 000000000000..5a34ee9e4a51 --- /dev/null +++ b/arch/i386/crypto/aes.c @@ -0,0 +1,520 @@ +/* + * + * Glue Code for optimized 586 assembler version of AES + * + * Copyright (c) 2002, Dr Brian Gladman <>, Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and/or fitness for purpose. + * + * Copyright (c) 2003, Adam J. Richter <adam@yggdrasil.com> (conversion to + * 2.5 API). + * Copyright (c) 2003, 2004 Fruhwirth Clemens <clemens@endorphin.org> + * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> + * + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/crypto.h> +#include <linux/linkage.h> + +asmlinkage void aes_enc_blk(const u8 *src, u8 *dst, void *ctx); +asmlinkage void aes_dec_blk(const u8 *src, u8 *dst, void *ctx); + +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 +#define AES_BLOCK_SIZE 16 +#define AES_KS_LENGTH 4 * AES_BLOCK_SIZE +#define RC_LENGTH 29 + +struct aes_ctx { + u32 ekey[AES_KS_LENGTH]; + u32 rounds; + u32 dkey[AES_KS_LENGTH]; +}; + +#define WPOLY 0x011b +#define u32_in(x) le32_to_cpu(*(const u32 *)(x)) +#define bytes2word(b0, b1, b2, b3) \ + (((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0)) + +/* define the finite field multiplies required for Rijndael */ +#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) +#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) +#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) +#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) +#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) +#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) +#define fi(x) ((x) ? pow[255 - log[x]]: 0) + +static inline u32 upr(u32 x, int n) +{ + return (x << 8 * n) | (x >> (32 - 8 * n)); +} + +static inline u8 bval(u32 x, int n) +{ + return x >> 8 * n; +} + +/* The forward and inverse affine transformations used in the S-box */ +#define fwd_affine(x) \ + (w = (u32)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(u8)(w^(w>>8))) + +#define inv_affine(x) \ + (w = (u32)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(u8)(w^(w>>8))) + +static u32 rcon_tab[RC_LENGTH]; + +u32 ft_tab[4][256]; +u32 fl_tab[4][256]; +u32 ls_tab[4][256]; +u32 im_tab[4][256]; +u32 il_tab[4][256]; +u32 it_tab[4][256]; + +void gen_tabs(void) +{ + u32 i, w; + u8 pow[512], log[256]; + + /* + * log and power tables for GF(2^8) finite field with + * WPOLY as modular polynomial - the simplest primitive + * root is 0x03, used here to generate the tables. + */ + i = 0; w = 1; + + do { + pow[i] = (u8)w; + pow[i + 255] = (u8)w; + log[w] = (u8)i++; + w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); + } while (w != 1); + + for(i = 0, w = 1; i < RC_LENGTH; ++i) { + rcon_tab[i] = bytes2word(w, 0, 0, 0); + w = f2(w); + } + + for(i = 0; i < 256; ++i) { + u8 b; + + b = fwd_affine(fi((u8)i)); + w = bytes2word(f2(b), b, b, f3(b)); + + /* tables for a normal encryption round */ + ft_tab[0][i] = w; + ft_tab[1][i] = upr(w, 1); + ft_tab[2][i] = upr(w, 2); + ft_tab[3][i] = upr(w, 3); + w = bytes2word(b, 0, 0, 0); + + /* + * tables for last encryption round + * (may also be used in the key schedule) + */ + fl_tab[0][i] = w; + fl_tab[1][i] = upr(w, 1); + fl_tab[2][i] = upr(w, 2); + fl_tab[3][i] = upr(w, 3); + + /* + * table for key schedule if fl_tab above is + * not of the required form + */ + ls_tab[0][i] = w; + ls_tab[1][i] = upr(w, 1); + ls_tab[2][i] = upr(w, 2); + ls_tab[3][i] = upr(w, 3); + + b = fi(inv_affine((u8)i)); + w = bytes2word(fe(b), f9(b), fd(b), fb(b)); + + /* tables for the inverse mix column operation */ + im_tab[0][b] = w; + im_tab[1][b] = upr(w, 1); + im_tab[2][b] = upr(w, 2); + im_tab[3][b] = upr(w, 3); + + /* tables for a normal decryption round */ + it_tab[0][i] = w; + it_tab[1][i] = upr(w,1); + it_tab[2][i] = upr(w,2); + it_tab[3][i] = upr(w,3); + + w = bytes2word(b, 0, 0, 0); + + /* tables for last decryption round */ + il_tab[0][i] = w; + il_tab[1][i] = upr(w,1); + il_tab[2][i] = upr(w,2); + il_tab[3][i] = upr(w,3); + } +} + +#define four_tables(x,tab,vf,rf,c) \ +( tab[0][bval(vf(x,0,c),rf(0,c))] ^ \ + tab[1][bval(vf(x,1,c),rf(1,c))] ^ \ + tab[2][bval(vf(x,2,c),rf(2,c))] ^ \ + tab[3][bval(vf(x,3,c),rf(3,c))] \ +) + +#define vf1(x,r,c) (x) +#define rf1(r,c) (r) +#define rf2(r,c) ((r-c)&3) + +#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0) +#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c) + +#define ff(x) inv_mcol(x) + +#define ke4(k,i) \ +{ \ + k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; \ + k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; \ + k[4*(i)+7] = ss[3] ^= ss[2]; \ +} + +#define kel4(k,i) \ +{ \ + k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; \ + k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ +} + +#define ke6(k,i) \ +{ \ + k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; \ + k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; \ + k[6*(i)+ 9] = ss[3] ^= ss[2]; \ + k[6*(i)+10] = ss[4] ^= ss[3]; \ + k[6*(i)+11] = ss[5] ^= ss[4]; \ +} + +#define kel6(k,i) \ +{ \ + k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; \ + k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; \ + k[6*(i)+ 9] = ss[3] ^= ss[2]; \ +} + +#define ke8(k,i) \ +{ \ + k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; \ + k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; \ + k[8*(i)+11] = ss[3] ^= ss[2]; \ + k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \ + k[8*(i)+13] = ss[5] ^= ss[4]; \ + k[8*(i)+14] = ss[6] ^= ss[5]; \ + k[8*(i)+15] = ss[7] ^= ss[6]; \ +} + +#define kel8(k,i) \ +{ \ + k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; \ + k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; \ + k[8*(i)+11] = ss[3] ^= ss[2]; \ +} + +#define kdf4(k,i) \ +{ \ + ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ + ss[1] = ss[1] ^ ss[3]; \ + ss[2] = ss[2] ^ ss[3]; \ + ss[3] = ss[3]; \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; \ + ss[i % 4] ^= ss[4]; \ + ss[4] ^= k[4*(i)]; \ + k[4*(i)+4] = ff(ss[4]); \ + ss[4] ^= k[4*(i)+1]; \ + k[4*(i)+5] = ff(ss[4]); \ + ss[4] ^= k[4*(i)+2]; \ + k[4*(i)+6] = ff(ss[4]); \ + ss[4] ^= k[4*(i)+3]; \ + k[4*(i)+7] = ff(ss[4]); \ +} + +#define kd4(k,i) \ +{ \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; \ + ss[i % 4] ^= ss[4]; \ + ss[4] = ff(ss[4]); \ + k[4*(i)+4] = ss[4] ^= k[4*(i)]; \ + k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \ + k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; \ + k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \ +} + +#define kdl4(k,i) \ +{ \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; \ + ss[i % 4] ^= ss[4]; \ + k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ + k[4*(i)+5] = ss[1] ^ ss[3]; \ + k[4*(i)+6] = ss[0]; \ + k[4*(i)+7] = ss[1]; \ +} + +#define kdf6(k,i) \ +{ \ + ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; \ + k[6*(i)+ 6] = ff(ss[0]); \ + ss[1] ^= ss[0]; \ + k[6*(i)+ 7] = ff(ss[1]); \ + ss[2] ^= ss[1]; \ + k[6*(i)+ 8] = ff(ss[2]); \ + ss[3] ^= ss[2]; \ + k[6*(i)+ 9] = ff(ss[3]); \ + ss[4] ^= ss[3]; \ + k[6*(i)+10] = ff(ss[4]); \ + ss[5] ^= ss[4]; \ + k[6*(i)+11] = ff(ss[5]); \ +} + +#define kd6(k,i) \ +{ \ + ss[6] = ls_box(ss[5],3) ^ rcon_tab[i]; \ + ss[0] ^= ss[6]; ss[6] = ff(ss[6]); \ + k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \ + ss[1] ^= ss[0]; \ + k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \ + ss[2] ^= ss[1]; \ + k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \ + ss[3] ^= ss[2]; \ + k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \ + ss[4] ^= ss[3]; \ + k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \ + ss[5] ^= ss[4]; \ + k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \ +} + +#define kdl6(k,i) \ +{ \ + ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; \ + k[6*(i)+ 6] = ss[0]; \ + ss[1] ^= ss[0]; \ + k[6*(i)+ 7] = ss[1]; \ + ss[2] ^= ss[1]; \ + k[6*(i)+ 8] = ss[2]; \ + ss[3] ^= ss[2]; \ + k[6*(i)+ 9] = ss[3]; \ +} + +#define kdf8(k,i) \ +{ \ + ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; \ + k[8*(i)+ 8] = ff(ss[0]); \ + ss[1] ^= ss[0]; \ + k[8*(i)+ 9] = ff(ss[1]); \ + ss[2] ^= ss[1]; \ + k[8*(i)+10] = ff(ss[2]); \ + ss[3] ^= ss[2]; \ + k[8*(i)+11] = ff(ss[3]); \ + ss[4] ^= ls_box(ss[3],0); \ + k[8*(i)+12] = ff(ss[4]); \ + ss[5] ^= ss[4]; \ + k[8*(i)+13] = ff(ss[5]); \ + ss[6] ^= ss[5]; \ + k[8*(i)+14] = ff(ss[6]); \ + ss[7] ^= ss[6]; \ + k[8*(i)+15] = ff(ss[7]); \ +} + +#define kd8(k,i) \ +{ \ + u32 __g = ls_box(ss[7],3) ^ rcon_tab[i]; \ + ss[0] ^= __g; \ + __g = ff(__g); \ + k[8*(i)+ 8] = __g ^= k[8*(i)]; \ + ss[1] ^= ss[0]; \ + k[8*(i)+ 9] = __g ^= k[8*(i)+ 1]; \ + ss[2] ^= ss[1]; \ + k[8*(i)+10] = __g ^= k[8*(i)+ 2]; \ + ss[3] ^= ss[2]; \ + k[8*(i)+11] = __g ^= k[8*(i)+ 3]; \ + __g = ls_box(ss[3],0); \ + ss[4] ^= __g; \ + __g = ff(__g); \ + k[8*(i)+12] = __g ^= k[8*(i)+ 4]; \ + ss[5] ^= ss[4]; \ + k[8*(i)+13] = __g ^= k[8*(i)+ 5]; \ + ss[6] ^= ss[5]; \ + k[8*(i)+14] = __g ^= k[8*(i)+ 6]; \ + ss[7] ^= ss[6]; \ + k[8*(i)+15] = __g ^= k[8*(i)+ 7]; \ +} + +#define kdl8(k,i) \ +{ \ + ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; \ + k[8*(i)+ 8] = ss[0]; \ + ss[1] ^= ss[0]; \ + k[8*(i)+ 9] = ss[1]; \ + ss[2] ^= ss[1]; \ + k[8*(i)+10] = ss[2]; \ + ss[3] ^= ss[2]; \ + k[8*(i)+11] = ss[3]; \ +} + +static int +aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +{ + int i; + u32 ss[8]; + struct aes_ctx *ctx = ctx_arg; + + /* encryption schedule */ + + ctx->ekey[0] = ss[0] = u32_in(in_key); + ctx->ekey[1] = ss[1] = u32_in(in_key + 4); + ctx->ekey[2] = ss[2] = u32_in(in_key + 8); + ctx->ekey[3] = ss[3] = u32_in(in_key + 12); + + switch(key_len) { + case 16: + for (i = 0; i < 9; i++) + ke4(ctx->ekey, i); + kel4(ctx->ekey, 9); + ctx->rounds = 10; + break; + + case 24: + ctx->ekey[4] = ss[4] = u32_in(in_key + 16); + ctx->ekey[5] = ss[5] = u32_in(in_key + 20); + for (i = 0; i < 7; i++) + ke6(ctx->ekey, i); + kel6(ctx->ekey, 7); + ctx->rounds = 12; + break; + + case 32: + ctx->ekey[4] = ss[4] = u32_in(in_key + 16); + ctx->ekey[5] = ss[5] = u32_in(in_key + 20); + ctx->ekey[6] = ss[6] = u32_in(in_key + 24); + ctx->ekey[7] = ss[7] = u32_in(in_key + 28); + for (i = 0; i < 6; i++) + ke8(ctx->ekey, i); + kel8(ctx->ekey, 6); + ctx->rounds = 14; + break; + + default: + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + /* decryption schedule */ + + ctx->dkey[0] = ss[0] = u32_in(in_key); + ctx->dkey[1] = ss[1] = u32_in(in_key + 4); + ctx->dkey[2] = ss[2] = u32_in(in_key + 8); + ctx->dkey[3] = ss[3] = u32_in(in_key + 12); + + switch (key_len) { + case 16: + kdf4(ctx->dkey, 0); + for (i = 1; i < 9; i++) + kd4(ctx->dkey, i); + kdl4(ctx->dkey, 9); + break; + + case 24: + ctx->dkey[4] = ff(ss[4] = u32_in(in_key + 16)); + ctx->dkey[5] = ff(ss[5] = u32_in(in_key + 20)); + kdf6(ctx->dkey, 0); + for (i = 1; i < 7; i++) + kd6(ctx->dkey, i); + kdl6(ctx->dkey, 7); + break; + + case 32: + ctx->dkey[4] = ff(ss[4] = u32_in(in_key + 16)); + ctx->dkey[5] = ff(ss[5] = u32_in(in_key + 20)); + ctx->dkey[6] = ff(ss[6] = u32_in(in_key + 24)); + ctx->dkey[7] = ff(ss[7] = u32_in(in_key + 28)); + kdf8(ctx->dkey, 0); + for (i = 1; i < 6; i++) + kd8(ctx->dkey, i); + kdl8(ctx->dkey, 6); + break; + } + return 0; +} + +static inline void aes_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + aes_enc_blk(src, dst, ctx); +} +static inline void aes_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + aes_dec_blk(src, dst, ctx); +} + + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aes_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt + } + } +}; + +static int __init aes_init(void) +{ + gen_tabs(); + return crypto_register_alg(&aes_alg); +} + +static void __exit aes_fini(void) +{ + crypto_unregister_alg(&aes_alg); +} + +module_init(aes_init); +module_exit(aes_fini); + +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, i586 asm optimized"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Fruhwirth Clemens, James Morris, Brian Gladman, Adam Richter"); +MODULE_ALIAS("aes"); diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c index 4f53d52de5fc..0946844217b9 100644 --- a/arch/i386/kernel/cpu/mtrr/if.c +++ b/arch/i386/kernel/cpu/mtrr/if.c @@ -101,9 +101,6 @@ mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; memset(line, 0, LINE_SIZE); if (len > LINE_SIZE) len = LINE_SIZE; diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 0455e6859dbc..3a6ebc7368b7 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -1512,13 +1512,6 @@ exit_pfm_fs(void) mntput(pfmfs_mnt); } -static loff_t -pfm_lseek(struct file *file, loff_t offset, int whence) -{ - DPRINT(("pfm_lseek called\n")); - return -ESPIPE; -} - static ssize_t pfm_read(struct file *filp, char *buf, size_t size, loff_t *ppos) { @@ -1545,10 +1538,6 @@ pfm_read(struct file *filp, char *buf, size_t size, loff_t *ppos) DPRINT(("message is too small ctx=%p (>=%ld)\n", ctx, sizeof(pfm_msg_t))); return -EINVAL; } - /* - * seeks are not allowed on message queues - */ - if (ppos != &filp->f_pos) return -ESPIPE; PROTECT_CTX(ctx, flags); @@ -2141,7 +2130,7 @@ pfm_no_open(struct inode *irrelevant, struct file *dontcare) static struct file_operations pfm_file_ops = { - .llseek = pfm_lseek, + .llseek = no_llseek, .read = pfm_read, .write = pfm_write, .poll = pfm_poll, diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index a85063a1260b..3ab0b37e0fa9 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -63,6 +63,7 @@ check_pgt_cache (void) low = pgt_cache_water[0]; high = pgt_cache_water[1]; + preempt_disable(); if (pgtable_cache_size > (u64) high) { do { if (pgd_quicklist) @@ -71,6 +72,7 @@ check_pgt_cache (void) free_page((unsigned long)pmd_alloc_one_fast(0, 0)); } while (pgtable_cache_size > (u64) low); } + preempt_enable(); } void diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index bcb3e0c5a3ec..afd36307070a 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -477,6 +477,9 @@ asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, goto out; if (pos < 0) goto out; + ret = -ESPIPE; + if (!(file->f_mode & FMODE_PREAD)) + goto out; ret = read(file, buf, count, &pos); if (ret > 0) dnotify_parent(file->f_dentry, DN_ACCESS); @@ -511,6 +514,10 @@ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, if (pos < 0) goto out; + ret = -ESPIPE; + if (!(file->f_mode & FMODE_PWRITE)) + goto out; + ret = write(file, buf, count, &pos); if (ret > 0) dnotify_parent(file->f_dentry, DN_MODIFY); diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c index dcae0c489933..1c0cc620a43f 100644 --- a/arch/mips/lasat/sysctl.c +++ b/arch/mips/lasat/sysctl.c @@ -60,11 +60,11 @@ int sysctl_lasatstring(ctl_table *table, int *name, int nlen, /* And the same for proc */ int proc_dolasatstring(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp) + void *buffer, size_t *lenp, loff_t *ppos) { int r; down(&lasat_info_sem); - r = proc_dostring(table, write, filp, buffer, lenp); + r = proc_dostring(table, write, filp, buffer, lenp, ppos); if ( (!write) || r) { up(&lasat_info_sem); return r; @@ -76,11 +76,11 @@ int proc_dolasatstring(ctl_table *table, int write, struct file *filp, /* proc function to write EEPROM after changing int entry */ int proc_dolasatint(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp) + void *buffer, size_t *lenp, loff_t *ppos) { int r; down(&lasat_info_sem); - r = proc_dointvec(table, write, filp, buffer, lenp); + r = proc_dointvec(table, write, filp, buffer, lenp, ppos); if ( (!write) || r) { up(&lasat_info_sem); return r; @@ -95,7 +95,7 @@ static int rtctmp; #ifdef CONFIG_DS1603 /* proc function to read/write RealTime Clock */ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp) + void *buffer, size_t *lenp, loff_t *ppos) { int r; down(&lasat_info_sem); @@ -105,7 +105,7 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, if (rtctmp < 0) rtctmp = 0; } - r = proc_dointvec(table, write, filp, buffer, lenp); + r = proc_dointvec(table, write, filp, buffer, lenp, ppos); if ( (!write) || r) { up(&lasat_info_sem); return r; @@ -180,14 +180,14 @@ void update_bcastaddr(void) static char proc_lasat_ipbuf[32]; /* Parsing of IP address */ int proc_lasat_ip(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp) + void *buffer, size_t *lenp, loff_t *ppos) { int len; unsigned int ip; char *p, c; if (!table->data || !table->maxlen || !*lenp || - (filp->f_pos && !write)) { + (*ppos && !write)) { *lenp = 0; return 0; } @@ -213,7 +213,7 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp, return -EFAULT; } proc_lasat_ipbuf[len] = 0; - filp->f_pos += *lenp; + *ppos += *lenp; /* Now see if we can convert it to a valid IP */ ip = in_aton(proc_lasat_ipbuf); *(unsigned int *)(table->data) = ip; @@ -241,7 +241,7 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp, len++; } *lenp = len; - filp->f_pos += len; + *ppos += len; } update_bcastaddr(); up(&lasat_info_sem); @@ -277,11 +277,11 @@ static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen, } int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp) + void *buffer, size_t *lenp, loff_t *ppos) { int r; down(&lasat_info_sem); - r = proc_dointvec(table, write, filp, buffer, lenp); + r = proc_dointvec(table, write, filp, buffer, lenp, ppos); if ( (!write) || r) { up(&lasat_info_sem); return r; diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c index 7a5dd9ca3668..514e7de4055b 100644 --- a/arch/ppc/8xx_io/cs4218_tdm.c +++ b/arch/ppc/8xx_io/cs4218_tdm.c @@ -1619,7 +1619,7 @@ static ssize_t sound_copy_translate_read(const u_char *userPtr, static int mixer_open(struct inode *inode, struct file *file) { mixer.busy = 1; - return 0; + return nonseekable_open(inode, file); } @@ -2105,7 +2105,7 @@ static int sq_open(struct inode *inode, struct file *file) sound_set_format(AFMT_MU_LAW); } - return 0; + return nonseekable_open(inode, file); err_out_nobusy: if (file->f_mode & FMODE_WRITE) { @@ -2404,7 +2404,7 @@ static int state_open(struct inode *inode, struct file *file) len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n", sq.active, sq.syncing); state.len = len; - return 0; + return nonseekable_open(inode, file); } diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 032168b86a49..cc4e6b9db773 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -825,39 +825,6 @@ config PROC_DEVICETREE an image of the device tree that the kernel copies from Open Firmware. If unsure, say Y here. -config PPC_RTAS - bool "Support for RTAS (RunTime Abstraction Services) in /proc" - depends on PPC_OF && PROC_FS - ---help--- - When you use this option, you will be able to use RTAS from - userspace. - - RTAS stands for RunTime Abstraction Services and should - provide a portable way to access and set system information. This is - commonly used on RS/6000 (pSeries) computers. - - You can access RTAS via the special proc file system entry rtas. - Don't confuse this rtas entry with the one in /proc/device-tree/rtas - which is readonly. - - If you don't know if you can use RTAS look into - /proc/device-tree/rtas. If there are some entries, it is very likely - that you will be able to use RTAS. - - You can do cool things with rtas. To print out information about - various sensors in the system, just do a - - $ cat /proc/rtas/sensors - - or if you power off your machine at night but want it running when - you enter your office at 7:45 am, do a - - # date -d 'tomorrow 7:30' +%s > /proc/rtas/poweron - - and shutdown. - - If unsure, say Y. - config PREP_RESIDUAL bool "Support for PReP Residual Data" depends on PPC_PREP diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index bf3d1a2bd558..e15c6919a27f 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -22,28 +22,25 @@ endif LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic CPPFLAGS += -Iarch/$(ARCH) -aflags-y += -Iarch/$(ARCH) -cflags-y += -Iarch/$(ARCH) -msoft-float -pipe \ +AFLAGS += -Iarch/$(ARCH) +CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ -ffixed-r2 -Wno-uninitialized -mmultiple CPP = $(CC) -E $(CFLAGS) CHECK := $(CHECK) -D__powerpc__=1 ifndef CONFIG_E500 -cflags-y += -mstring +CFLAGS += -mstring endif -aflags-$(CONFIG_4xx) += -m405 -cflags-$(CONFIG_4xx) += -Wa,-m405 -aflags-$(CONFIG_6xx) += -maltivec -cflags-$(CONFIG_6xx) += -Wa,-maltivec -aflags-$(CONFIG_E500) += -me500 -cflags-$(CONFIG_E500) += -Wa,-me500 -aflags-$(CONFIG_PPC64BRIDGE) += -mppc64bridge -cflags-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge - -AFLAGS += $(aflags-y) -CFLAGS += $(cflags-y) +cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge +cpu-as-$(CONFIG_4xx) += -Wa,-m405 +cpu-as-$(CONFIG_6xx) += -Wa,-maltivec +cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec +cpu-as-$(CONFIG_E500) += -Wa,-me500 + +AFLAGS += $(cpu-as-y) +CFLAGS += $(cpu-as-y) head-y := arch/ppc/kernel/head.o head-$(CONFIG_8xx) := arch/ppc/kernel/head_8xx.o diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index c3b03b6188fc..2531070a689a 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -2,16 +2,6 @@ # Makefile for the linux kernel. # -ifdef CONFIG_PPC64BRIDGE -EXTRA_AFLAGS := -Wa,-mppc64bridge -endif -ifdef CONFIG_4xx -EXTRA_AFLAGS := -Wa,-m405 -endif -ifdef CONFIG_E500 -EXTRA_AFLAGS := -Wa,-me500 -endif - extra-$(CONFIG_PPC_STD_MMU) := head.o extra-$(CONFIG_40x) := head_4xx.o extra-$(CONFIG_44x) := head_44x.o diff --git a/arch/ppc/kernel/pci-dma.c b/arch/ppc/kernel/pci-dma.c deleted file mode 100644 index 63354f6af1b0..000000000000 --- a/arch/ppc/kernel/pci-dma.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com> - * - * - * Dynamic DMA mapping support. - * - * swiped from i386 - * - */ - -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/string.h> -#include <linux/pci.h> -#include <asm/io.h> - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - - if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) - gfp |= GFP_DMA; - -#ifdef CONFIG_NOT_COHERENT_CACHE - ret = consistent_alloc(gfp, size, dma_handle); -#else - ret = (void *)__get_free_pages(gfp, get_order(size)); -#endif - - if (ret != NULL) { - memset(ret, 0, size); -#ifndef CONFIG_NOT_COHERENT_CACHE - *dma_handle = virt_to_bus(ret); -#endif - } - return ret; -} - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ -#ifdef CONFIG_NOT_COHERENT_CACHE - consistent_free(vaddr); -#else - free_pages((unsigned long)vaddr, get_order(size)); -#endif -} diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index 29ff57bbab54..91592c03ea8b 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -35,7 +35,7 @@ static int ppc_htab_show(struct seq_file *m, void *v); static ssize_t ppc_htab_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos); int proc_dol2crvec(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp); + void __user *buffer, size_t *lenp, loff_t *ppos); extern PTE *Hash, *Hash_end; extern unsigned long Hash_size, Hash_mask; @@ -320,7 +320,7 @@ static ssize_t ppc_htab_write(struct file * file, const char __user * ubuffer, } int proc_dol2crvec(ctl_table *table, int write, struct file *filp, - void __user *buffer_arg, size_t *lenp) + void __user *buffer_arg, size_t *lenp, loff_t *ppos) { int vleft, first=1, len, left, val; char __user *buffer = (char __user *) buffer_arg; @@ -344,7 +344,7 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp, if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)) return -EFAULT; - if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) { + if ( /*!table->maxlen ||*/ (*ppos && !write)) { *lenp = 0; return 0; } @@ -435,6 +435,6 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp, if (write && first) return -EINVAL; *lenp -= left; - filp->f_pos += *lenp; + *ppos += *lenp; return 0; } diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c index b970dd51dd95..1d79838d90ac 100644 --- a/arch/ppc/mm/44x_mmu.c +++ b/arch/ppc/mm/44x_mmu.c @@ -93,10 +93,14 @@ ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys) } /* - * Configure PPC44x TLB for AS0 exception processing. + * MMU_init_hw does the chip-specific initialization of the MMU hardware. */ -static void __init -ppc44x_tlb_config(void) +void __init MMU_init_hw(void) +{ + flush_instruction_cache(); +} + +unsigned long __init mmu_mapin_ram(void) { unsigned int pinned_tlbs = 1; int i; @@ -124,39 +128,6 @@ ppc44x_tlb_config(void) unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE; ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr); } -} - -/* - * MMU_init_hw does the chip-specific initialization of the MMU hardware. - */ -void __init MMU_init_hw(void) -{ - flush_instruction_cache(); - - ppc44x_tlb_config(); -} - -/* TODO: Add large page lowmem mapping support */ -unsigned long __init mmu_mapin_ram(void) -{ - unsigned long v, s, f = _PAGE_GUARDED; - phys_addr_t p; - - v = KERNELBASE; - p = PPC_MEMSTART; - - for (s = 0; s < total_lowmem; s += PAGE_SIZE) { - if ((char *) v >= _stext && (char *) v < etext) - f |= _PAGE_RAM_TEXT; - else - f |= _PAGE_RAM; - map_page(v, p, f); - v += PAGE_SIZE; - p += PAGE_SIZE; - } - - if (ppc_md.progress) - ppc_md.progress("MMU:mmu_mapin_ram done", 0x401); - return s; + return total_lowmem; } diff --git a/arch/ppc/mm/Makefile b/arch/ppc/mm/Makefile index 458e67106c6a..cd3eae147cf8 100644 --- a/arch/ppc/mm/Makefile +++ b/arch/ppc/mm/Makefile @@ -2,10 +2,6 @@ # Makefile for the linux ppc-specific parts of the memory manager. # -ifdef CONFIG_PPC64BRIDGE -EXTRA_AFLAGS := -Wa,-mppc64bridge -endif - obj-y := fault.o init.o mem_pieces.o \ mmu_context.o pgtable.o diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index b439b155c7c5..578b0ac9cc04 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -175,6 +175,15 @@ config IBM_OPENBIOS depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y +config PPC4xx_DMA + bool "PPC4xx DMA controller support" + depends on 4xx + +config PPC4xx_EDMA + bool + depends on !STB03xxx && PPC4xx_DMA + default y + config PM bool "Power Management support (EXPERIMENTAL)" depends on 4xx && EXPERIMENTAL diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index 749fff956fe6..c4352e6bb71a 100755 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -64,7 +64,8 @@ #define UART0_IO_BASE (u8 *) 0xE0000200 #define UART1_IO_BASE (u8 *) 0xE0000300 -#define BASE_BAUD 33000000/3/16 +/* external Epson SG-615P */ +#define BASE_BAUD 691200 #define STD_UART_OP(num) \ { 0, BASE_BAUD, 0, UART##num##_INT, \ diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile index 334015b3cf28..c59d4871d950 100644 --- a/arch/ppc/platforms/Makefile +++ b/arch/ppc/platforms/Makefile @@ -2,13 +2,6 @@ # Makefile for the linux kernel. # -ifdef CONFIG_PPC64BRIDGE -EXTRA_AFLAGS := -Wa,-mppc64bridge -endif -ifdef CONFIG_40x -EXTRA_AFLAGS := -Wa,-m405 -endif - # Extra CFLAGS so we don't have to do relative includes CFLAGS_pmac_setup.o += -Iarch/$(ARCH)/mm @@ -26,7 +19,6 @@ obj-$(CONFIG_NVRAM) += pmac_nvram.o obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o endif obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o -obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o obj-$(CONFIG_EST8260) += est8260_setup.o diff --git a/arch/ppc/platforms/error_log.c b/arch/ppc/platforms/error_log.c deleted file mode 100644 index 4a71e1885fd2..000000000000 --- a/arch/ppc/platforms/error_log.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * arch/ppc/kernel/error_log.c - * - * Copyright (c) 2000 Tilmann Bitterberg - * (tilmann@bitterberg.de) - * - * Error processing of errors found by rtas even-scan routine - * which is done with every heartbeat. (chrp_setup.c) - */ - -#include <linux/sched.h> - -#include <asm/prom.h> - -#include "error_log.h" - -/* ****************************************************************** */ -/* - * EVENT-SCAN - * The whole stuff below here doesn't take any action when it found - * an error, it just prints as much information as possible and - * then its up to the user to decide what to do. - * - * Returns 0 if no errors were found - * Returns 1 if there may be more errors - */ -int ppc_rtas_errorlog_scan(void) -{ -const char *_errlog_severity[] = { -#ifdef VERBOSE_ERRORS - "No Error\n\t\ -Should require no further information", - "Event\n\t\ -This is not really an error, it is an event. I use events\n\t\ -to communicate with RTAS back and forth.", - "Warning\n\t\ -Indicates a non-state-losing error, either fully recovered\n\t\ -by RTAS or not needing recovery. Ignore it.", - "Error sync\n\t\ -May only be fatal to a certain program or thread. Recovery\n\t\ -and continuation is possible, if I only had a handler for\n\t\ -this. Less serious", - "Error\n\t\ -Less serious, but still causing a loss of data and state.\n\t\ -I can't tell you exactly what to do, You have to decide\n\t\ -with help from the target and initiator field, what kind\n\t\ -of further actions may take place.", - "Fatal\n\t\ -Represent a permanent hardware failure and I believe this\n\t\ -affects my overall performance and behaviour. I would not\n\t\ -attempt to continue normal operation." -#else - "No Error", - "Event", - "Warning", - "Error sync", - "Error", - "Fatal" -#endif /* VERBOSE_ERRORS */ -}; - -#if 0 /* unused?? */ -const char *_errlog_disposition[] = { -#ifdef VERBOSE_ERRORS - "Fully recovered\n\t\ -There was an error, but it is fully recovered by RTAS.", - "Limited recovery\n\t\ -RTAS was able to recover the state of the machine, but some\n\t\ -feature of the machine has been disabled or lost (for example\n\t\ -error checking) or performance may suffer.", - "Not recovered\n\t\ -Whether RTAS did not try to recover anything or recovery failed:\n\t\ -HOUSTON, WE HAVE A PROBLEM!" -#else - "Fully recovered", - "Limited recovery", - "Not recovered" -#endif /* VERBOSE_ERRORS */ -}; -#endif - -const char *_errlog_extended[] = { -#ifdef VERBOSE_ERRORS - "Not present\n\t\ -Sad, the RTAS call didn't return an extended error log.", - "Present\n\t\ -The extended log is present and hopefully it contains a lot of\n\t\ -useful information, which leads to the solution of the problem." -#else - "Not present", - "Present" -#endif /* VERBOSE_ERRORS */ -}; - -const char *_errlog_initiator[] = { - "Unknown or not applicable", - "CPU", - "PCI", - "ISA", - "Memory", - "Power management" -}; - -const char *_errlog_target[] = { - "Unknown or not applicable", - "CPU", - "PCI", - "ISA", - "Memory", - "Power management" -}; - rtas_error_log error_log; - char logdata[1024]; - int error; -#if 0 /* unused?? */ - int retries = 0; /* if HW error, try 10 times */ -#endif - - error = call_rtas ("event-scan", 4, 1, (unsigned long *)&error_log, - INTERNAL_ERROR | EPOW_WARNING, - 0, __pa(logdata), 1024); - - if (error == 1) /* no errors found */ - return 0; - - if (error == -1) { - printk(KERN_ERR "Unable to get errors. Do you a favor and throw this box away\n"); - return 0; - } - if (error_log.version != 1) - printk(KERN_WARNING "Unknown version (%d), please implement me\n", - error_log.version); - - switch (error_log.disposition) { - case DISP_FULLY_RECOVERED: - /* there was an error, but everything is fine now */ - return 0; - case DISP_NOT_RECOVERED: - printk("We have a really serious Problem!\n"); - case DISP_LIMITED_RECOVERY: - printk("Error classification\n"); - printk("Severity : %s\n", - ppc_rtas_errorlog_check_severity (error_log)); - printk("Initiator : %s\n", - ppc_rtas_errorlog_check_initiator (error_log)); - printk("Target : %s\n", - ppc_rtas_errorlog_check_target (error_log)); - printk("Type : %s\n", - ppc_rtas_errorlog_check_type (error_log)); - printk("Ext. log : %s\n", - ppc_rtas_errorlog_check_extended (error_log)); - if (error_log.extended) - ppc_rtas_errorlog_disect_extended (logdata); - return 1; - default: - /* nothing */ - break; - } - return 0; -} -/* ****************************************************************** */ -const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log) -{ - const char *_errlog_type[] = { - "unknown type", - "too many tries failed", - "TCE error", - "RTAS device failed", - "target timed out", - "parity error on data", /* 5 */ - "parity error on address", - "parity error on external cache", - "access to invalid address", - "uncorrectable ECC error", - "corrected ECC error" /* 10 */ - }; - if (error_log.type == TYPE_EPOW) - return "EPOW"; - if (error_log.type >= TYPE_PMGM_POWER_SW_ON) - return "PowerMGM Event (not handled right now)"; - return _errlog_type[error_log.type]; -} - diff --git a/arch/ppc/platforms/error_log.h b/arch/ppc/platforms/error_log.h deleted file mode 100644 index b8226aef3d4a..000000000000 --- a/arch/ppc/platforms/error_log.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef __ERROR_LOG_H__ -#define __ERROR_LOG_H__ - -#define VERBOSE_ERRORS 1 /* Maybe I enlarge the kernel too much */ -#undef VERBOSE_ERRORS - -/* Event classes */ -/* XXX: Endianess correct? NOW*/ -#define INTERNAL_ERROR 0x80000000 /* set bit 0 */ -#define EPOW_WARNING 0x40000000 /* set bit 1 */ -#define POWERMGM_EVENTS 0x20000000 /* set bit 2 */ - -/* event-scan returns */ -#define SEVERITY_FATAL 0x5 -#define SEVERITY_ERROR 0x4 -#define SEVERITY_ERROR_SYNC 0x3 -#define SEVERITY_WARNING 0x2 -#define SEVERITY_EVENT 0x1 -#define SEVERITY_NO_ERROR 0x0 -#define DISP_FULLY_RECOVERED 0x0 -#define DISP_LIMITED_RECOVERY 0x1 -#define DISP_NOT_RECOVERED 0x2 -#define PART_PRESENT 0x0 -#define PART_NOT_PRESENT 0x1 -#define INITIATOR_UNKNOWN 0x0 -#define INITIATOR_CPU 0x1 -#define INITIATOR_PCI 0x2 -#define INITIATOR_ISA 0x3 -#define INITIATOR_MEMORY 0x4 -#define INITIATOR_POWERMGM 0x5 -#define TARGET_UNKNOWN 0x0 -#define TARGET_CPU 0x1 -#define TARGET_PCI 0x2 -#define TARGET_ISA 0x3 -#define TARGET_MEMORY 0x4 -#define TARGET_POWERMGM 0x5 -#define TYPE_RETRY 0x01 -#define TYPE_TCE_ERR 0x02 -#define TYPE_INTERN_DEV_FAIL 0x03 -#define TYPE_TIMEOUT 0x04 -#define TYPE_DATA_PARITY 0x05 -#define TYPE_ADDR_PARITY 0x06 -#define TYPE_CACHE_PARITY 0x07 -#define TYPE_ADDR_INVALID 0x08 -#define TYPE_ECC_UNCORR 0x09 -#define TYPE_ECC_CORR 0x0a -#define TYPE_EPOW 0x40 -/* I don't add PowerMGM events right now, this is a different topic */ -#define TYPE_PMGM_POWER_SW_ON 0x60 -#define TYPE_PMGM_POWER_SW_OFF 0x61 -#define TYPE_PMGM_LID_OPEN 0x62 -#define TYPE_PMGM_LID_CLOSE 0x63 -#define TYPE_PMGM_SLEEP_BTN 0x64 -#define TYPE_PMGM_WAKE_BTN 0x65 -#define TYPE_PMGM_BATTERY_WARN 0x66 -#define TYPE_PMGM_BATTERY_CRIT 0x67 -#define TYPE_PMGM_SWITCH_TO_BAT 0x68 -#define TYPE_PMGM_SWITCH_TO_AC 0x69 -#define TYPE_PMGM_KBD_OR_MOUSE 0x6a -#define TYPE_PMGM_ENCLOS_OPEN 0x6b -#define TYPE_PMGM_ENCLOS_CLOSED 0x6c -#define TYPE_PMGM_RING_INDICATE 0x6d -#define TYPE_PMGM_LAN_ATTENTION 0x6e -#define TYPE_PMGM_TIME_ALARM 0x6f -#define TYPE_PMGM_CONFIG_CHANGE 0x70 -#define TYPE_PMGM_SERVICE_PROC 0x71 - -typedef struct _rtas_error_log { - unsigned long version:8; /* Architectural version */ - unsigned long severity:3; /* Severity level of error */ - unsigned long disposition:2; /* Degree of recovery */ - unsigned long extended:1; /* extended log present? */ - unsigned long /* reserved */ :2; /* Reserved for future use */ - unsigned long initiator:4; /* Initiator of event */ - unsigned long target:4; /* Target of failed operation */ - unsigned long type:8; /* General event or error*/ - unsigned long extended_log_length:32; /* length in bytes */ -} rtas_error_log; - -/* ****************************************************************** */ -#define ppc_rtas_errorlog_check_severity(x) \ - (_errlog_severity[x.severity]) -#define ppc_rtas_errorlog_check_target(x) \ - (_errlog_target[x.target]) -#define ppc_rtas_errorlog_check_initiator(x) \ - (_errlog_initiator[x.initiator]) -#define ppc_rtas_errorlog_check_extended(x) \ - (_errlog_extended[x.extended]) -#define ppc_rtas_errorlog_disect_extended(x) \ - do { /* implement me */ } while(0) -extern const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log); -extern int ppc_rtas_errorlog_scan(void); - - -#endif /* __ERROR_LOG_H__ */ diff --git a/arch/ppc/platforms/proc_rtas.c b/arch/ppc/platforms/proc_rtas.c deleted file mode 100644 index f24f39923916..000000000000 --- a/arch/ppc/platforms/proc_rtas.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * arch/ppc/platforms/proc_rtas.c - * Copyright (C) 2000 Tilmann Bitterberg - * (tilmann@bitterberg.de) - * - * RTAS (Runtime Abstraction Services) stuff - * Intention is to provide a clean user interface - * to use the RTAS. - * - * TODO: - * Split off a header file and maybe move it to a different - * location. Write Documentation on what the /proc/rtas/ entries - * actually do. - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> -#include <linux/ctype.h> -#include <linux/time.h> -#include <linux/string.h> -#include <linux/init.h> - -#include <asm/uaccess.h> -#include <asm/bitops.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <asm/prom.h> -#include <asm/machdep.h> /* for ppc_md */ -#include <asm/time.h> - -/* Token for Sensors */ -#define KEY_SWITCH 0x0001 -#define ENCLOSURE_SWITCH 0x0002 -#define THERMAL_SENSOR 0x0003 -#define LID_STATUS 0x0004 -#define POWER_SOURCE 0x0005 -#define BATTERY_VOLTAGE 0x0006 -#define BATTERY_REMAINING 0x0007 -#define BATTERY_PERCENTAGE 0x0008 -#define EPOW_SENSOR 0x0009 -#define BATTERY_CYCLESTATE 0x000a -#define BATTERY_CHARGING 0x000b - -/* IBM specific sensors */ -#define IBM_SURVEILLANCE 0x2328 /* 9000 */ -#define IBM_FANRPM 0x2329 /* 9001 */ -#define IBM_VOLTAGE 0x232a /* 9002 */ -#define IBM_DRCONNECTOR 0x232b /* 9003 */ -#define IBM_POWERSUPPLY 0x232c /* 9004 */ -#define IBM_INTQUEUE 0x232d /* 9005 */ - -/* Status return values */ -#define SENSOR_CRITICAL_HIGH 13 -#define SENSOR_WARNING_HIGH 12 -#define SENSOR_NORMAL 11 -#define SENSOR_WARNING_LOW 10 -#define SENSOR_CRITICAL_LOW 9 -#define SENSOR_SUCCESS 0 -#define SENSOR_HW_ERROR -1 -#define SENSOR_BUSY -2 -#define SENSOR_NOT_EXIST -3 -#define SENSOR_DR_ENTITY -9000 - -/* Location Codes */ -#define LOC_SCSI_DEV_ADDR 'A' -#define LOC_SCSI_DEV_LOC 'B' -#define LOC_CPU 'C' -#define LOC_DISKETTE 'D' -#define LOC_ETHERNET 'E' -#define LOC_FAN 'F' -#define LOC_GRAPHICS 'G' -/* reserved / not used 'H' */ -#define LOC_IO_ADAPTER 'I' -/* reserved / not used 'J' */ -#define LOC_KEYBOARD 'K' -#define LOC_LCD 'L' -#define LOC_MEMORY 'M' -#define LOC_NV_MEMORY 'N' -#define LOC_MOUSE 'O' -#define LOC_PLANAR 'P' -#define LOC_OTHER_IO 'Q' -#define LOC_PARALLEL 'R' -#define LOC_SERIAL 'S' -#define LOC_DEAD_RING 'T' -#define LOC_RACKMOUNTED 'U' /* for _u_nit is rack mounted */ -#define LOC_VOLTAGE 'V' -#define LOC_SWITCH_ADAPTER 'W' -#define LOC_OTHER 'X' -#define LOC_FIRMWARE 'Y' -#define LOC_SCSI 'Z' - -/* Tokens for indicators */ -#define TONE_FREQUENCY 0x0001 /* 0 - 1000 (HZ)*/ -#define TONE_VOLUME 0x0002 /* 0 - 100 (%) */ -#define SYSTEM_POWER_STATE 0x0003 -#define WARNING_LIGHT 0x0004 -#define DISK_ACTIVITY_LIGHT 0x0005 -#define HEX_DISPLAY_UNIT 0x0006 -#define BATTERY_WARNING_TIME 0x0007 -#define CONDITION_CYCLE_REQUEST 0x0008 -#define SURVEILLANCE_INDICATOR 0x2328 /* 9000 */ -#define DR_ACTION 0x2329 /* 9001 */ -#define DR_INDICATOR 0x232a /* 9002 */ -/* 9003 - 9004: Vendor specific */ -#define GLOBAL_INTERRUPT_QUEUE 0x232d /* 9005 */ -/* 9006 - 9999: Vendor specific */ - -/* other */ -#define MAX_SENSORS 17 /* I only know of 17 sensors */ -#define MAX_LINELENGTH 256 -#define SENSOR_PREFIX "ibm,sensor-" -#define cel_to_fahr(x) ((x*9/5)+32) - - -/* Globals */ -static struct proc_dir_entry *proc_rtas; -static struct rtas_sensors sensors; -static struct device_node *rtas; -static unsigned long power_on_time = 0; /* Save the time the user set */ -static char progress_led[MAX_LINELENGTH]; - -static unsigned long rtas_tone_frequency = 1000; -static unsigned long rtas_tone_volume = 0; - -/* ****************STRUCTS******************************************* */ -struct individual_sensor { - unsigned int token; - unsigned int quant; -}; - -struct rtas_sensors { - struct individual_sensor sensor[MAX_SENSORS]; - unsigned int quant; -}; - -/* ****************************************************************** */ -/* Declarations */ -static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off, - int count, int *eof, void *data); -static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_progress_read(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); - -static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf, - size_t count, loff_t *ppos); - -struct file_operations ppc_rtas_poweron_operations = { - .read = ppc_rtas_poweron_read, - .write = ppc_rtas_poweron_write -}; -struct file_operations ppc_rtas_progress_operations = { - .read = ppc_rtas_progress_read, - .write = ppc_rtas_progress_write -}; - -struct file_operations ppc_rtas_clock_operations = { - .read = ppc_rtas_clock_read, - .write = ppc_rtas_clock_write -}; - -struct file_operations ppc_rtas_tone_freq_operations = { - .read = ppc_rtas_tone_freq_read, - .write = ppc_rtas_tone_freq_write -}; -struct file_operations ppc_rtas_tone_volume_operations = { - .read = ppc_rtas_tone_volume_read, - .write = ppc_rtas_tone_volume_write -}; - -int ppc_rtas_find_all_sensors (void); -int ppc_rtas_process_sensor(struct individual_sensor s, int state, - int error, char * buf); -char * ppc_rtas_process_error(int error); -int get_location_code(struct individual_sensor s, char * buf); -int check_location_string (char *c, char * buf); -int check_location (char *c, int idx, char * buf); - -/* ****************************************************************** */ -/* MAIN */ -/* ****************************************************************** */ -static int __init proc_rtas_init(void) -{ - struct proc_dir_entry *entry; - - rtas = find_devices("rtas"); - if ((rtas == 0) || (_machine != _MACH_chrp)) { - return 1; - } - - proc_rtas = proc_mkdir("rtas", 0); - if (proc_rtas == 0) - return 1; - - /* /proc/rtas entries */ - - entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_progress_operations; - - entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_clock_operations; - - entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_poweron_operations; - - create_proc_read_entry("sensors", S_IRUGO, proc_rtas, - ppc_rtas_sensor_read, NULL); - - entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations; - - entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas); - if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations; - - return 0; -} -__initcall(proc_rtas_init); - -/* ****************************************************************** */ -/* POWER-ON-TIME */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - struct rtc_time tm; - unsigned long nowtime; - char *dest; - int error; - - nowtime = simple_strtoul(buf, &dest, 10); - if (*dest != '\0' && *dest != '\n') { - printk("ppc_rtas_poweron_write: Invalid time\n"); - return count; - } - power_on_time = nowtime; /* save the time */ - - to_tm(nowtime, &tm); - - error = call_rtas("set-time-for-power-on", 7, 1, NULL, - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */); - if (error != 0) - printk(KERN_WARNING "error: setting poweron time returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - int n; - if (power_on_time == 0) - n = sprintf(buf, "Power on time not set\n"); - else - n = sprintf(buf, "%lu\n", power_on_time); - - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} - -/* ****************************************************************** */ -/* PROGRESS */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - unsigned long hex; - - strcpy(progress_led, buf); /* save the string */ - /* Lets see if the user passed hexdigits */ - hex = simple_strtoul(buf, NULL, 10); - - ppc_md.progress ((char *)buf, hex); - return count; - - /* clear the line */ /* ppc_md.progress(" ", 0xffff);*/ -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_progress_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - int n = 0; - if (progress_led != NULL) - n = sprintf (buf, "%s\n", progress_led); - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} - -/* ****************************************************************** */ -/* CLOCK */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - struct rtc_time tm; - unsigned long nowtime; - char *dest; - int error; - - nowtime = simple_strtoul(buf, &dest, 10); - if (*dest != '\0' && *dest != '\n') { - printk("ppc_rtas_clock_write: Invalid time\n"); - return count; - } - - to_tm(nowtime, &tm); - error = call_rtas("set-time-of-day", 7, 1, NULL, - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, 0); - if (error != 0) - printk(KERN_WARNING "error: setting the clock returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - unsigned int year, mon, day, hour, min, sec; - unsigned long *ret = kmalloc(4*8, GFP_KERNEL); - int n, error; - - error = call_rtas("get-time-of-day", 0, 8, ret); - - year = ret[0]; mon = ret[1]; day = ret[2]; - hour = ret[3]; min = ret[4]; sec = ret[5]; - - if (error != 0){ - printk(KERN_WARNING "error: reading the clock returned: %s\n", - ppc_rtas_process_error(error)); - n = sprintf (buf, "0"); - } else { - n = sprintf (buf, "%lu\n", mktime(year, mon, day, hour, min, sec)); - } - kfree(ret); - - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} - -/* ****************************************************************** */ -/* SENSOR STUFF */ -/* ****************************************************************** */ -static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off, - int count, int *eof, void *data) -{ - int i,j,n; - unsigned long ret; - int state, error; - char buffer[MAX_LINELENGTH*MAX_SENSORS]; /* May not be enough */ - - if (count < 0) - return -EINVAL; - - n = sprintf ( buffer , "RTAS (RunTime Abstraction Services) Sensor Information\n"); - n += sprintf ( buffer+n, "Sensor\t\tValue\t\tCondition\tLocation\n"); - n += sprintf ( buffer+n, "********************************************************\n"); - - if (ppc_rtas_find_all_sensors() != 0) { - n += sprintf ( buffer+n, "\nNo sensors are available\n"); - goto return_string; - } - - for (i=0; i<sensors.quant; i++) { - j = sensors.sensor[i].quant; - /* A sensor may have multiple instances */ - while (j >= 0) { - error = call_rtas("get-sensor-state", 2, 2, &ret, - sensors.sensor[i].token, sensors.sensor[i].quant-j); - state = (int) ret; - n += ppc_rtas_process_sensor(sensors.sensor[i], state, error, buffer+n ); - n += sprintf (buffer+n, "\n"); - j--; - } /* while */ - } /* for */ - -return_string: - if (off >= strlen(buffer)) { - *eof = 1; - return 0; - } - if (n > strlen(buffer) - off) - n = strlen(buffer) - off; - if (n > count) - n = count; - else - *eof = 1; - memcpy(buf, buffer + off, n); - *start = buf; - return n; -} - -/* ****************************************************************** */ - -int ppc_rtas_find_all_sensors (void) -{ - unsigned long *utmp; - int len, i, j; - - utmp = (unsigned long *) get_property(rtas, "rtas-sensors", &len); - if (utmp == NULL) { - printk (KERN_ERR "error: could not get rtas-sensors\n"); - return 1; - } - - sensors.quant = len / 8; /* int + int */ - - for (i=0, j=0; j<sensors.quant; i+=2, j++) { - sensors.sensor[j].token = utmp[i]; - sensors.sensor[j].quant = utmp[i+1]; - } - return 0; -} - -/* ****************************************************************** */ -/* - * Builds a string of what rtas returned - */ -char * ppc_rtas_process_error(int error) -{ - switch (error) { - case SENSOR_CRITICAL_HIGH: - return "(critical high)"; - case SENSOR_WARNING_HIGH: - return "(warning high)"; - case SENSOR_NORMAL: - return "(normal)"; - case SENSOR_WARNING_LOW: - return "(warning low)"; - case SENSOR_CRITICAL_LOW: - return "(critical low)"; - case SENSOR_SUCCESS: - return "(read ok)"; - case SENSOR_HW_ERROR: - return "(hardware error)"; - case SENSOR_BUSY: - return "(busy)"; - case SENSOR_NOT_EXIST: - return "(non existant)"; - case SENSOR_DR_ENTITY: - return "(dr entity removed)"; - default: - return "(UNKNOWN)"; - } -} - -/* ****************************************************************** */ -/* - * Builds a string out of what the sensor said - */ - -int ppc_rtas_process_sensor(struct individual_sensor s, int state, - int error, char * buf) -{ - /* Defined return vales */ - const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", "Mainenance" }; - const char * enclosure_switch[] = { "Closed", "Open" }; - const char * lid_status[] = { " ", "Open", "Closed" }; - const char * power_source[] = { "AC\t", "Battery", "AC & Battery" }; - const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" }; - const char * epow_sensor[] = { - "EPOW Reset", "Cooling warning", "Power warning", - "System shutdown", "System halt", "EPOW main enclosure", - "EPOW power off" }; - const char * battery_cyclestate[] = { "None", "In progress", "Requested" }; - const char * battery_charging[] = { "Charging", "Discharching", "No current flow" }; - const char * ibm_drconnector[] = { "Empty", "Present" }; - const char * ibm_intqueue[] = { "Disabled", "Enabled" }; - - int have_strings = 0; - int temperature = 0; - int unknown = 0; - int n = 0; - - /* What kind of sensor do we have here? */ - switch (s.token) { - case KEY_SWITCH: - n += sprintf(buf+n, "Key switch:\t"); - n += sprintf(buf+n, "%s\t", key_switch[state]); - have_strings = 1; - break; - case ENCLOSURE_SWITCH: - n += sprintf(buf+n, "Enclosure switch:\t"); - n += sprintf(buf+n, "%s\t", enclosure_switch[state]); - have_strings = 1; - break; - case THERMAL_SENSOR: - n += sprintf(buf+n, "Temp. (°C/°F):\t"); - temperature = 1; - break; - case LID_STATUS: - n += sprintf(buf+n, "Lid status:\t"); - n += sprintf(buf+n, "%s\t", lid_status[state]); - have_strings = 1; - break; - case POWER_SOURCE: - n += sprintf(buf+n, "Power source:\t"); - n += sprintf(buf+n, "%s\t", power_source[state]); - have_strings = 1; - break; - case BATTERY_VOLTAGE: - n += sprintf(buf+n, "Battery voltage:\t"); - break; - case BATTERY_REMAINING: - n += sprintf(buf+n, "Battery remaining:\t"); - n += sprintf(buf+n, "%s\t", battery_remaining[state]); - have_strings = 1; - break; - case BATTERY_PERCENTAGE: - n += sprintf(buf+n, "Battery percentage:\t"); - break; - case EPOW_SENSOR: - n += sprintf(buf+n, "EPOW Sensor:\t"); - n += sprintf(buf+n, "%s\t", epow_sensor[state]); - have_strings = 1; - break; - case BATTERY_CYCLESTATE: - n += sprintf(buf+n, "Battery cyclestate:\t"); - n += sprintf(buf+n, "%s\t", battery_cyclestate[state]); - have_strings = 1; - break; - case BATTERY_CHARGING: - n += sprintf(buf+n, "Battery Charging:\t"); - n += sprintf(buf+n, "%s\t", battery_charging[state]); - have_strings = 1; - break; - case IBM_SURVEILLANCE: - n += sprintf(buf+n, "Surveillance:\t"); - break; - case IBM_FANRPM: - n += sprintf(buf+n, "Fan (rpm):\t"); - break; - case IBM_VOLTAGE: - n += sprintf(buf+n, "Voltage (mv):\t"); - break; - case IBM_DRCONNECTOR: - n += sprintf(buf+n, "DR connector:\t"); - n += sprintf(buf+n, "%s\t", ibm_drconnector[state]); - have_strings = 1; - break; - case IBM_POWERSUPPLY: - n += sprintf(buf+n, "Powersupply:\t"); - break; - case IBM_INTQUEUE: - n += sprintf(buf+n, "Interrupt queue:\t"); - n += sprintf(buf+n, "%s\t", ibm_intqueue[state]); - have_strings = 1; - break; - default: - n += sprintf(buf+n, "Unkown sensor (type %d), ignoring it\n", - s.token); - unknown = 1; - have_strings = 1; - break; - } - if (have_strings == 0) { - if (temperature) { - n += sprintf(buf+n, "%4d /%4d\t", state, cel_to_fahr(state)); - } else - n += sprintf(buf+n, "%10d\t", state); - } - if (unknown == 0) { - n += sprintf ( buf+n, "%s\t", ppc_rtas_process_error(error)); - n += get_location_code(s, buf+n); - } - return n; -} - -/* ****************************************************************** */ - -int check_location (char *c, int idx, char * buf) -{ - int n = 0; - - switch (*(c+idx)) { - case LOC_PLANAR: - n += sprintf ( buf, "Planar #%c", *(c+idx+1)); - break; - case LOC_CPU: - n += sprintf ( buf, "CPU #%c", *(c+idx+1)); - break; - case LOC_FAN: - n += sprintf ( buf, "Fan #%c", *(c+idx+1)); - break; - case LOC_RACKMOUNTED: - n += sprintf ( buf, "Rack #%c", *(c+idx+1)); - break; - case LOC_VOLTAGE: - n += sprintf ( buf, "Voltage #%c", *(c+idx+1)); - break; - case LOC_LCD: - n += sprintf ( buf, "LCD #%c", *(c+idx+1)); - break; - case '.': - n += sprintf ( buf, "- %c", *(c+idx+1)); - default: - n += sprintf ( buf, "Unknown location"); - break; - } - return n; -} - - -/* ****************************************************************** */ -/* - * Format: - * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ] - * the '.' may be an abbrevation - */ -int check_location_string (char *c, char *buf) -{ - int n=0,i=0; - - while (c[i]) { - if (isalpha(c[i]) || c[i] == '.') { - n += check_location(c, i, buf+n); - } - else if (c[i] == '/' || c[i] == '-') - n += sprintf(buf+n, " at "); - i++; - } - return n; -} - - -/* ****************************************************************** */ - -int get_location_code(struct individual_sensor s, char * buffer) -{ - char rstr[512], tmp[10], tmp2[10]; - int n=0, i=0, llen, len; - /* char *buf = kmalloc(MAX_LINELENGTH, GFP_KERNEL); */ - char *ret; - - static int pos = 0; /* remember position where buffer was */ - - /* construct the sensor number like 0003 */ - /* fill with zeros */ - n = sprintf(tmp, "%d", s.token); - len = strlen(tmp); - while (strlen(tmp) < 4) - n += sprintf (tmp+n, "0"); - - /* invert the string */ - while (tmp[i]) { - if (i<len) - tmp2[4-len+i] = tmp[i]; - else - tmp2[3-i] = tmp[i]; - i++; - } - tmp2[4] = '\0'; - - sprintf (rstr, SENSOR_PREFIX"%s", tmp2); - - ret = (char *) get_property(rtas, rstr, &llen); - - n=0; - if (ret[0] == '\0') - n += sprintf ( buffer+n, "--- ");/* does not have a location */ - else { - char t[50]; - ret += pos; - - n += check_location_string(ret, buffer + n); - n += sprintf ( buffer+n, " "); - /* see how many characters we have printed */ - sprintf ( t, "%s ", ret); - - pos += strlen(t); - if (pos >= llen) pos=0; - } - return n; -} -/* ****************************************************************** */ -/* INDICATORS - Tone Frequency */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - unsigned long freq; - char *dest; - int error; - freq = simple_strtoul(buf, &dest, 10); - if (*dest != '\0' && *dest != '\n') { - printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n"); - return count; - } - if (freq < 0) freq = 0; - rtas_tone_frequency = freq; /* save it for later */ - error = call_rtas("set-indicator", 3, 1, NULL, - TONE_FREQUENCY, 0, freq); - if (error != 0) - printk(KERN_WARNING "error: setting tone frequency returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - int n; - n = sprintf(buf, "%lu\n", rtas_tone_frequency); - - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} -/* ****************************************************************** */ -/* INDICATORS - Tone Volume */ -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - unsigned long volume; - char *dest; - int error; - volume = simple_strtoul(buf, &dest, 10); - if (*dest != '\0' && *dest != '\n') { - printk("ppc_rtas_tone_volume_write: Invalid tone volume\n"); - return count; - } - if (volume < 0) volume = 0; - if (volume > 100) volume = 100; - - rtas_tone_volume = volume; /* save it for later */ - error = call_rtas("set-indicator", 3, 1, NULL, - TONE_VOLUME, 0, volume); - if (error != 0) - printk(KERN_WARNING "error: setting tone volume returned: %s\n", - ppc_rtas_process_error(error)); - return count; -} -/* ****************************************************************** */ -static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - int n; - n = sprintf(buf, "%lu\n", rtas_tone_volume); - - if (*ppos >= strlen(buf)) - return 0; - if (n > strlen(buf) - *ppos) - n = strlen(buf) - *ppos; - if (n > count) - n = count; - *ppos += n; - return n; -} diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 0939624fb66e..4de92f49857e 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -2,16 +2,6 @@ # Makefile for the linux kernel. # -ifdef CONFIG_PPC64BRIDGE -EXTRA_AFLAGS := -Wa,-mppc64bridge -endif -ifdef CONFIG_4xx -EXTRA_AFLAGS := -Wa,-m405 -endif -ifdef CONFIG_E500 -EXTRA_AFLAGS := -Wa,-me500 -endif - CFLAGS_prom_init.o += -fPIC CFLAGS_btext.o += -fPIC @@ -25,7 +15,8 @@ ifeq ($(CONFIG_4xx),y) obj-$(CONFIG_4xx) += ppc4xx_pic.o obj-$(CONFIG_40x) += ppc4xx_setup.o obj-$(CONFIG_GEN_RTC) += todc_time.o -obj-$(CONFIG_KGDB) += ppc4xx_kgdb.o +obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o +obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o ifeq ($(CONFIG_40x),y) obj-$(CONFIG_KGDB) += ppc4xx_kgdb.o obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o diff --git a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c index 050e12bc59fb..b2f3d850503c 100644 --- a/arch/ppc/syslib/ppc4xx_dma.c +++ b/arch/ppc/syslib/ppc4xx_dma.c @@ -1,42 +1,427 @@ /* - * Author: Pete Popov <ppopov@mvista.com> or source@mvista.com + * arch/ppc/kernel/ppc4xx_dma.c * - * arch/ppc/kernel/ppc405_dma.c + * IBM PPC4xx DMA engine core library * - * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. + * Copyright 2000-2004 MontaVista Software Inc. * - * IBM 405 DMA Controller Functions + * Cleaned up and converted to new DCR access + * Matt Porter <mporter@kernel.crashing.org> + * + * Original code by Armin Kuster <akuster@mvista.com> + * and Pete Popov <ppopov@mvista.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/config.h> #include <linux/kernel.h> -#include <asm/system.h> -#include <asm/io.h> #include <linux/mm.h> #include <linux/miscdevice.h> #include <linux/init.h> #include <linux/module.h> -#include <asm/ppc405_dma.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/ppc4xx_dma.h> + +ppc_dma_ch_t dma_channels[MAX_PPC4xx_DMA_CHANNELS]; + +int +ppc4xx_get_dma_status(void) +{ + return (mfdcr(DCRN_DMASR)); +} + +void +ppc4xx_set_src_addr(int dmanr, phys_addr_t src_addr) +{ + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("set_src_addr: bad channel: %d\n", dmanr); + return; + } + +#ifdef PPC4xx_DMA64BIT + mtdcr(DCRN_DMASAH0 + dmanr*2, (u32)(src_addr >> 32)); +#else + mtdcr(DCRN_DMASA0 + dmanr*2, (u32)src_addr); +#endif +} + +void +ppc4xx_set_dst_addr(int dmanr, phys_addr_t dst_addr) +{ + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("set_dst_addr: bad channel: %d\n", dmanr); + return; + } + +#ifdef PPC4xx_DMA64BIT + mtdcr(DCRN_DMADAH0 + dmanr*2, (u32)(dst_addr >> 32)); +#else + mtdcr(DCRN_DMADA0 + dmanr*2, (u32)dst_addr); +#endif +} + +void +ppc4xx_enable_dma(unsigned int dmanr) +{ + unsigned int control; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + unsigned int status_bits[] = { DMA_CS0 | DMA_TS0 | DMA_CH0_ERR, + DMA_CS1 | DMA_TS1 | DMA_CH1_ERR, + DMA_CS2 | DMA_TS2 | DMA_CH2_ERR, + DMA_CS3 | DMA_TS3 | DMA_CH3_ERR}; + + if (p_dma_ch->in_use) { + printk("enable_dma: channel %d in use\n", dmanr); + return; + } + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("enable_dma: bad channel: %d\n", dmanr); + return; + } + + if (p_dma_ch->mode == DMA_MODE_READ) { + /* peripheral to memory */ + ppc4xx_set_src_addr(dmanr, 0); + ppc4xx_set_dst_addr(dmanr, p_dma_ch->addr); + } else if (p_dma_ch->mode == DMA_MODE_WRITE) { + /* memory to peripheral */ + ppc4xx_set_src_addr(dmanr, p_dma_ch->addr); + ppc4xx_set_dst_addr(dmanr, 0); + } + + /* for other xfer modes, the addresses are already set */ + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + + control &= ~(DMA_TM_MASK | DMA_TD); /* clear all mode bits */ + if (p_dma_ch->mode == DMA_MODE_MM) { + /* software initiated memory to memory */ + control |= DMA_ETD_OUTPUT | DMA_TCE_ENABLE; + } + + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + /* + * Clear the CS, TS, RI bits for the channel from DMASR. This + * has been observed to happen correctly only after the mode and + * ETD/DCE bits in DMACRx are set above. Must do this before + * enabling the channel. + */ + + mtdcr(DCRN_DMASR, status_bits[dmanr]); + + /* + * For device-paced transfers, Terminal Count Enable apparently + * must be on, and this must be turned on after the mode, etc. + * bits are cleared above (at least on Redwood-6). + */ + + if ((p_dma_ch->mode == DMA_MODE_MM_DEVATDST) || + (p_dma_ch->mode == DMA_MODE_MM_DEVATSRC)) + control |= DMA_TCE_ENABLE; + + /* + * Now enable the channel. + */ + + control |= (p_dma_ch->mode | DMA_CE_ENABLE); + + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + p_dma_ch->in_use = 1; +} + +void +ppc4xx_disable_dma(unsigned int dmanr) +{ + unsigned int control; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (!p_dma_ch->in_use) { + printk("disable_dma: channel %d not in use\n", dmanr); + return; + } + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("disable_dma: bad channel: %d\n", dmanr); + return; + } + + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + control &= ~DMA_CE_ENABLE; + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + p_dma_ch->in_use = 0; +} + +/* + * Sets the dma mode for single DMA transfers only. + * For scatter/gather transfers, the mode is passed to the + * alloc_dma_handle() function as one of the parameters. + * + * The mode is simply saved and used later. This allows + * the driver to call set_dma_mode() and set_dma_addr() in + * any order. + * + * Valid mode values are: + * + * DMA_MODE_READ peripheral to memory + * DMA_MODE_WRITE memory to peripheral + * DMA_MODE_MM memory to memory + * DMA_MODE_MM_DEVATSRC device-paced memory to memory, device at src + * DMA_MODE_MM_DEVATDST device-paced memory to memory, device at dst + */ +int +ppc4xx_set_dma_mode(unsigned int dmanr, unsigned int mode) +{ + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("set_dma_mode: bad channel 0x%x\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + p_dma_ch->mode = mode; + + return DMA_STATUS_GOOD; +} + +/* + * Sets the DMA Count register. Note that 'count' is in bytes. + * However, the DMA Count register counts the number of "transfers", + * where each transfer is equal to the bus width. Thus, count + * MUST be a multiple of the bus width. + */ +void +ppc4xx_set_dma_count(unsigned int dmanr, unsigned int count) +{ + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + +#ifdef DEBUG_4xxDMA + { + int error = 0; + switch (p_dma_ch->pwidth) { + case PW_8: + break; + case PW_16: + if (count & 0x1) + error = 1; + break; + case PW_32: + if (count & 0x3) + error = 1; + break; + case PW_64: + if (count & 0x7) + error = 1; + break; + default: + printk("set_dma_count: invalid bus width: 0x%x\n", + p_dma_ch->pwidth); + return; + } + if (error) + printk + ("Warning: set_dma_count count 0x%x bus width %d\n", + count, p_dma_ch->pwidth); + } +#endif + count = count >> p_dma_ch->shift; + + mtdcr(DCRN_DMACT0 + (dmanr * 0x8), count); +} /* - * Function prototypes + * Returns the number of bytes left to be transfered. + * After a DMA transfer, this should return zero. + * Reading this while a DMA transfer is still in progress will return + * unpredictable results. */ +int +ppc4xx_get_dma_residue(unsigned int dmanr) +{ + unsigned int count; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; -int hw_init_dma_channel(unsigned int, ppc_dma_ch_t *); -int init_dma_channel(unsigned int); -int get_channel_config(unsigned int, ppc_dma_ch_t *); -int set_channel_priority(unsigned int, unsigned int); -unsigned int get_peripheral_width(unsigned int); -int alloc_dma_handle(sgl_handle_t *, unsigned int, unsigned int); -void free_dma_handle(sgl_handle_t); + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_get_dma_residue: bad channel 0x%x\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + count = mfdcr(DCRN_DMACT0 + (dmanr * 0x8)); -ppc_dma_ch_t dma_channels[MAX_405GP_DMA_CHANNELS]; + return (count << p_dma_ch->shift); +} + +/* + * Sets the DMA address for a memory to peripheral or peripheral + * to memory transfer. The address is just saved in the channel + * structure for now and used later in enable_dma(). + */ +void +ppc4xx_set_dma_addr(unsigned int dmanr, phys_addr_t addr) +{ + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_set_dma_addr: bad channel: %d\n", dmanr); + return; + } + +#ifdef DEBUG_4xxDMA + { + int error = 0; + switch (p_dma_ch->pwidth) { + case PW_8: + break; + case PW_16: + if ((unsigned) addr & 0x1) + error = 1; + break; + case PW_32: + if ((unsigned) addr & 0x3) + error = 1; + break; + case PW_64: + if ((unsigned) addr & 0x7) + error = 1; + break; + default: + printk("ppc4xx_set_dma_addr: invalid bus width: 0x%x\n", + p_dma_ch->pwidth); + return; + } + if (error) + printk("Warning: ppc4xx_set_dma_addr addr 0x%x bus width %d\n", + addr, p_dma_ch->pwidth); + } +#endif + + /* save dma address and program it later after we know the xfer mode */ + p_dma_ch->addr = addr; +} + +/* + * Sets both DMA addresses for a memory to memory transfer. + * For memory to peripheral or peripheral to memory transfers + * the function set_dma_addr() should be used instead. + */ +void +ppc4xx_set_dma_addr2(unsigned int dmanr, phys_addr_t src_dma_addr, + phys_addr_t dst_dma_addr) +{ + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_set_dma_addr2: bad channel: %d\n", dmanr); + return; + } + +#ifdef DEBUG_4xxDMA + { + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + int error = 0; + switch (p_dma_ch->pwidth) { + case PW_8: + break; + case PW_16: + if (((unsigned) src_dma_addr & 0x1) || + ((unsigned) dst_dma_addr & 0x1) + ) + error = 1; + break; + case PW_32: + if (((unsigned) src_dma_addr & 0x3) || + ((unsigned) dst_dma_addr & 0x3) + ) + error = 1; + break; + case PW_64: + if (((unsigned) src_dma_addr & 0x7) || + ((unsigned) dst_dma_addr & 0x7) + ) + error = 1; + break; + default: + printk("ppc4xx_set_dma_addr2: invalid bus width: 0x%x\n", + p_dma_ch->pwidth); + return; + } + if (error) + printk + ("Warning: ppc4xx_set_dma_addr2 src 0x%x dst 0x%x bus width %d\n", + src_dma_addr, dst_dma_addr, p_dma_ch->pwidth); + } +#endif + + ppc4xx_set_src_addr(dmanr, src_dma_addr); + ppc4xx_set_dst_addr(dmanr, dst_dma_addr); +} + +/* + * Enables the channel interrupt. + * + * If performing a scatter/gatter transfer, this function + * MUST be called before calling alloc_dma_handle() and building + * the sgl list. Otherwise, interrupts will not be enabled, if + * they were previously disabled. + */ +int +ppc4xx_enable_dma_interrupt(unsigned int dmanr) +{ + unsigned int control; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_enable_dma_interrupt: bad channel: %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + p_dma_ch->int_enable = 1; + + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + control |= DMA_CIE_ENABLE; /* Channel Interrupt Enable */ + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + return DMA_STATUS_GOOD; +} + +/* + * Disables the channel interrupt. + * + * If performing a scatter/gatter transfer, this function + * MUST be called before calling alloc_dma_handle() and building + * the sgl list. Otherwise, interrupts will not be disabled, if + * they were previously enabled. + */ +int +ppc4xx_disable_dma_interrupt(unsigned int dmanr) +{ + unsigned int control; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_disable_dma_interrupt: bad channel: %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + p_dma_ch->int_enable = 0; + + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + control &= ~DMA_CIE_ENABLE; /* Channel Interrupt Enable */ + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + return DMA_STATUS_GOOD; +} /* * Configures a DMA channel, including the peripheral bus width, if a @@ -47,166 +432,112 @@ ppc_dma_ch_t dma_channels[MAX_405GP_DMA_CHANNELS]; * called from platform specific init code. The driver should not need to * call this function. */ -int hw_init_dma_channel(unsigned int dmanr, ppc_dma_ch_t *p_init) +int +ppc4xx_init_dma_channel(unsigned int dmanr, ppc_dma_ch_t * p_init) { - unsigned int polarity; - uint32_t control = 0; - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - -#ifdef DEBUG_405DMA - if (!p_init) { - printk("hw_init_dma_channel: NULL p_init\n"); - return DMA_STATUS_NULL_POINTER; - } - if (dmanr >= MAX_405GP_DMA_CHANNELS) { - printk("hw_init_dma_channel: bad channel %d\n", dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif + unsigned int polarity; + uint32_t control = 0; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + + DMA_MODE_READ = (unsigned long) DMA_TD; /* Peripheral to Memory */ + DMA_MODE_WRITE = 0; /* Memory to Peripheral */ + + if (!p_init) { + printk("ppc4xx_init_dma_channel: NULL p_init\n"); + return DMA_STATUS_NULL_POINTER; + } + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_init_dma_channel: bad channel %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } #if DCRN_POL > 0 - polarity = mfdcr(DCRN_POL); + polarity = mfdcr(DCRN_POL); #else - polarity = 0; + polarity = 0; #endif - /* Setup the control register based on the values passed to - * us in p_init. Then, over-write the control register with this - * new value. - */ - - control |= ( - SET_DMA_CIE_ENABLE(p_init->int_enable) | /* interrupt enable */ - SET_DMA_BEN(p_init->buffer_enable) | /* buffer enable */ - SET_DMA_ETD(p_init->etd_output) | /* end of transfer pin */ - SET_DMA_TCE(p_init->tce_enable) | /* terminal count enable */ - SET_DMA_PL(p_init->pl) | /* peripheral location */ - SET_DMA_DAI(p_init->dai) | /* dest addr increment */ - SET_DMA_SAI(p_init->sai) | /* src addr increment */ - SET_DMA_PRIORITY(p_init->cp) | /* channel priority */ - SET_DMA_PW(p_init->pwidth) | /* peripheral/bus width */ - SET_DMA_PSC(p_init->psc) | /* peripheral setup cycles */ - SET_DMA_PWC(p_init->pwc) | /* peripheral wait cycles */ - SET_DMA_PHC(p_init->phc) | /* peripheral hold cycles */ - SET_DMA_PREFETCH(p_init->pf) /* read prefetch */ - ); - - switch (dmanr) { - case 0: - /* clear all polarity signals and then "or" in new signal levels */ - polarity &= ~(DMAReq0_ActiveLow | DMAAck0_ActiveLow | EOT0_ActiveLow); - polarity |= p_dma_ch->polarity; -#if DCRN_POL > 0 - mtdcr(DCRN_POL, polarity); -#endif - mtdcr(DCRN_DMACR0, control); - break; - case 1: - polarity &= ~(DMAReq1_ActiveLow | DMAAck1_ActiveLow | EOT1_ActiveLow); - polarity |= p_dma_ch->polarity; -#if DCRN_POL > 0 - mtdcr(DCRN_POL, polarity); -#endif - mtdcr(DCRN_DMACR1, control); - break; - case 2: - polarity &= ~(DMAReq2_ActiveLow | DMAAck2_ActiveLow | EOT2_ActiveLow); - polarity |= p_dma_ch->polarity; -#if DCRN_POL > 0 - mtdcr(DCRN_POL, polarity); -#endif - mtdcr(DCRN_DMACR2, control); - break; - case 3: - polarity &= ~(DMAReq3_ActiveLow | DMAAck3_ActiveLow | EOT3_ActiveLow); - polarity |= p_dma_ch->polarity; + /* Setup the control register based on the values passed to + * us in p_init. Then, over-write the control register with this + * new value. + */ + control |= SET_DMA_CONTROL; + + /* clear all polarity signals and then "or" in new signal levels */ + polarity &= ~GET_DMA_POLARITY(dmanr); + polarity |= p_dma_ch->polarity; #if DCRN_POL > 0 - mtdcr(DCRN_POL, polarity); + mtdcr(DCRN_POL, polarity); #endif - mtdcr(DCRN_DMACR3, control); - break; - default: - return DMA_STATUS_BAD_CHANNEL; - } - - /* save these values in our dma channel structure */ - memcpy(p_dma_ch, p_init, sizeof(ppc_dma_ch_t)); - - /* - * The peripheral width values written in the control register are: - * PW_8 0 - * PW_16 1 - * PW_32 2 - * PW_64 3 - * - * Since the DMA count register takes the number of "transfers", - * we need to divide the count sent to us in certain - * functions by the appropriate number. It so happens that our - * right shift value is equal to the peripheral width value. - */ - p_dma_ch->shift = p_init->pwidth; - - /* - * Save the control word for easy access. - */ - p_dma_ch->control = control; - - mtdcr(DCRN_DMASR, 0xffffffff); /* clear status register */ - return DMA_STATUS_GOOD; + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + + /* save these values in our dma channel structure */ + memcpy(p_dma_ch, p_init, sizeof (ppc_dma_ch_t)); + + /* + * The peripheral width values written in the control register are: + * PW_8 0 + * PW_16 1 + * PW_32 2 + * PW_64 3 + * + * Since the DMA count register takes the number of "transfers", + * we need to divide the count sent to us in certain + * functions by the appropriate number. It so happens that our + * right shift value is equal to the peripheral width value. + */ + p_dma_ch->shift = p_init->pwidth; + + /* + * Save the control word for easy access. + */ + p_dma_ch->control = control; + + mtdcr(DCRN_DMASR, 0xffffffff); /* clear status register */ + return DMA_STATUS_GOOD; } - - - /* * This function returns the channel configuration. */ -int get_channel_config(unsigned int dmanr, ppc_dma_ch_t *p_dma_ch) +int +ppc4xx_get_channel_config(unsigned int dmanr, ppc_dma_ch_t * p_dma_ch) { - unsigned int polarity; - unsigned int control; + unsigned int polarity; + unsigned int control; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_get_channel_config: bad channel %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } #if DCRN_POL > 0 - polarity = mfdcr(DCRN_POL); + polarity = mfdcr(DCRN_POL); #else - polarity = 0; + polarity = 0; #endif - switch (dmanr) { - case 0: - p_dma_ch->polarity = - polarity & (DMAReq0_ActiveLow | DMAAck0_ActiveLow | EOT0_ActiveLow); - control = mfdcr(DCRN_DMACR0); - break; - case 1: - p_dma_ch->polarity = - polarity & (DMAReq1_ActiveLow | DMAAck1_ActiveLow | EOT1_ActiveLow); - control = mfdcr(DCRN_DMACR1); - break; - case 2: - p_dma_ch->polarity = - polarity & (DMAReq2_ActiveLow | DMAAck2_ActiveLow | EOT2_ActiveLow); - control = mfdcr(DCRN_DMACR2); - break; - case 3: - p_dma_ch->polarity = - polarity & (DMAReq3_ActiveLow | DMAAck3_ActiveLow | EOT3_ActiveLow); - control = mfdcr(DCRN_DMACR3); - break; - default: - return DMA_STATUS_BAD_CHANNEL; - } - - p_dma_ch->cp = GET_DMA_PRIORITY(control); - p_dma_ch->pwidth = GET_DMA_PW(control); - p_dma_ch->psc = GET_DMA_PSC(control); - p_dma_ch->pwc = GET_DMA_PWC(control); - p_dma_ch->phc = GET_DMA_PHC(control); - p_dma_ch->pf = GET_DMA_PREFETCH(control); - p_dma_ch->int_enable = GET_DMA_CIE_ENABLE(control); - p_dma_ch->shift = GET_DMA_PW(control); - - return DMA_STATUS_GOOD; + p_dma_ch->polarity = polarity & GET_DMA_POLARITY(dmanr); + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + + p_dma_ch->cp = GET_DMA_PRIORITY(control); + p_dma_ch->pwidth = GET_DMA_PW(control); + p_dma_ch->psc = GET_DMA_PSC(control); + p_dma_ch->pwc = GET_DMA_PWC(control); + p_dma_ch->phc = GET_DMA_PHC(control); + p_dma_ch->ce = GET_DMA_CE_ENABLE(control); + p_dma_ch->int_enable = GET_DMA_CIE_ENABLE(control); + p_dma_ch->shift = GET_DMA_PW(control); + +#ifdef CONFIG_PPC4xx_EDMA + p_dma_ch->pf = GET_DMA_PREFETCH(control); +#else + p_dma_ch->ch_enable = GET_DMA_CH(control); + p_dma_ch->ece_enable = GET_DMA_ECE(control); + p_dma_ch->tcd_disable = GET_DMA_TCD(control); +#endif + return DMA_STATUS_GOOD; } /* @@ -222,50 +553,28 @@ int get_channel_config(unsigned int dmanr, ppc_dma_ch_t *p_dma_ch) * PRIORITY_HIGH * */ -int set_channel_priority(unsigned int dmanr, unsigned int priority) +int +ppc4xx_set_channel_priority(unsigned int dmanr, unsigned int priority) { - unsigned int control; - -#ifdef DEBUG_405DMA - if ( (priority != PRIORITY_LOW) && - (priority != PRIORITY_MID_LOW) && - (priority != PRIORITY_MID_HIGH) && - (priority != PRIORITY_HIGH)) { - printk("set_channel_priority: bad priority: 0x%x\n", priority); - } -#endif + unsigned int control; - switch (dmanr) { - case 0: - control = mfdcr(DCRN_DMACR0); - control|= SET_DMA_PRIORITY(priority); - mtdcr(DCRN_DMACR0, control); - break; - case 1: - control = mfdcr(DCRN_DMACR1); - control|= SET_DMA_PRIORITY(priority); - mtdcr(DCRN_DMACR1, control); - break; - case 2: - control = mfdcr(DCRN_DMACR2); - control|= SET_DMA_PRIORITY(priority); - mtdcr(DCRN_DMACR2, control); - break; - case 3: - control = mfdcr(DCRN_DMACR3); - control|= SET_DMA_PRIORITY(priority); - mtdcr(DCRN_DMACR3, control); - break; - default: -#ifdef DEBUG_405DMA - printk("set_channel_priority: bad channel: %d\n", dmanr); -#endif - return DMA_STATUS_BAD_CHANNEL; - } - return DMA_STATUS_GOOD; -} + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_set_channel_priority: bad channel %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + if ((priority != PRIORITY_LOW) && + (priority != PRIORITY_MID_LOW) && + (priority != PRIORITY_MID_HIGH) && (priority != PRIORITY_HIGH)) { + printk("ppc4xx_set_channel_priority: bad priority: 0x%x\n", priority); + } + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); + control |= SET_DMA_PRIORITY(priority); + mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control); + return DMA_STATUS_GOOD; +} /* * Returns the width of the peripheral attached to this channel. This assumes @@ -280,213 +589,36 @@ int set_channel_priority(unsigned int dmanr, unsigned int priority) * * The function returns 0 on error. */ -unsigned int get_peripheral_width(unsigned int dmanr) +unsigned int +ppc4xx_get_peripheral_width(unsigned int dmanr) { - unsigned int control; - - switch (dmanr) { - case 0: - control = mfdcr(DCRN_DMACR0); - break; - case 1: - control = mfdcr(DCRN_DMACR1); - break; - case 2: - control = mfdcr(DCRN_DMACR2); - break; - case 3: - control = mfdcr(DCRN_DMACR3); - break; - default: -#ifdef DEBUG_405DMA - printk("get_peripheral_width: bad channel: %d\n", dmanr); -#endif - return 0; - } - return(GET_DMA_PW(control)); -} - - - - -/* - * Create a scatter/gather list handle. This is simply a structure which - * describes a scatter/gather list. - * - * A handle is returned in "handle" which the driver should save in order to - * be able to access this list later. A chunk of memory will be allocated - * to be used by the API for internal management purposes, including managing - * the sg list and allocating memory for the sgl descriptors. One page should - * be more than enough for that purpose. Perhaps it's a bit wasteful to use - * a whole page for a single sg list, but most likely there will be only one - * sg list per channel. - * - * Interrupt notes: - * Each sgl descriptor has a copy of the DMA control word which the DMA engine - * loads in the control register. The control word has a "global" interrupt - * enable bit for that channel. Interrupts are further qualified by a few bits - * in the sgl descriptor count register. In order to setup an sgl, we have to - * know ahead of time whether or not interrupts will be enabled at the completion - * of the transfers. Thus, enable_dma_interrupt()/disable_dma_interrupt() MUST - * be called before calling alloc_dma_handle(). If the interrupt mode will never - * change after powerup, then enable_dma_interrupt()/disable_dma_interrupt() - * do not have to be called -- interrupts will be enabled or disabled based - * on how the channel was configured after powerup by the hw_init_dma_channel() - * function. Each sgl descriptor will be setup to interrupt if an error occurs; - * however, only the last descriptor will be setup to interrupt. Thus, an - * interrupt will occur (if interrupts are enabled) only after the complete - * sgl transfer is done. - */ -int alloc_dma_handle(sgl_handle_t *phandle, unsigned int mode, unsigned int dmanr) -{ - sgl_list_info_t *psgl; - dma_addr_t dma_addr; - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - uint32_t sg_command; - void *ret; - -#ifdef DEBUG_405DMA - if (!phandle) { - printk("alloc_dma_handle: null handle pointer\n"); - return DMA_STATUS_NULL_POINTER; - } - switch (mode) { - case DMA_MODE_READ: - case DMA_MODE_WRITE: - case DMA_MODE_MM: - case DMA_MODE_MM_DEVATSRC: - case DMA_MODE_MM_DEVATDST: - break; - default: - printk("alloc_dma_handle: bad mode 0x%x\n", mode); - return DMA_STATUS_BAD_MODE; - } - if (dmanr >= MAX_405GP_DMA_CHANNELS) { - printk("alloc_dma_handle: invalid channel 0x%x\n", dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif + unsigned int control; - /* Get a page of memory, which is zeroed out by pci_alloc_consistent() */ - -/* wrong not a pci device - armin */ - /* psgl = (sgl_list_info_t *) pci_alloc_consistent(NULL, SGL_LIST_SIZE, &dma_addr); -*/ - - ret = consistent_alloc(GFP_ATOMIC |GFP_DMA, SGL_LIST_SIZE, &dma_addr); - if (ret != NULL) { - memset(ret, 0,SGL_LIST_SIZE ); - psgl = (sgl_list_info_t *) ret; + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_get_peripheral_width: bad channel %d\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; } + control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8)); - if (psgl == NULL) { - *phandle = (sgl_handle_t)NULL; - return DMA_STATUS_OUT_OF_MEMORY; - } - - psgl->dma_addr = dma_addr; - psgl->dmanr = dmanr; - - /* - * Modify and save the control word. These word will get written to each sgl - * descriptor. The DMA engine then loads this control word into the control - * register every time it reads a new descriptor. - */ - psgl->control = p_dma_ch->control; - psgl->control &= ~(DMA_TM_MASK | DMA_TD); /* clear all "mode" bits first */ - psgl->control |= (mode | DMA_CH_ENABLE); /* save the control word along with the mode */ - - if (p_dma_ch->int_enable) { - psgl->control |= DMA_CIE_ENABLE; /* channel interrupt enabled */ - } - else { - psgl->control &= ~DMA_CIE_ENABLE; - } - -#if DCRN_ASGC > 0 - sg_command = mfdcr(DCRN_ASGC); - switch (dmanr) { - case 0: - sg_command |= SSG0_MASK_ENABLE; - break; - case 1: - sg_command |= SSG1_MASK_ENABLE; - break; - case 2: - sg_command |= SSG2_MASK_ENABLE; - break; - case 3: - sg_command |= SSG3_MASK_ENABLE; - break; - default: -#ifdef DEBUG_405DMA - printk("alloc_dma_handle: bad channel: %d\n", dmanr); -#endif - free_dma_handle((sgl_handle_t)psgl); - *phandle = (sgl_handle_t)NULL; - return DMA_STATUS_BAD_CHANNEL; - } - - mtdcr(DCRN_ASGC, sg_command); /* enable writing to this channel's sgl control bits */ -#else - (void)sg_command; -#endif - psgl->sgl_control = SG_ERI_ENABLE | SG_LINK; /* sgl descriptor control bits */ - - if (p_dma_ch->int_enable) { - if (p_dma_ch->tce_enable) - psgl->sgl_control |= SG_TCI_ENABLE; - else - psgl->sgl_control |= SG_ETI_ENABLE; - } - - *phandle = (sgl_handle_t)psgl; - return DMA_STATUS_GOOD; -} - - - -/* - * Destroy a scatter/gather list handle that was created by alloc_dma_handle(). - * The list must be empty (contain no elements). - */ -void free_dma_handle(sgl_handle_t handle) -{ - sgl_list_info_t *psgl = (sgl_list_info_t *)handle; - - if (!handle) { -#ifdef DEBUG_405DMA - printk("free_dma_handle: got NULL\n"); -#endif - return; - } - else if (psgl->phead) { -#ifdef DEBUG_405DMA - printk("free_dma_handle: list not empty\n"); -#endif - return; - } - else if (!psgl->dma_addr) { /* should never happen */ -#ifdef DEBUG_405DMA - printk("free_dma_handle: no dma address\n"); -#endif - return; - } - - /* wrong not a PCI device -armin */ - /* pci_free_consistent(NULL, SGL_LIST_SIZE, (void *)psgl, psgl->dma_addr); */ - // free_pages((unsigned long)psgl, get_order(SGL_LIST_SIZE)); - consistent_free((void *)psgl); - - + return (GET_DMA_PW(control)); } -EXPORT_SYMBOL(hw_init_dma_channel); -EXPORT_SYMBOL(get_channel_config); -EXPORT_SYMBOL(set_channel_priority); -EXPORT_SYMBOL(get_peripheral_width); -EXPORT_SYMBOL(alloc_dma_handle); -EXPORT_SYMBOL(free_dma_handle); +EXPORT_SYMBOL(ppc4xx_init_dma_channel); +EXPORT_SYMBOL(ppc4xx_get_channel_config); +EXPORT_SYMBOL(ppc4xx_set_channel_priority); +EXPORT_SYMBOL(ppc4xx_get_peripheral_width); EXPORT_SYMBOL(dma_channels); +EXPORT_SYMBOL(ppc4xx_set_src_addr); +EXPORT_SYMBOL(ppc4xx_set_dst_addr); +EXPORT_SYMBOL(ppc4xx_set_dma_addr); +EXPORT_SYMBOL(ppc4xx_set_dma_addr2); +EXPORT_SYMBOL(ppc4xx_enable_dma); +EXPORT_SYMBOL(ppc4xx_disable_dma); +EXPORT_SYMBOL(ppc4xx_set_dma_mode); +EXPORT_SYMBOL(ppc4xx_set_dma_count); +EXPORT_SYMBOL(ppc4xx_get_dma_residue); +EXPORT_SYMBOL(ppc4xx_enable_dma_interrupt); +EXPORT_SYMBOL(ppc4xx_disable_dma_interrupt); +EXPORT_SYMBOL(ppc4xx_get_dma_status); diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c new file mode 100644 index 000000000000..49c6e9c61f38 --- /dev/null +++ b/arch/ppc/syslib/ppc4xx_sgdma.c @@ -0,0 +1,455 @@ +/* + * arch/ppc/kernel/ppc4xx_sgdma.c + * + * IBM PPC4xx DMA engine scatter/gather library + * + * Copyright 2002-2003 MontaVista Software Inc. + * + * Cleaned up and converted to new DCR access + * Matt Porter <mporter@kernel.crashing.org> + * + * Original code by Armin Kuster <akuster@mvista.com> + * and Pete Popov <ppopov@mvista.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> + +#include <asm/system.h> +#include <asm/io.h> +#include <asm/ppc4xx_dma.h> + +void +ppc4xx_set_sg_addr(int dmanr, phys_addr_t sg_addr) +{ + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_set_sg_addr: bad channel: %d\n", dmanr); + return; + } + +#ifdef PPC4xx_DMA_64BIT + mtdcr(DCRN_ASGH0 + (dmanr * 0x8), (u32)(sg_addr >> 32)); +#endif + mtdcr(DCRN_ASG0 + (dmanr * 0x8), (u32)sg_addr); +} + +/* + * Add a new sgl descriptor to the end of a scatter/gather list + * which was created by alloc_dma_handle(). + * + * For a memory to memory transfer, both dma addresses must be + * valid. For a peripheral to memory transfer, one of the addresses + * must be set to NULL, depending on the direction of the transfer: + * memory to peripheral: set dst_addr to NULL, + * peripheral to memory: set src_addr to NULL. + */ +int +ppc4xx_add_dma_sgl(sgl_handle_t handle, phys_addr_t src_addr, phys_addr_t dst_addr, + unsigned int count) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + ppc_dma_ch_t *p_dma_ch; + + if (!handle) { + printk("ppc4xx_add_dma_sgl: null handle\n"); + return DMA_STATUS_BAD_HANDLE; + } + + if (psgl->dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_add_dma_sgl: bad channel: %d\n", psgl->dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + p_dma_ch = &dma_channels[psgl->dmanr]; + +#ifdef DEBUG_4xxDMA + { + int error = 0; + unsigned int aligned = + (unsigned) src_addr | (unsigned) dst_addr | count; + switch (p_dma_ch->pwidth) { + case PW_8: + break; + case PW_16: + if (aligned & 0x1) + error = 1; + break; + case PW_32: + if (aligned & 0x3) + error = 1; + break; + case PW_64: + if (aligned & 0x7) + error = 1; + break; + default: + printk("ppc4xx_add_dma_sgl: invalid bus width: 0x%x\n", + p_dma_ch->pwidth); + return DMA_STATUS_GENERAL_ERROR; + } + if (error) + printk + ("Alignment warning: ppc4xx_add_dma_sgl src 0x%x dst 0x%x count 0x%x bus width var %d\n", + src_addr, dst_addr, count, p_dma_ch->pwidth); + + } +#endif + + if ((unsigned) (psgl->ptail + 1) >= ((unsigned) psgl + SGL_LIST_SIZE)) { + printk("sgl handle out of memory \n"); + return DMA_STATUS_OUT_OF_MEMORY; + } + + if (!psgl->ptail) { + psgl->phead = (ppc_sgl_t *) + ((unsigned) psgl + sizeof (sgl_list_info_t)); + psgl->phead_dma = psgl->dma_addr + sizeof(sgl_list_info_t); + psgl->ptail = psgl->phead; + psgl->ptail_dma = psgl->phead_dma; + } else { + psgl->ptail->next = psgl->ptail_dma + sizeof(ppc_sgl_t); + psgl->ptail++; + psgl->ptail_dma += sizeof(ppc_sgl_t); + } + + psgl->ptail->control = psgl->control; + psgl->ptail->src_addr = src_addr; + psgl->ptail->dst_addr = dst_addr; + psgl->ptail->control_count = (count >> p_dma_ch->shift) | + psgl->sgl_control; + psgl->ptail->next = (uint32_t) NULL; + + return DMA_STATUS_GOOD; +} + +/* + * Enable (start) the DMA described by the sgl handle. + */ +void +ppc4xx_enable_dma_sgl(sgl_handle_t handle) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + ppc_dma_ch_t *p_dma_ch; + uint32_t sg_command; + + if (!handle) { + printk("ppc4xx_enable_dma_sgl: null handle\n"); + return; + } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { + printk("ppc4xx_enable_dma_sgl: bad channel in handle %d\n", + psgl->dmanr); + return; + } else if (!psgl->phead) { + printk("ppc4xx_enable_dma_sgl: sg list empty\n"); + return; + } + + p_dma_ch = &dma_channels[psgl->dmanr]; + psgl->ptail->control_count &= ~SG_LINK; /* make this the last dscrptr */ + sg_command = mfdcr(DCRN_ASGC); + + ppc4xx_set_sg_addr(psgl->dmanr, psgl->phead_dma); + + sg_command |= SSG_ENABLE(psgl->dmanr); + + mtdcr(DCRN_ASGC, sg_command); /* start transfer */ +} + +/* + * Halt an active scatter/gather DMA operation. + */ +void +ppc4xx_disable_dma_sgl(sgl_handle_t handle) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + uint32_t sg_command; + + if (!handle) { + printk("ppc4xx_enable_dma_sgl: null handle\n"); + return; + } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { + printk("ppc4xx_enable_dma_sgl: bad channel in handle %d\n", + psgl->dmanr); + return; + } + + sg_command = mfdcr(DCRN_ASGC); + sg_command &= ~SSG_ENABLE(psgl->dmanr); + mtdcr(DCRN_ASGC, sg_command); /* stop transfer */ +} + +/* + * Returns number of bytes left to be transferred from the entire sgl list. + * *src_addr and *dst_addr get set to the source/destination address of + * the sgl descriptor where the DMA stopped. + * + * An sgl transfer must NOT be active when this function is called. + */ +int +ppc4xx_get_dma_sgl_residue(sgl_handle_t handle, phys_addr_t * src_addr, + phys_addr_t * dst_addr) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + ppc_dma_ch_t *p_dma_ch; + ppc_sgl_t *pnext, *sgl_addr; + uint32_t count_left; + + if (!handle) { + printk("ppc4xx_get_dma_sgl_residue: null handle\n"); + return DMA_STATUS_BAD_HANDLE; + } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { + printk("ppc4xx_get_dma_sgl_residue: bad channel in handle %d\n", + psgl->dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + sgl_addr = (ppc_sgl_t *) __va(mfdcr(DCRN_ASG0 + (psgl->dmanr * 0x8))); + count_left = mfdcr(DCRN_DMACT0 + (psgl->dmanr * 0x8)); + + if (!sgl_addr) { + printk("ppc4xx_get_dma_sgl_residue: sgl addr register is null\n"); + goto error; + } + + pnext = psgl->phead; + while (pnext && + ((unsigned) pnext < ((unsigned) psgl + SGL_LIST_SIZE) && + (pnext != sgl_addr)) + ) { + pnext++; + } + + if (pnext == sgl_addr) { /* found the sgl descriptor */ + + *src_addr = pnext->src_addr; + *dst_addr = pnext->dst_addr; + + /* + * Now search the remaining descriptors and add their count. + * We already have the remaining count from this descriptor in + * count_left. + */ + pnext++; + + while ((pnext != psgl->ptail) && + ((unsigned) pnext < ((unsigned) psgl + SGL_LIST_SIZE)) + ) { + count_left += pnext->control_count & SG_COUNT_MASK; + } + + if (pnext != psgl->ptail) { /* should never happen */ + printk + ("ppc4xx_get_dma_sgl_residue error (1) psgl->ptail 0x%x handle 0x%x\n", + (unsigned int) psgl->ptail, (unsigned int) handle); + goto error; + } + + /* success */ + p_dma_ch = &dma_channels[psgl->dmanr]; + return (count_left << p_dma_ch->shift); /* count in bytes */ + + } else { + /* this shouldn't happen */ + printk + ("get_dma_sgl_residue, unable to match current address 0x%x, handle 0x%x\n", + (unsigned int) sgl_addr, (unsigned int) handle); + + } + + error: + *src_addr = (phys_addr_t) NULL; + *dst_addr = (phys_addr_t) NULL; + return 0; +} + +/* + * Returns the address(es) of the buffer(s) contained in the head element of + * the scatter/gather list. The element is removed from the scatter/gather + * list and the next element becomes the head. + * + * This function should only be called when the DMA is not active. + */ +int +ppc4xx_delete_dma_sgl_element(sgl_handle_t handle, phys_addr_t * src_dma_addr, + phys_addr_t * dst_dma_addr) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + + if (!handle) { + printk("ppc4xx_delete_sgl_element: null handle\n"); + return DMA_STATUS_BAD_HANDLE; + } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) { + printk("ppc4xx_delete_sgl_element: bad channel in handle %d\n", + psgl->dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + if (!psgl->phead) { + printk("ppc4xx_delete_sgl_element: sgl list empty\n"); + *src_dma_addr = (phys_addr_t) NULL; + *dst_dma_addr = (phys_addr_t) NULL; + return DMA_STATUS_SGL_LIST_EMPTY; + } + + *src_dma_addr = (phys_addr_t) psgl->phead->src_addr; + *dst_dma_addr = (phys_addr_t) psgl->phead->dst_addr; + + if (psgl->phead == psgl->ptail) { + /* last descriptor on the list */ + psgl->phead = NULL; + psgl->ptail = NULL; + } else { + psgl->phead++; + psgl->phead_dma += sizeof(ppc_sgl_t); + } + + return DMA_STATUS_GOOD; +} + + +/* + * Create a scatter/gather list handle. This is simply a structure which + * describes a scatter/gather list. + * + * A handle is returned in "handle" which the driver should save in order to + * be able to access this list later. A chunk of memory will be allocated + * to be used by the API for internal management purposes, including managing + * the sg list and allocating memory for the sgl descriptors. One page should + * be more than enough for that purpose. Perhaps it's a bit wasteful to use + * a whole page for a single sg list, but most likely there will be only one + * sg list per channel. + * + * Interrupt notes: + * Each sgl descriptor has a copy of the DMA control word which the DMA engine + * loads in the control register. The control word has a "global" interrupt + * enable bit for that channel. Interrupts are further qualified by a few bits + * in the sgl descriptor count register. In order to setup an sgl, we have to + * know ahead of time whether or not interrupts will be enabled at the completion + * of the transfers. Thus, enable_dma_interrupt()/disable_dma_interrupt() MUST + * be called before calling alloc_dma_handle(). If the interrupt mode will never + * change after powerup, then enable_dma_interrupt()/disable_dma_interrupt() + * do not have to be called -- interrupts will be enabled or disabled based + * on how the channel was configured after powerup by the hw_init_dma_channel() + * function. Each sgl descriptor will be setup to interrupt if an error occurs; + * however, only the last descriptor will be setup to interrupt. Thus, an + * interrupt will occur (if interrupts are enabled) only after the complete + * sgl transfer is done. + */ +int +ppc4xx_alloc_dma_handle(sgl_handle_t * phandle, unsigned int mode, unsigned int dmanr) +{ + sgl_list_info_t *psgl; + dma_addr_t dma_addr; + ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; + uint32_t sg_command; + void *ret; + + if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) { + printk("ppc4xx_alloc_dma_handle: invalid channel 0x%x\n", dmanr); + return DMA_STATUS_BAD_CHANNEL; + } + + if (!phandle) { + printk("ppc4xx_alloc_dma_handle: null handle pointer\n"); + return DMA_STATUS_NULL_POINTER; + } + + /* Get a page of memory, which is zeroed out by consistent_alloc() */ + ret = dma_alloc_coherent(NULL, DMA_PPC4xx_SIZE, &dma_addr, GFP_KERNEL); + if (ret != NULL) { + memset(ret, 0, DMA_PPC4xx_SIZE); + psgl = (sgl_list_info_t *) ret; + } + + if (psgl == NULL) { + *phandle = (sgl_handle_t) NULL; + return DMA_STATUS_OUT_OF_MEMORY; + } + + psgl->dma_addr = dma_addr; + psgl->dmanr = dmanr; + + /* + * Modify and save the control word. These words will be + * written to each sgl descriptor. The DMA engine then + * loads this control word into the control register + * every time it reads a new descriptor. + */ + psgl->control = p_dma_ch->control; + /* Clear all mode bits */ + psgl->control &= ~(DMA_TM_MASK | DMA_TD); + /* Save control word and mode */ + psgl->control |= (mode | DMA_CE_ENABLE); + + /* In MM mode, we must set ETD/TCE */ + if (mode == DMA_MODE_MM) + psgl->control |= DMA_ETD_OUTPUT | DMA_TCE_ENABLE; + + if (p_dma_ch->int_enable) { + /* Enable channel interrupt */ + psgl->control |= DMA_CIE_ENABLE; + } else { + psgl->control &= ~DMA_CIE_ENABLE; + } + + sg_command = mfdcr(DCRN_ASGC); + sg_command |= SSG_MASK_ENABLE(dmanr); + + /* Enable SGL control access */ + mtdcr(DCRN_ASGC, sg_command); + psgl->sgl_control = SG_ERI_ENABLE | SG_LINK; + + if (p_dma_ch->int_enable) { + if (p_dma_ch->tce_enable) + psgl->sgl_control |= SG_TCI_ENABLE; + else + psgl->sgl_control |= SG_ETI_ENABLE; + } + + *phandle = (sgl_handle_t) psgl; + return DMA_STATUS_GOOD; +} + +/* + * Destroy a scatter/gather list handle that was created by alloc_dma_handle(). + * The list must be empty (contain no elements). + */ +void +ppc4xx_free_dma_handle(sgl_handle_t handle) +{ + sgl_list_info_t *psgl = (sgl_list_info_t *) handle; + + if (!handle) { + printk("ppc4xx_free_dma_handle: got NULL\n"); + return; + } else if (psgl->phead) { + printk("ppc4xx_free_dma_handle: list not empty\n"); + return; + } else if (!psgl->dma_addr) { /* should never happen */ + printk("ppc4xx_free_dma_handle: no dma address\n"); + return; + } + + dma_free_coherent(NULL, DMA_PPC4xx_SIZE, (void *) psgl, 0); +} + +EXPORT_SYMBOL(ppc4xx_alloc_dma_handle); +EXPORT_SYMBOL(ppc4xx_free_dma_handle); +EXPORT_SYMBOL(ppc4xx_add_dma_sgl); +EXPORT_SYMBOL(ppc4xx_delete_dma_sgl_element); +EXPORT_SYMBOL(ppc4xx_enable_dma_sgl); +EXPORT_SYMBOL(ppc4xx_disable_dma_sgl); +EXPORT_SYMBOL(ppc4xx_get_dma_sgl_residue); diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 304181cd88af..5705ce63bfc7 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -424,8 +424,6 @@ config IRQSTACKS for handling hard and soft interrupts. This can help avoid overflowing the process kernel stacks. -endmenu - config SPINLINE bool "Inline spinlock code at each call site" depends on SMP && !PPC_SPLPAR && !PPC_ISERIES @@ -436,6 +434,8 @@ config SPINLINE If in doubt, say N. +endmenu + source "security/Kconfig" source "crypto/Kconfig" diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index 9e665ed64d42..c5dd7e13b7c1 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -15,14 +15,11 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \ obj-$(CONFIG_PPC_OF) += of_device.o -obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_iommu.o +pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \ + iSeries_IoMmTable.o +pci-obj-$(CONFIG_PPC_PSERIES) += pci_dn.o pci_dma_direct.o -ifdef CONFIG_PPC_ISERIES -obj-$(CONFIG_PCI) += iSeries_pci.o iSeries_pci_reset.o \ - iSeries_IoMmTable.o -else -obj-$(CONFIG_PCI) += pci_dma_direct.o -endif +obj-$(CONFIG_PCI) += pci.o pci_iommu.o $(pci-obj-y) obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ iSeries_VpdInfo.o XmPciLpEvent.o \ diff --git a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c index bb8ca7fcfca7..d2a7377add53 100644 --- a/arch/ppc64/kernel/chrp_setup.c +++ b/arch/ppc64/kernel/chrp_setup.c @@ -298,8 +298,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, cur_cpu_spec->firmware_features); } -void -chrp_progress(char *s, unsigned short hex) +void chrp_progress(char *s, unsigned short hex) { struct device_node *root; int width, *p; @@ -313,60 +312,55 @@ chrp_progress(char *s, unsigned short hex) return; if (max_width == 0) { - if ( (root = find_path_device("/rtas")) && + if ((root = find_path_device("/rtas")) && (p = (unsigned int *)get_property(root, "ibm,display-line-length", - NULL)) ) + NULL))) max_width = *p; else max_width = 0x10; display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); } - if (display_character == RTAS_UNKNOWN_SERVICE) { - /* use hex display */ - if (set_indicator == RTAS_UNKNOWN_SERVICE) - return; - rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); - return; - } - if(display_character == RTAS_UNKNOWN_SERVICE) { + if (display_character == RTAS_UNKNOWN_SERVICE) { /* use hex display if available */ - if(set_indicator != RTAS_UNKNOWN_SERVICE) + if (set_indicator != RTAS_UNKNOWN_SERVICE) rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); return; } spin_lock(&progress_lock); - /* Last write ended with newline, but we didn't print it since + /* + * Last write ended with newline, but we didn't print it since * it would just clear the bottom line of output. Print it now * instead. * * If no newline is pending, print a CR to start output at the * beginning of the line. */ - if(pending_newline) { + if (pending_newline) { rtas_call(display_character, 1, 1, NULL, '\r'); rtas_call(display_character, 1, 1, NULL, '\n'); pending_newline = 0; - } else + } else { rtas_call(display_character, 1, 1, NULL, '\r'); + } width = max_width; os = s; while (*os) { - if(*os == '\n' || *os == '\r') { + if (*os == '\n' || *os == '\r') { /* Blank to end of line. */ - while(width-- > 0) + while (width-- > 0) rtas_call(display_character, 1, 1, NULL, ' '); /* If newline is the last character, save it * until next call to avoid bumping up the * display output. */ - if(*os == '\n' && !os[1]) { + if (*os == '\n' && !os[1]) { pending_newline = 1; spin_unlock(&progress_lock); return; @@ -374,7 +368,7 @@ chrp_progress(char *s, unsigned short hex) /* RTAS wants CR-LF, not just LF */ - if(*os == '\n') { + if (*os == '\n') { rtas_call(display_character, 1, 1, NULL, '\r'); rtas_call(display_character, 1, 1, NULL, '\n'); } else { @@ -393,14 +387,14 @@ chrp_progress(char *s, unsigned short hex) os++; /* if we overwrite the screen length */ - if ( width <= 0 ) - while ( (*os != 0) && (*os != '\n') && (*os != '\r') ) + if (width <= 0) + while ((*os != 0) && (*os != '\n') && (*os != '\r')) os++; } /* Blank to end of line. */ - while ( width-- > 0 ) - rtas_call(display_character, 1, 1, NULL, ' ' ); + while (width-- > 0) + rtas_call(display_character, 1, 1, NULL, ' '); spin_unlock(&progress_lock); } diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c index aa66533f24b8..5fdcce2db45e 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/ppc64/kernel/eeh.c @@ -618,7 +618,7 @@ void __init eeh_init(void) info.buid_lo = BUID_LO(buid); info.buid_hi = BUID_HI(buid); - traverse_pci_devices(phb, early_enable_eeh, NULL, &info); + traverse_pci_devices(phb, early_enable_eeh, &info); } if (eeh_subsystem_enabled) { diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S index 148bb78cedf4..2d48d24e7ab8 100644 --- a/arch/ppc64/kernel/entry.S +++ b/arch/ppc64/kernel/entry.S @@ -194,6 +194,7 @@ syscall_exit_trace_cont: mtspr SRR0,r7 mtspr SRR1,r8 rfid + b . /* prevent speculative execution */ syscall_enosys: li r3,-ENOSYS @@ -540,7 +541,7 @@ restore: ld r1,GPR1(r1) rfid - b . + b . /* prevent speculative execution */ /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ do_work: @@ -684,6 +685,7 @@ _GLOBAL(enter_rtas) mtspr SRR0,r5 mtspr SRR1,r6 rfid + b . /* prevent speculative execution */ _STATIC(rtas_return_loc) /* relocation is off at this point */ @@ -704,6 +706,7 @@ _STATIC(rtas_return_loc) mtspr SRR0,r3 mtspr SRR1,r4 rfid + b . /* prevent speculative execution */ _STATIC(rtas_restore_regs) /* relocation is on at this point */ diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index aefc7e6f0033..a5d67f59951d 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -221,7 +221,8 @@ exception_marker: mtspr SRR0,r12; \ mfspr r12,SRR1; /* and SRR1 */ \ mtspr SRR1,r10; \ - rfid + rfid; \ + b . /* prevent speculative execution */ /* * This is the start of the interrupt handlers for iSeries @@ -302,12 +303,14 @@ exception_marker: . = n; \ .globl label##_Pseries; \ label##_Pseries: \ + HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) #define STD_EXCEPTION_ISERIES(n, label, area) \ .globl label##_Iseries; \ label##_Iseries: \ + HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_ISERIES_1(area); \ EXCEPTION_PROLOG_ISERIES_2; \ @@ -316,6 +319,7 @@ label##_Iseries: \ #define MASKABLE_EXCEPTION_ISERIES(n, label) \ .globl label##_Iseries; \ label##_Iseries: \ + HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ lbz r10,PACAPROFENABLED(r13); \ @@ -409,12 +413,14 @@ __start_interrupts: . = 0x200 _MachineCheckPseries: + HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common) . = 0x300 .globl DataAccess_Pseries DataAccess_Pseries: + HMT_MEDIUM mtspr SPRG1,r13 BEGIN_FTR_SECTION mtspr SPRG2,r12 @@ -433,6 +439,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) . = 0x380 .globl DataAccessSLB_Pseries DataAccessSLB_Pseries: + HMT_MEDIUM mtspr SPRG1,r13 mfspr r13,SPRG3 /* get paca address into r13 */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ @@ -453,12 +460,14 @@ DataAccessSLB_Pseries: mtspr SRR1,r10 mfspr r3,DAR rfid + b . /* prevent speculative execution */ STD_EXCEPTION_PSERIES(0x400, InstructionAccess) . = 0x480 .globl InstructionAccessSLB_Pseries InstructionAccessSLB_Pseries: + HMT_MEDIUM mtspr SPRG1,r13 mfspr r13,SPRG3 /* get paca address into r13 */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ @@ -479,6 +488,7 @@ InstructionAccessSLB_Pseries: mtspr SRR1,r10 mr r3,r11 /* SRR0 is faulting address */ rfid + b . /* prevent speculative execution */ STD_EXCEPTION_PSERIES(0x500, HardwareInterrupt) STD_EXCEPTION_PSERIES(0x600, Alignment) @@ -491,6 +501,7 @@ InstructionAccessSLB_Pseries: . = 0xc00 .globl SystemCall_Pseries SystemCall_Pseries: + HMT_MEDIUM mr r9,r13 mfmsr r10 mfspr r13,SPRG3 @@ -503,6 +514,7 @@ SystemCall_Pseries: mfspr r12,SRR1 mtspr SRR1,r10 rfid + b . /* prevent speculative execution */ STD_EXCEPTION_PSERIES(0xd00, SingleStep) STD_EXCEPTION_PSERIES(0xe00, Trap_0e) @@ -727,6 +739,7 @@ HardwareInterrupt_Iseries_masked: ld r12,PACA_EXGEN+EX_R12(r13) ld r13,PACA_EXGEN+EX_R13(r13) rfid + b . /* prevent speculative execution */ #endif /* @@ -742,10 +755,12 @@ fwnmi_data_area: . = 0x8000 .globl SystemReset_FWNMI SystemReset_FWNMI: + HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, SystemReset_common) .globl MachineCheck_FWNMI MachineCheck_FWNMI: + HMT_MEDIUM mtspr SPRG1,r13 /* save r13 */ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common) @@ -867,6 +882,7 @@ fast_exception_return: REST_4GPRS(10, r1) ld r1,GPR1(r1) rfid + b . /* prevent speculative execution */ unrecov_fer: bl .save_nvgprs @@ -1146,6 +1162,7 @@ _GLOBAL(do_stab_bolted) ld r12,PACA_EXSLB+EX_R12(r13) ld r13,PACA_EXSLB+EX_R13(r13) rfid + b . /* prevent speculative execution */ /* * r13 points to the PACA, r9 contains the saved CR, @@ -1190,6 +1207,7 @@ _GLOBAL(do_slb_miss) ld r12,PACA_EXSLB+EX_R12(r13) ld r13,PACA_EXSLB+EX_R13(r13) rfid + b . /* prevent speculative execution */ unrecov_slb: EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) @@ -1295,6 +1313,7 @@ _STATIC(mmu_off) mtspr SRR1,r3 sync rfid + b . /* prevent speculative execution */ _GLOBAL(__start_initialization_pSeries) mr r31,r3 /* save parameters */ mr r30,r4 @@ -1777,6 +1796,7 @@ _GLOBAL(__secondary_start) mtspr SRR0,r3 mtspr SRR1,r4 rfid + b . /* prevent speculative execution */ /* * Running with relocation on at this point. All we want to do is @@ -1940,6 +1960,7 @@ _STATIC(start_here_pSeries) mtspr SRR0,r3 mtspr SRR1,r4 rfid + b . /* prevent speculative execution */ #endif /* CONFIG_PPC_PSERIES */ /* This is where all platforms converge execution */ diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 75da7df42b7b..846168746864 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -143,47 +143,6 @@ EXPORT_SYMBOL(synchronize_irq); #endif /* CONFIG_SMP */ -/* XXX Make this into free_irq() - Anton */ - -/* This could be promoted to a real free_irq() ... */ -static int -do_free_irq(int irq, void* dev_id) -{ - irq_desc_t *desc = get_irq_desc(irq); - struct irqaction **p; - unsigned long flags; - - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - - /* Found it - now remove it from the list of entries */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - mask_irq(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - /* Wait to make sure it's not being used on another CPU */ - synchronize_irq(irq); - kfree(action); - return 0; - } - printk("Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - break; - } - return -ENOENT; -} - - int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) @@ -194,8 +153,7 @@ int request_irq(unsigned int irq, if (irq >= NR_IRQS) return -EINVAL; if (!handler) - /* We could implement really free_irq() instead of that... */ - return do_free_irq(irq, dev_id); + return -EINVAL; action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); @@ -222,7 +180,38 @@ EXPORT_SYMBOL(request_irq); void free_irq(unsigned int irq, void *dev_id) { - request_irq(irq, NULL, 0, NULL, dev_id); + irq_desc_t *desc = get_irq_desc(irq); + struct irqaction **p; + unsigned long flags; + + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != dev_id) + continue; + + /* Found it - now remove it from the list of entries */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + mask_irq(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + /* Wait to make sure it's not being used on another CPU */ + synchronize_irq(irq); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + break; + } + return; } EXPORT_SYMBOL(free_irq); diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c index a04037bba220..92bc868f31d9 100644 --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c @@ -600,8 +600,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) BUG(); /* No I/O resource for this PHB? */ if (request_resource(&ioport_resource, res)) - printk(KERN_ERR "Failed to request IO" - "on hose %d\n", 0 /* FIXME */); + printk(KERN_ERR "Failed to request IO on " + "PCI domain %d\n", pci_domain_nr(bus)); + for (i = 0; i < 3; ++i) { res = &hose->mem_resources[i]; @@ -609,8 +610,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) BUG(); /* No memory resource for this PHB? */ bus->resource[i+1] = res; if (res->flags && request_resource(&iomem_resource, res)) - printk(KERN_ERR "Failed to request MEM" - "on hose %d\n", 0 /* FIXME */); + printk(KERN_ERR "Failed to request MEM on " + "PCI domain %d\n", + pci_domain_nr(bus)); } } else if (pci_probe_only && (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h index 50c3bf6a1133..2ca27ccc7795 100644 --- a/arch/ppc64/kernel/pci.h +++ b/arch/ppc64/kernel/pci.h @@ -34,8 +34,8 @@ extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ *******************************************************************/ struct device_node; typedef void *(*traverse_func)(struct device_node *me, void *data); -void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data); -void *traverse_all_pci_devices(traverse_func pre); +void *traverse_pci_devices(struct device_node *start, traverse_func pre, + void *data); void pci_devs_phb_init(void); void pci_fix_bus_sysdata(void); diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c index 7f003be6e062..c771bdc644df 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c @@ -19,8 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include <linux/config.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/delay.h> @@ -40,20 +38,20 @@ #include "pci.h" -/* Traverse_func that inits the PCI fields of the device node. +/* + * Traverse_func that inits the PCI fields of the device node. * NOTE: this *must* be done before read/write config to the device. */ -static void * __init -update_dn_pci_info(struct device_node *dn, void *data) +static void * __init update_dn_pci_info(struct device_node *dn, void *data) { -#ifdef CONFIG_PPC_PSERIES - struct pci_controller *phb = (struct pci_controller *)data; + struct pci_controller *phb = data; u32 *regs; char *device_type = get_property(dn, "device_type", NULL); char *model; dn->phb = phb; - if (device_type && strcmp(device_type, "pci") == 0 && get_property(dn, "class-code", NULL) == 0) { + if (device_type && (strcmp(device_type, "pci") == 0) && + (get_property(dn, "class-code", NULL) == 0)) { /* special case for PHB's. Sigh. */ regs = (u32 *)get_property(dn, "bus-range", NULL); dn->busno = regs[0]; @@ -72,57 +70,47 @@ update_dn_pci_info(struct device_node *dn, void *data) dn->devfn = (regs[0] >> 8) & 0xff; } } -#endif return NULL; } -/****************************************************************** +/* * Traverse a device tree stopping each PCI device in the tree. * This is done depth first. As each node is processed, a "pre" - * function is called, the children are processed recursively, and - * then a "post" function is called. + * function is called and the children are processed recursively. * - * The "pre" and "post" funcs return a value. If non-zero - * is returned from the "pre" func, the traversal stops and this - * value is returned. The return value from "post" is not used. - * This return value is useful when using traverse as - * a method of finding a device. + * The "pre" func returns a value. If non-zero is returned from + * the "pre" func, the traversal stops and this value is returned. + * This return value is useful when using traverse as a method of + * finding a device. * - * NOTE: we do not run the funcs for devices that do not appear to + * NOTE: we do not run the func for devices that do not appear to * be PCI except for the start node which we assume (this is good * because the start node is often a phb which may be missing PCI * properties). * We use the class-code as an indicator. If we run into * one of these nodes we also assume its siblings are non-pci for * performance. - * - ******************************************************************/ -void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data) + */ +void *traverse_pci_devices(struct device_node *start, traverse_func pre, + void *data) { struct device_node *dn, *nextdn; void *ret; - if (pre && (ret = pre(start, data)) != NULL) + if (pre && ((ret = pre(start, data)) != NULL)) return ret; for (dn = start->child; dn; dn = nextdn) { nextdn = NULL; -#ifdef CONFIG_PPC_PSERIES if (get_property(dn, "class-code", NULL)) { - if (pre && (ret = pre(dn, data)) != NULL) + if (pre && ((ret = pre(dn, data)) != NULL)) return ret; - if (dn->child) { + if (dn->child) /* Depth first...do children */ nextdn = dn->child; - } else if (dn->sibling) { + else if (dn->sibling) /* ok, try next sibling instead. */ nextdn = dn->sibling; - } else { - /* no more children or siblings...call "post" */ - if (post) - post(dn, data); - } } -#endif if (!nextdn) { /* Walk up to next valid sibling. */ do { @@ -136,31 +124,35 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, travers return NULL; } -/* Same as traverse_pci_devices except this does it for all phbs. +/* + * Same as traverse_pci_devices except this does it for all phbs. */ -void *traverse_all_pci_devices(traverse_func pre) +static void *traverse_all_pci_devices(traverse_func pre) { - struct pci_controller* phb; + struct pci_controller *phb; void *ret; - for (phb=hose_head;phb;phb=phb->next) - if ((ret = traverse_pci_devices((struct device_node *)phb->arch_data, pre, NULL, phb)) != NULL) + + for (phb = hose_head; phb; phb = phb->next) + if ((ret = traverse_pci_devices(phb->arch_data, pre, phb)) + != NULL) return ret; return NULL; } -/* Traversal func that looks for a <busno,devfcn> value. +/* + * Traversal func that looks for a <busno,devfcn> value. * If found, the device_node is returned (thus terminating the traversal). */ -static void * -is_devfn_node(struct device_node *dn, void *data) +static void *is_devfn_node(struct device_node *dn, void *data) { int busno = ((unsigned long)data >> 8) & 0xff; int devfn = ((unsigned long)data) & 0xff; - return (devfn == dn->devfn && busno == dn->busno) ? dn : NULL; + return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL; } -/* This is the "slow" path for looking up a device_node from a +/* + * This is the "slow" path for looking up a device_node from a * pci_dev. It will hunt for the device under its parent's * phb and then update sysdata for a future fastpath. * @@ -174,14 +166,14 @@ is_devfn_node(struct device_node *dn, void *data) */ struct device_node *fetch_dev_dn(struct pci_dev *dev) { - struct device_node *orig_dn = (struct device_node *)dev->sysdata; + struct device_node *orig_dn = dev->sysdata; struct pci_controller *phb = orig_dn->phb; /* assume same phb as orig_dn */ struct device_node *phb_dn; struct device_node *dn; unsigned long searchval = (dev->bus->number << 8) | dev->devfn; - phb_dn = (struct device_node *)(phb->arch_data); - dn = (struct device_node *)traverse_pci_devices(phb_dn, is_devfn_node, NULL, (void *)searchval); + phb_dn = phb->arch_data; + dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval); if (dn) { dev->sysdata = dn; /* ToDo: call some device init hook here */ @@ -191,25 +183,23 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev) EXPORT_SYMBOL(fetch_dev_dn); -/****************************************************************** +/* * Actually initialize the phbs. * The buswalk on this phb has not happened yet. - ******************************************************************/ -void __init -pci_devs_phb_init(void) + */ +void __init pci_devs_phb_init(void) { /* This must be done first so the device nodes have valid pci info! */ traverse_all_pci_devices(update_dn_pci_info); } -static void __init -pci_fixup_bus_sysdata_list(struct list_head *bus_list) +static void __init pci_fixup_bus_sysdata_list(struct list_head *bus_list) { struct list_head *ln; struct pci_bus *bus; - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { + for (ln = bus_list->next; ln != bus_list; ln = ln->next) { bus = pci_bus_b(ln); if (bus->self) bus->sysdata = bus->self->sysdata; @@ -217,7 +207,7 @@ pci_fixup_bus_sysdata_list(struct list_head *bus_list) } } -/****************************************************************** +/* * Fixup the bus->sysdata ptrs to point to the bus' device_node. * This is done late in pcibios_init(). We do this mostly for * sanity, but pci_dma.c uses these at DMA time so they must be @@ -225,9 +215,8 @@ pci_fixup_bus_sysdata_list(struct list_head *bus_list) * To do this we recurse down the bus hierarchy. Note that PHB's * have bus->self == NULL, but fortunately bus->sysdata is already * correct in this case. - ******************************************************************/ -void __init -pci_fix_bus_sysdata(void) + */ +void __init pci_fix_bus_sysdata(void) { pci_fixup_bus_sysdata_list(&pci_root_buses); } diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c index 3484e4804227..e0ab44dc1fc4 100644 --- a/arch/ppc64/kernel/ptrace32.c +++ b/arch/ppc64/kernel/ptrace32.c @@ -404,7 +404,9 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) break; } - + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned int __user *) data); + break; default: ret = ptrace_request(child, request, addr, data); diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c index 2f92d958fbb4..7bf41f3cab90 100644 --- a/arch/ppc64/kernel/rtc.c +++ b/arch/ppc64/kernel/rtc.c @@ -56,9 +56,7 @@ extern int piranha_simulator; * ioctls. */ -static loff_t rtc_llseek(struct file *file, loff_t offset, int origin); - -static ssize_t rtc_read(struct file *file, char *buf, +static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); static int rtc_ioctl(struct inode *inode, struct file *file, @@ -81,12 +79,7 @@ static const unsigned char days_in_mo[] = * Now all the various file operations that we export. */ -static loff_t rtc_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - -static ssize_t rtc_read(struct file *file, char *buf, +static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { return -EIO; @@ -113,7 +106,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_TIME)) return -EACCES; - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + if (copy_from_user(&rtc_tm, (struct rtc_time __user *)arg, sizeof(struct rtc_time))) return -EFAULT; @@ -147,7 +140,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } case RTC_EPOCH_READ: /* Read the epoch. */ { - return put_user (epoch, (unsigned long *)arg); + return put_user (epoch, (unsigned long __user *)arg); } case RTC_EPOCH_SET: /* Set the epoch. */ { @@ -166,11 +159,12 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, default: return -EINVAL; } - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; + return copy_to_user((void __user *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; } static int rtc_open(struct inode *inode, struct file *file) { + nonseekable_open(inode, file); return 0; } @@ -184,7 +178,7 @@ static int rtc_release(struct inode *inode, struct file *file) */ static struct file_operations rtc_fops = { .owner = THIS_MODULE, - .llseek = rtc_llseek, + .llseek = no_llseek, .read = rtc_read, .ioctl = rtc_ioctl, .open = rtc_open, diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c index 057c1382ed83..41b34932f14a 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/ppc64/kernel/sysfs.c @@ -208,8 +208,8 @@ static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \ return sprintf(buf, "%lx\n", val); \ } \ -static ssize_t store_##NAME(struct sys_device *dev, const char *buf, \ - size_t count) \ +static ssize_t __attribute_used__ \ + store_##NAME(struct sys_device *dev, const char *buf, size_t count) \ { \ struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ unsigned long val; \ diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index a881d25f1f13..c9f950c2cea3 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -27,7 +27,6 @@ #include <asm/naca.h> #include <asm/rtas.h> #include <asm/xics.h> -#include <asm/ppcdebug.h> #include <asm/hvcall.h> #include <asm/machdep.h> @@ -239,13 +238,13 @@ static unsigned int real_irq_to_virt(unsigned int real_irq) #ifdef CONFIG_SMP static int get_irq_server(unsigned int irq) { - cpumask_t cpumask = irq_affinity[irq]; - cpumask_t tmp = CPU_MASK_NONE; unsigned int server; #ifdef CONFIG_IRQ_ALL_CPUS /* For the moment only implement delivery to all cpus or one cpu */ if (smp_threads_ready) { + cpumask_t cpumask = irq_affinity[irq]; + cpumask_t tmp = CPU_MASK_NONE; if (cpus_equal(cpumask, CPU_MASK_ALL)) { server = default_distrib_server; } else { @@ -286,7 +285,7 @@ static void xics_enable_irq(unsigned int virq) call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, DEFAULT_PRIORITY); if (call_status != 0) { - printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_set_xive " + printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive " "returned %x\n", irq, call_status); return; } @@ -294,7 +293,7 @@ static void xics_enable_irq(unsigned int virq) /* Now unmask the interrupt (often a no-op) */ call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); if (call_status != 0) { - printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_int_on " + printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on " "returned %x\n", irq, call_status); return; } @@ -310,7 +309,7 @@ static void xics_disable_real_irq(unsigned int irq) call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); if (call_status != 0) { - printk(KERN_ERR "xics_disable_real_irq: irq=%x: " + printk(KERN_ERR "xics_disable_real_irq: irq=%d: " "ibm_int_off returned %x\n", irq, call_status); return; } @@ -319,7 +318,7 @@ static void xics_disable_real_irq(unsigned int irq) /* Have to set XIVE to 0xff to be able to remove a slot */ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff); if (call_status != 0) { - printk(KERN_ERR "xics_disable_irq: irq=%x: ibm_set_xive(0xff)" + printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)" " returned %x\n", irq, call_status); return; } @@ -356,8 +355,6 @@ static void xics_mask_and_ack_irq(unsigned int irq) } } -extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); - int xics_get_irq(struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); @@ -384,7 +381,7 @@ int xics_get_irq(struct pt_regs *regs) if (irq == NO_IRQ) irq = real_irq_to_virt_slowpath(vec); if (irq == NO_IRQ) { - printk(KERN_ERR "Interrupt 0x%x (real) is invalid," + printk(KERN_ERR "Interrupt %d (real) is invalid," " disabling it.\n", vec); xics_disable_real_irq(vec); } else @@ -395,8 +392,6 @@ int xics_get_irq(struct pt_regs *regs) #ifdef CONFIG_SMP -extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; - irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); @@ -469,11 +464,9 @@ void xics_init_IRQ(void) ibm_int_off = rtas_token("ibm,int-off"); np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation"); - if (!np) { - printk(KERN_WARNING "Can't find Interrupt Presentation\n"); - udbg_printf("Can't find Interrupt Presentation\n"); - while (1); - } + if (!np) + panic("xics_init_IRQ: can't find interrupt presentation"); + nextnode: ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", NULL); if (ireg) { @@ -484,11 +477,8 @@ nextnode: } ireg = (uint *)get_property(np, "reg", &ilen); - if (!ireg) { - printk(KERN_WARNING "Can't find Interrupt Reg Property\n"); - udbg_printf("Can't find Interrupt Reg Property\n"); - while (1); - } + if (!ireg) + panic("xics_init_IRQ: can't find interrupt reg property"); while (ilen) { inodes[indx].addr = (unsigned long long)*ireg++ << 32; @@ -528,16 +518,14 @@ nextnode: np = of_find_node_by_type(NULL, "interrupt-controller"); if (!np) { - printk(KERN_WARNING "xics: no ISA Interrupt Controller\n"); + printk(KERN_WARNING "xics: no ISA interrupt controller\n"); xics_irq_8259_cascade_real = -1; xics_irq_8259_cascade = -1; } else { ireg = (uint *) get_property(np, "interrupts", NULL); - if (!ireg) { - printk(KERN_WARNING "Can't find ISA Interrupts Property\n"); - udbg_printf("Can't find ISA Interrupts Property\n"); - while (1); - } + if (!ireg) + panic("xics_init_IRQ: can't find ISA interrupts property"); + xics_irq_8259_cascade_real = *ireg; xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); @@ -558,13 +546,8 @@ nextnode: xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE); #endif /* CONFIG_SMP */ -#ifdef CONFIG_PPC_PSERIES - /* actually iSeries does not use any of xics...but it has link dependencies - * for now, except this new one... - */ } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { ops = &pSeriesLP_ops; -#endif } xics_8259_pic.enable = i8259_pic.enable; @@ -590,7 +573,8 @@ static int __init xics_setup_i8259(void) xics_irq_8259_cascade != -1) { if (request_irq(irq_offset_up(xics_irq_8259_cascade), no_action, 0, "8259 cascade", NULL)) - printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); + printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 " + "cascade\n"); i8259_init(); } return 0; @@ -643,7 +627,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) irq, newmask, xics_status[1]); if (status) { - printk(KERN_ERR "xics_set_affinity irq=%d ibm,set-xive " + printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive " "returns %d\n", irq, status); return; } @@ -723,7 +707,7 @@ void xics_migrate_irqs_away(void) status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, xics_status[0], xics_status[1]); if (status) - printk(KERN_ERR "migrate_irqs_away irq=%d " + printk(KERN_ERR "migrate_irqs_away: irq=%d " "ibm,set-xive returns %d\n", virq, status); diff --git a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S index 367cb7dec858..4b3dfe091c1f 100644 --- a/arch/ppc64/mm/slb_low.S +++ b/arch/ppc64/mm/slb_low.S @@ -37,9 +37,6 @@ _GLOBAL(slb_allocate) * a free slot first but that took too long. Unfortunately we * dont have any LRU information to help us choose a slot. */ - srdi r9,r1,27 - ori r9,r9,1 /* mangle SP for later compare */ - ld r10,PACASTABRR(r13) 3: addi r10,r10,1 @@ -48,18 +45,32 @@ _GLOBAL(slb_allocate) blt+ 4f li r10,SLB_NUM_BOLTED -4: - slbmfee r11,r10 - /* Don't throw out the segment for our kernel stack. Since we + + /* + * Never cast out the segment for our kernel stack. Since we * dont invalidate the ERAT we could have a valid translation - * for the kernel stack during the first part of exception - * exit which gets invalidated due to a tlbie from another cpu - * at a non recoverable point (after setting srr0/1) - Anton - * + * for the kernel stack during the first part of exception exit + * which gets invalidated due to a tlbie from another cpu at a + * non recoverable point (after setting srr0/1) - Anton + */ +4: slbmfee r11,r10 + srdi r11,r11,27 + /* + * Use paca->ksave as the value of the kernel stack pointer, + * because this is valid at all times. * The >> 27 (rather than >> 28) is so that the LSB is the * valid bit - this way we check valid and ESID in one compare. + * In order to completely close the tiny race in the context + * switch (between updating r1 and updating paca->ksave), + * we check against both r1 and paca->ksave. */ - srdi r11,r11,27 + srdi r9,r1,27 + ori r9,r9,1 /* mangle SP for later compare */ + cmpd r11,r9 + beq- 3b + ld r9,PACAKSAVE(r13) + srdi r9,r9,27 + ori r9,r9,1 cmpd r11,r9 beq- 3b diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 5906668177f0..ce8cb18b90a4 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -181,6 +181,15 @@ config QDIO_PERF_STATS If unsure, say N. +config QDIO_DEBUG + bool "Extended debugging information" + depends on QDIO + help + Say Y here to get extended debugging output in /proc/s390dbf/qdio... + Warning: this option reduces the performance of the QDIO module. + + If unsure, say N. + comment "Misc" config PREEMPT diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index d957683d6165..3589f48ded47 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <asm/uaccess.h> #include <asm/io.h> +#include <asm/smp.h> #include <linux/interrupt.h> #include <linux/proc_fs.h> #include <linux/page-flags.h> @@ -87,11 +88,11 @@ struct appldata_parameter_list { */ static const char appldata_proc_name[APPLDATA_PROC_NAME_LENGTH] = "appldata"; static int appldata_timer_handler(ctl_table *ctl, int write, struct file *filp, - void __user *buffer, size_t *lenp); + void __user *buffer, size_t *lenp, loff_t *ppos); static int appldata_interval_handler(ctl_table *ctl, int write, struct file *filp, void __user *buffer, - size_t *lenp); + size_t *lenp, loff_t *ppos); static struct ctl_table_header *appldata_sysctl_header; static struct ctl_table appldata_table[] = { @@ -314,12 +315,12 @@ __appldata_vtimer_setup(int cmd) */ static int appldata_timer_handler(ctl_table *ctl, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int len; char buf[2]; - if (!*lenp || filp->f_pos) { + if (!*lenp || *ppos) { *lenp = 0; return 0; } @@ -342,7 +343,7 @@ appldata_timer_handler(ctl_table *ctl, int write, struct file *filp, spin_unlock(&appldata_timer_lock); out: *lenp = len; - filp->f_pos += len; + *ppos += len; return 0; } @@ -354,12 +355,12 @@ out: */ static int appldata_interval_handler(ctl_table *ctl, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int len, interval; char buf[16]; - if (!*lenp || filp->f_pos) { + if (!*lenp || *ppos) { *lenp = 0; return 0; } @@ -390,7 +391,7 @@ appldata_interval_handler(ctl_table *ctl, int write, struct file *filp, interval); out: *lenp = len; - filp->f_pos += len; + *ppos += len; return 0; } @@ -402,7 +403,7 @@ out: */ static int appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { struct appldata_ops *ops = NULL, *tmp_ops; int rc, len, found; @@ -428,7 +429,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, } spin_unlock_bh(&appldata_ops_lock); - if (!*lenp || filp->f_pos) { + if (!*lenp || *ppos) { *lenp = 0; module_put(ops->owner); return 0; @@ -487,7 +488,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, spin_unlock_bh(&appldata_ops_lock); out: *lenp = len; - filp->f_pos += len; + *ppos += len; module_put(ops->owner); return 0; } diff --git a/arch/s390/defconfig b/arch/s390/defconfig index ec342423d0d9..84650d326864 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -11,7 +11,6 @@ CONFIG_UID16=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y # # General setup @@ -71,6 +70,7 @@ CONFIG_MATHEMU=y CONFIG_MACHCHK_WARNING=y CONFIG_QDIO=y # CONFIG_QDIO_PERF_STATS is not set +# CONFIG_QDIO_DEBUG is not set # # Misc @@ -93,6 +93,7 @@ CONFIG_NO_IDLE_HZ_INIT=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set @@ -511,7 +512,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_AES_GENERIC is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index a0e6722b6981..48209a81ae9f 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h @@ -214,4 +214,7 @@ struct sigevent32 { } _sigev_un; }; +extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from); +extern int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from); + #endif /* _ASM_S390X_S390_H */ diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 70c83cb56c3e..e8c8b2fe7af5 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -106,6 +106,53 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from) return err; } +int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from) +{ + int err; + u32 tmp; + + if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32))) + return -EFAULT; + + err = __get_user(to->si_signo, &from->si_signo); + err |= __get_user(to->si_errno, &from->si_errno); + err |= __get_user(to->si_code, &from->si_code); + + if (from->si_code < 0) + err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); + else { + switch (from->si_code >> 16) { + case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ + case __SI_MESGQ >> 16: + err |= __get_user(to->si_int, &from->si_int); + /* fallthrough */ + case __SI_KILL >> 16: + err |= __get_user(to->si_pid, &from->si_pid); + err |= __get_user(to->si_uid, &from->si_uid); + break; + case __SI_CHLD >> 16: + err |= __get_user(to->si_pid, &from->si_pid); + err |= __get_user(to->si_uid, &from->si_uid); + err |= __get_user(to->si_utime, &from->si_utime); + err |= __get_user(to->si_stime, &from->si_stime); + err |= __get_user(to->si_status, &from->si_status); + break; + case __SI_FAULT >> 16: + err |= __get_user(tmp, &from->si_addr); + to->si_addr = (void *)(u64) (tmp & PSW32_ADDR_INSN); + break; + case __SI_POLL >> 16: + case __SI_TIMER >> 16: + err |= __get_user(to->si_band, &from->si_band); + err |= __get_user(to->si_fd, &from->si_fd); + break; + default: + break; + } + } + return err; +} + /* * Atomically swap in the new signal mask, and wait for a signal. */ diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index a0ddc4f7d9e5..26b89e55d9c1 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -553,6 +553,19 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned int); } return 0; + case PTRACE_GETEVENTMSG: + return put_user((__u32) child->ptrace_message, + (unsigned int __user *) data); + case PTRACE_GETSIGINFO: + if (child->last_siginfo == NULL) + return -EINVAL; + return copy_siginfo_to_user32((siginfo_t32 __user *) data, + child->last_siginfo); + case PTRACE_SETSIGINFO: + if (child->last_siginfo == NULL) + return -EINVAL; + return copy_siginfo_from_user32(child->last_siginfo, + (siginfo_t32 __user *) data); } return ptrace_request(child, request, addr, data); } diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 72d4f1e6ff7b..cb2950301061 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -19,6 +19,7 @@ #include <asm/pgalloc.h> #include <asm/uaccess.h> +#include <asm/smp.h> #include "../../../drivers/s390/net/smsgiucv.h" @@ -255,13 +256,13 @@ static struct ctl_table cmm_table[]; static int cmm_pages_handler(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp) + void *buffer, size_t *lenp, loff_t *ppos) { char buf[16], *p; long pages; int len; - if (!*lenp || (filp->f_pos && !write)) { + if (!*lenp || (*ppos && !write)) { *lenp = 0; return 0; } @@ -290,19 +291,19 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp, return -EFAULT; } *lenp = len; - filp->f_pos += len; + *ppos += len; return 0; } static int cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp) + void *buffer, size_t *lenp, loff_t *ppos) { char buf[64], *p; long pages, seconds; int len; - if (!*lenp || (filp->f_pos && !write)) { + if (!*lenp || (*ppos && !write)) { *lenp = 0; return 0; } @@ -327,7 +328,7 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp, return -EFAULT; } *lenp = len; - filp->f_pos += len; + *ppos += len; return 0; } diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 79d52a1dd356..7d0688aa6833 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -83,6 +83,7 @@ config HW_CONSOLE config SMP bool "Symmetric multi-processing support (does not work on sun4/sun4c)" + depends on BROKEN ---help--- This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -221,6 +222,7 @@ config SUN_PM config SUN4 bool "Support for SUN4 machines (disables SUN4[CDM] support)" + depends on !SMP help Say Y here if, and only if, your machine is a sun4. Note that a kernel compiled with this option will run only on sun4. diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index fd065fb3e00c..46591a15eb43 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -45,6 +45,7 @@ int smp_activated = 0; volatile int __cpu_number_map[NR_CPUS]; volatile int __cpu_logical_map[NR_CPUS]; cycles_t cacheflush_time = 0; /* XXX */ +unsigned long cache_decay_ticks = 100; cpumask_t cpu_online_map = CPU_MASK_NONE; cpumask_t phys_cpu_present_map = CPU_MASK_NONE; @@ -203,6 +204,11 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) } } +void smp_reschedule_irq(void) +{ + set_need_resched(); +} + void smp_flush_page_to_ram(unsigned long page) { /* Current theory is that those who call this are the one's diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index e5e134903570..9f659c2f4196 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -43,7 +43,6 @@ extern ctxd_t *srmmu_ctx_table_phys; extern void calibrate_delay(void); extern volatile int smp_processors_ready; -extern unsigned long cpu_present_map; extern int smp_num_cpus; static int smp_highest_cpu; extern int smp_threads_ready; @@ -100,8 +99,6 @@ void __init smp4d_callin(void) * the SMP initialization the master will be just allowed * to call the scheduler code. */ - init_idle(); - /* Get our local ticker going. */ smp_setup_percpu_timer(); @@ -152,7 +149,6 @@ void __init smp4d_callin(void) extern int cpu_idle(void *unused); extern void init_IRQ(void); extern void cpu_panic(void); -extern int start_secondary(void *unused); /* * Cycle through the processors asking the PROM to start each one. @@ -174,12 +170,12 @@ void __init smp4d_boot_cpus(void) current_set[0] = NULL; local_irq_enable(); - cpu_present_map = 0; + cpus_clear(cpu_present_map); /* XXX This whole thing has to go. See sparc64. */ for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) - cpu_present_map |= (1<<mid); - SMP_PRINTK(("cpu_present_map %08lx\n", cpu_present_map)); + cpu_set(mid, cpu_present_map); + SMP_PRINTK(("cpu_present_map %08lx\n", cpus_addr(cpu_present_map)[0])); for(i=0; i < NR_CPUS; i++) __cpu_number_map[i] = -1; for(i=0; i < NR_CPUS; i++) @@ -197,7 +193,7 @@ void __init smp4d_boot_cpus(void) if(i == boot_cpu_id) continue; - if(cpu_present_map & (1 << i)) { + if (cpu_isset(i, cpu_present_map)) { extern unsigned long sun4d_cpu_startup; unsigned long *entry = &sun4d_cpu_startup; struct task_struct *p; @@ -254,19 +250,19 @@ void __init smp4d_boot_cpus(void) } } if(!(cpu_callin_map[i])) { - cpu_present_map &= ~(1 << i); + cpu_clear(i, cpu_present_map); __cpu_number_map[i] = -1; } } local_flush_cache_all(); if(cpucount == 0) { printk("Error: only one Processor found.\n"); - cpu_present_map = (1 << hard_smp4d_processor_id()); + cpu_present_map = cpumask_of_cpu(hard_smp4d_processor_id()); } else { unsigned long bogosum = 0; for(i = 0; i < NR_CPUS; i++) { - if(cpu_present_map & (1 << i)) { + if (cpu_isset(i, cpu_present_map)) { bogosum += cpu_data(i).udelay_val; smp_highest_cpu = i; } @@ -346,12 +342,13 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, /* Init receive/complete mapping, plus fire the IPI's off. */ { - register unsigned long mask; + cpumask_t mask; register int i; - mask = (cpu_present_map & ~(1 << hard_smp4d_processor_id())); + mask = cpumask_of_cpu(hard_smp4d_processor_id()); + cpus_andnot(mask, cpu_present_map, mask); for(i = 0; i <= high; i++) { - if(mask & (1 << i)) { + if (cpu_isset(i, mask)) { ccall_info.processors_in[i] = 0; ccall_info.processors_out[i] = 0; sun4d_send_ipi(i, IRQ_CROSS_CALL); @@ -498,11 +495,11 @@ void __init sun4d_init_smp(void) t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); /* And set btfixup... */ - BTFIXUPSET_BLACKBOX(smp_processor_id, smp4d_blackbox_id); + BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id); BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); for (i = 0; i < NR_CPUS; i++) { ccall_info.processors_in[i] = 1; diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 01587b160819..f2fc64edc773 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -95,8 +95,6 @@ void __init smp4m_callin(void) * the SMP initialization the master will be just allowed * to call the scheduler code. */ - init_idle(); - /* Allow master to continue. */ swap((unsigned long *)&cpu_callin_map[cpuid], 1); @@ -126,7 +124,6 @@ void __init smp4m_callin(void) extern int cpu_idle(void *unused); extern void init_IRQ(void); extern void cpu_panic(void); -extern int start_secondary(void *unused); /* * Cycle through the processors asking the PROM to start each one. @@ -460,9 +457,9 @@ void __init smp4m_blackbox_current(unsigned *addr) void __init sun4m_init_smp(void) { - BTFIXUPSET_BLACKBOX(smp_processor_id, smp4m_blackbox_id); + BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id); BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current); BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); } diff --git a/arch/sparc/kernel/trampoline.S b/arch/sparc/kernel/trampoline.S index 1db353f4668e..2dcdaa1fd8cd 100644 --- a/arch/sparc/kernel/trampoline.S +++ b/arch/sparc/kernel/trampoline.S @@ -88,8 +88,6 @@ cpu3_startup: .align 4 smp_do_cpu_idle: - call init_idle - nop call cpu_idle mov 0, %o0 diff --git a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S index ed91f1e8c4c4..eb6a9e7595df 100644 --- a/arch/sparc/lib/memcpy.S +++ b/arch/sparc/lib/memcpy.S @@ -42,124 +42,124 @@ x: #endif /* Both these macros have to start with exactly the same insn */ -#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - ldd [%src + offset + 0x10], %t4; \ - ldd [%src + offset + 0x18], %t6; \ - st %t0, [%dst + offset + 0x00]; \ - st %t1, [%dst + offset + 0x04]; \ - st %t2, [%dst + offset + 0x08]; \ - st %t3, [%dst + offset + 0x0c]; \ - st %t4, [%dst + offset + 0x10]; \ - st %t5, [%dst + offset + 0x14]; \ - st %t6, [%dst + offset + 0x18]; \ - st %t7, [%dst + offset + 0x1c]; - -#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - ldd [%src + offset + 0x10], %t4; \ - ldd [%src + offset + 0x18], %t6; \ - std %t0, [%dst + offset + 0x00]; \ - std %t2, [%dst + offset + 0x08]; \ - std %t4, [%dst + offset + 0x10]; \ - std %t6, [%dst + offset + 0x18]; - -#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ldd [%src - offset - 0x10], %t0; \ - ldd [%src - offset - 0x08], %t2; \ - st %t0, [%dst - offset - 0x10]; \ - st %t1, [%dst - offset - 0x0c]; \ - st %t2, [%dst - offset - 0x08]; \ - st %t3, [%dst - offset - 0x04]; - -#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ldd [%src - offset - 0x10], %t0; \ - ldd [%src - offset - 0x08], %t2; \ - std %t0, [%dst - offset - 0x10]; \ - std %t2, [%dst - offset - 0x08]; - -#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ - ldub [%src - offset - 0x02], %t0; \ - ldub [%src - offset - 0x01], %t1; \ - stb %t0, [%dst - offset - 0x02]; \ - stb %t1, [%dst - offset - 0x01]; +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + ldd [%src + (offset) + 0x10], %t4; \ + ldd [%src + (offset) + 0x18], %t6; \ + st %t0, [%dst + (offset) + 0x00]; \ + st %t1, [%dst + (offset) + 0x04]; \ + st %t2, [%dst + (offset) + 0x08]; \ + st %t3, [%dst + (offset) + 0x0c]; \ + st %t4, [%dst + (offset) + 0x10]; \ + st %t5, [%dst + (offset) + 0x14]; \ + st %t6, [%dst + (offset) + 0x18]; \ + st %t7, [%dst + (offset) + 0x1c]; + +#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + ldd [%src + (offset) + 0x10], %t4; \ + ldd [%src + (offset) + 0x18], %t6; \ + std %t0, [%dst + (offset) + 0x00]; \ + std %t2, [%dst + (offset) + 0x08]; \ + std %t4, [%dst + (offset) + 0x10]; \ + std %t6, [%dst + (offset) + 0x18]; + +#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - (offset) - 0x10], %t0; \ + ldd [%src - (offset) - 0x08], %t2; \ + st %t0, [%dst - (offset) - 0x10]; \ + st %t1, [%dst - (offset) - 0x0c]; \ + st %t2, [%dst - (offset) - 0x08]; \ + st %t3, [%dst - (offset) - 0x04]; + +#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - (offset) - 0x10], %t0; \ + ldd [%src - (offset) - 0x08], %t2; \ + std %t0, [%dst - (offset) - 0x10]; \ + std %t2, [%dst - (offset) - 0x08]; + +#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src - (offset) - 0x02], %t0; \ + ldub [%src - (offset) - 0x01], %t1; \ + stb %t0, [%dst - (offset) - 0x02]; \ + stb %t1, [%dst - (offset) - 0x01]; /* Both these macros have to start with exactly the same insn */ -#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src - offset - 0x20], %t0; \ - ldd [%src - offset - 0x18], %t2; \ - ldd [%src - offset - 0x10], %t4; \ - ldd [%src - offset - 0x08], %t6; \ - st %t0, [%dst - offset - 0x20]; \ - st %t1, [%dst - offset - 0x1c]; \ - st %t2, [%dst - offset - 0x18]; \ - st %t3, [%dst - offset - 0x14]; \ - st %t4, [%dst - offset - 0x10]; \ - st %t5, [%dst - offset - 0x0c]; \ - st %t6, [%dst - offset - 0x08]; \ - st %t7, [%dst - offset - 0x04]; - -#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src - offset - 0x20], %t0; \ - ldd [%src - offset - 0x18], %t2; \ - ldd [%src - offset - 0x10], %t4; \ - ldd [%src - offset - 0x08], %t6; \ - std %t0, [%dst - offset - 0x20]; \ - std %t2, [%dst - offset - 0x18]; \ - std %t4, [%dst - offset - 0x10]; \ - std %t6, [%dst - offset - 0x08]; - -#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - st %t0, [%dst + offset + 0x00]; \ - st %t1, [%dst + offset + 0x04]; \ - st %t2, [%dst + offset + 0x08]; \ - st %t3, [%dst + offset + 0x0c]; - -#define RMOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ - ldub [%src + offset + 0x00], %t0; \ - ldub [%src + offset + 0x01], %t1; \ - stb %t0, [%dst + offset + 0x00]; \ - stb %t1, [%dst + offset + 0x01]; - -#define SMOVE_CHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - srl %t0, shir, %t5; \ - srl %t1, shir, %t6; \ - sll %t0, shil, %t0; \ - or %t5, %prev, %t5; \ - sll %t1, shil, %prev; \ - or %t6, %t0, %t0; \ - srl %t2, shir, %t1; \ - srl %t3, shir, %t6; \ - sll %t2, shil, %t2; \ - or %t1, %prev, %t1; \ - std %t4, [%dst + offset + offset2 - 0x04]; \ - std %t0, [%dst + offset + offset2 + 0x04]; \ - sll %t3, shil, %prev; \ +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src - (offset) - 0x20], %t0; \ + ldd [%src - (offset) - 0x18], %t2; \ + ldd [%src - (offset) - 0x10], %t4; \ + ldd [%src - (offset) - 0x08], %t6; \ + st %t0, [%dst - (offset) - 0x20]; \ + st %t1, [%dst - (offset) - 0x1c]; \ + st %t2, [%dst - (offset) - 0x18]; \ + st %t3, [%dst - (offset) - 0x14]; \ + st %t4, [%dst - (offset) - 0x10]; \ + st %t5, [%dst - (offset) - 0x0c]; \ + st %t6, [%dst - (offset) - 0x08]; \ + st %t7, [%dst - (offset) - 0x04]; + +#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src - (offset) - 0x20], %t0; \ + ldd [%src - (offset) - 0x18], %t2; \ + ldd [%src - (offset) - 0x10], %t4; \ + ldd [%src - (offset) - 0x08], %t6; \ + std %t0, [%dst - (offset) - 0x20]; \ + std %t2, [%dst - (offset) - 0x18]; \ + std %t4, [%dst - (offset) - 0x10]; \ + std %t6, [%dst - (offset) - 0x08]; + +#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + st %t0, [%dst + (offset) + 0x00]; \ + st %t1, [%dst + (offset) + 0x04]; \ + st %t2, [%dst + (offset) + 0x08]; \ + st %t3, [%dst + (offset) + 0x0c]; + +#define RMOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src + (offset) + 0x00], %t0; \ + ldub [%src + (offset) + 0x01], %t1; \ + stb %t0, [%dst + (offset) + 0x00]; \ + stb %t1, [%dst + (offset) + 0x01]; + +#define SMOVE_CHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + srl %t0, shir, %t5; \ + srl %t1, shir, %t6; \ + sll %t0, shil, %t0; \ + or %t5, %prev, %t5; \ + sll %t1, shil, %prev; \ + or %t6, %t0, %t0; \ + srl %t2, shir, %t1; \ + srl %t3, shir, %t6; \ + sll %t2, shil, %t2; \ + or %t1, %prev, %t1; \ + std %t4, [%dst + (offset) + (offset2) - 0x04]; \ + std %t0, [%dst + (offset) + (offset2) + 0x04]; \ + sll %t3, shil, %prev; \ or %t6, %t2, %t4; -#define SMOVE_ALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - srl %t0, shir, %t4; \ - srl %t1, shir, %t5; \ - sll %t0, shil, %t6; \ - or %t4, %prev, %t0; \ - sll %t1, shil, %prev; \ - or %t5, %t6, %t1; \ - srl %t2, shir, %t4; \ - srl %t3, shir, %t5; \ - sll %t2, shil, %t6; \ - or %t4, %prev, %t2; \ - sll %t3, shil, %prev; \ - or %t5, %t6, %t3; \ - std %t0, [%dst + offset + offset2 + 0x00]; \ - std %t2, [%dst + offset + offset2 + 0x08]; +#define SMOVE_ALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + srl %t0, shir, %t4; \ + srl %t1, shir, %t5; \ + sll %t0, shil, %t6; \ + or %t4, %prev, %t0; \ + sll %t1, shil, %prev; \ + or %t5, %t6, %t1; \ + srl %t2, shir, %t4; \ + srl %t3, shir, %t5; \ + sll %t2, shil, %t6; \ + or %t4, %prev, %t2; \ + sll %t3, shil, %prev; \ + or %t5, %t6, %t3; \ + std %t0, [%dst + (offset) + (offset2) + 0x00]; \ + std %t2, [%dst + (offset) + (offset2) + 0x08]; .text .align 4 diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 45469d2f6e1c..c18475eaaee1 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1697,9 +1697,7 @@ static void turbosparc_flush_cache_mm(struct mm_struct *mm) static void turbosparc_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - struct mm_struct *mm = vma->vm_mm; - - FLUSH_BEGIN(mm) + FLUSH_BEGIN(vma->vm_mm) flush_user_windows(); turbosparc_idflash_clear(); FLUSH_END @@ -1750,9 +1748,7 @@ static void turbosparc_flush_tlb_mm(struct mm_struct *mm) static void turbosparc_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - struct mm_struct *mm = vma->vm_mm; - - FLUSH_BEGIN(mm) + FLUSH_BEGIN(vma->vm_mm) srmmu_flush_whole_tlb(); FLUSH_END } diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index e3f3cddeadaa..147ec19f6bb9 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -82,7 +82,7 @@ static int harddog_open(struct inode *inode, struct file *file) timer_alive = 1; unlock_kernel(); - return 0; + return nonseekable_open(inode, file); } extern void stop_watchdog(int in_fd, int out_fd); @@ -108,10 +108,6 @@ extern int ping_watchdog(int fd); static ssize_t harddog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* * Refresh the timer. */ diff --git a/crypto/Kconfig b/crypto/Kconfig index de13d3ffb7fe..9cf82c159c19 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -120,7 +120,7 @@ config CRYPTO_SERPENT config CRYPTO_AES tristate "AES cipher algorithms" - depends on CRYPTO + depends on CRYPTO && !(X86 && !X86_64) help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. @@ -138,6 +138,26 @@ config CRYPTO_AES See http://csrc.nist.gov/CryptoToolkit/aes/ for more information. +config CRYPTO_AES_586 + tristate "AES cipher algorithms (i586)" + depends on CRYPTO && (X86 && !X86_64) + help + AES cipher algorithms (FIPS-197). AES uses the Rijndael + algorithm. + + Rijndael appears to be consistently a very good performer in + both hardware and software across a wide range of computing + environments regardless of its use in feedback or non-feedback + modes. Its key setup time is excellent, and its key agility is + good. Rijndael's very low memory requirements make it very well + suited for restricted-space environments, in which it also + demonstrates excellent performance. Rijndael's operations are + among the easiest to defend against power and timing attacks. + + The AES specifies three key sizes: 128, 192 and 256 bits + + See http://csrc.nist.gov/encryption/aes/ for more information. + config CRYPTO_CAST5 tristate "CAST5 (CAST-128) cipher algorithm" depends on CRYPTO diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index a64ef154db08..7eb20609694e 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -345,7 +345,7 @@ acpi_system_write_alarm ( acpi_set_register(ACPI_BITREG_RT_CLOCK_ENABLE, 1, ACPI_MTX_LOCK); - file->f_pos += count; + *ppos += count; result = 0; end: diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index afaed937f24b..4d10ac66001a 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -632,6 +632,8 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth) return 0; } +EXPORT_SYMBOL(blk_queue_resize_tags); + /** * blk_queue_end_tag - end tag operations for a request * @q: the request queue for the device diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index f57dd9d77f23..03df60080650 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -90,7 +90,7 @@ static int sg_set_reserved_size(request_queue_t *q, int __user *p) if (size < 0) return -EINVAL; if (size > (q->max_sectors << 9)) - return -EINVAL; + size = q->max_sectors << 9; q->sg_reserved_size = size; return 0; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 9faa8a08a836..d1df4adff1a9 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -302,7 +302,7 @@ static int hci_vhci_chr_open(struct inode *inode, struct file * file) } file->private_data = hci_vhci; - return 0; + return nonseekable_open(inode, file); } static int hci_vhci_chr_close(struct inode *inode, struct file *file) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index bfdc4d24a2c7..360d4b64a42e 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2933,13 +2933,13 @@ struct cdrom_sysctl_settings { } cdrom_sysctl_settings; int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int pos; struct cdrom_device_info *cdi; char *info = cdrom_sysctl_settings.info; - if (!*lenp || (filp->f_pos && !write)) { + if (!*lenp || (*ppos && !write)) { *lenp = 0; return 0; } @@ -3028,7 +3028,7 @@ int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp, strcpy(info+pos,"\n\n"); - return proc_dostring(ctl, write, filp, buffer, lenp); + return proc_dostring(ctl, write, filp, buffer, lenp, ppos); } /* Unfortunately, per device settings are not implemented through @@ -3060,13 +3060,13 @@ void cdrom_update_settings(void) } static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = ctl->data; int val = *valp; int ret; - ret = proc_dointvec(ctl, write, filp, buffer, lenp); + ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && *valp != val) { diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 4171ca18b629..e2c4ecac7381 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -213,15 +213,11 @@ static void ds1620_read_state(struct therm *therm) } static ssize_t -ds1620_read(struct file *file, char *buf, size_t count, loff_t *ptr) +ds1620_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) { signed int cur_temp; signed char cur_temp_degF; - /* Can't seek (pread) on this device */ - if (ptr != &file->f_pos) - return -ESPIPE; - cur_temp = cvt_9_to_int(ds1620_in(THERM_READ_TEMP, 9)) >> 1; /* convert to Fahrenheit, as per wdt.c */ @@ -237,8 +233,14 @@ static int ds1620_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct therm therm; + union { + struct therm __user *therm; + int __user *i; + } uarg; int i; + uarg.i = (int __user *)arg; + switch(cmd) { case CMD_SET_THERMOSTATE: case CMD_SET_THERMOSTATE2: @@ -246,11 +248,11 @@ ds1620_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned return -EPERM; if (cmd == CMD_SET_THERMOSTATE) { - if (get_user(therm.hi, (int *)arg)) + if (get_user(therm.hi, uarg.i)) return -EFAULT; therm.lo = therm.hi - 3; } else { - if (copy_from_user(&therm, (void *)arg, sizeof(therm))) + if (copy_from_user(&therm, uarg.therm, sizeof(therm))) return -EFAULT; } @@ -268,10 +270,10 @@ ds1620_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned therm.hi >>= 1; if (cmd == CMD_GET_THERMOSTATE) { - if (put_user(therm.hi, (int *)arg)) + if (put_user(therm.hi, uarg.i)) return -EFAULT; } else { - if (copy_to_user((void *)arg, &therm, sizeof(therm))) + if (copy_to_user(uarg.therm, &therm, sizeof(therm))) return -EFAULT; } break; @@ -283,23 +285,23 @@ ds1620_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned if (cmd == CMD_GET_TEMPERATURE) i >>= 1; - return put_user(i, (int *)arg) ? -EFAULT : 0; + return put_user(i, uarg.i) ? -EFAULT : 0; case CMD_GET_STATUS: i = ds1620_in(THERM_READ_CONFIG, 8) & 0xe3; - return put_user(i, (int *)arg) ? -EFAULT : 0; + return put_user(i, uarg.i) ? -EFAULT : 0; case CMD_GET_FAN: i = netwinder_get_fan(); - return put_user(i, (int *)arg) ? -EFAULT : 0; + return put_user(i, uarg.i) ? -EFAULT : 0; case CMD_SET_FAN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (get_user(i, (int *)arg)) + if (get_user(i, uarg.i)) return -EFAULT; netwinder_set_fan(i); @@ -338,6 +340,7 @@ static struct proc_dir_entry *proc_therm_ds1620; static struct file_operations ds1620_fops = { .owner = THIS_MODULE, + .open = nonseekable_open, .read = ds1620_read, .ioctl = ds1620_ioctl, }; @@ -380,7 +383,7 @@ static int __init ds1620_init(void) return ret; #ifdef THERM_USE_PROC - proc_therm_ds1620 = create_proc_entry("therm", 0, 0); + proc_therm_ds1620 = create_proc_entry("therm", 0, NULL); if (proc_therm_ds1620) proc_therm_ds1620->read_proc = proc_therm_ds1620_read; else diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index e6ad246b9527..e8f15f46eca4 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -128,10 +128,6 @@ static ssize_t dtlk_read(struct file *file, char __user *buf, char ch; int i = 0, retries; - /* Can't seek (pread) on the DoubleTalk. */ - if (ppos != &file->f_pos) - return -ESPIPE; - TRACE_TEXT("(dtlk_read"); /* printk("DoubleTalk PC - dtlk_read()\n"); */ @@ -180,10 +176,6 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf, } #endif - /* Can't seek (pwrite) on the DoubleTalk. */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (iminor(file->f_dentry->d_inode) != DTLK_MINOR) return -EINVAL; @@ -303,11 +295,12 @@ static int dtlk_open(struct inode *inode, struct file *file) { TRACE_TEXT("(dtlk_open"); + nonseekable_open(inode, file); switch (iminor(inode)) { case DTLK_MINOR: if (dtlk_busy) return -EBUSY; - return 0; + return nonseekable_open(inode, file); default: return -ENXIO; diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c index 95666a2ebe13..eefd94a6d04c 100644 --- a/drivers/char/ftape/zftape/zftape-init.c +++ b/drivers/char/ftape/zftape/zftape-init.c @@ -113,6 +113,7 @@ static int zft_open(struct inode *ino, struct file *filep) int result; TRACE_FUN(ft_t_flow); + nonseekable_open(ino, filep); TRACE(ft_t_flow, "called for minor %d", iminor(ino)); if ( test_and_set_bit(0,&busy_flag) ) { TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy"); diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 59cf9b408359..fb84924901ef 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -598,10 +598,6 @@ static ssize_t ipmi_write(struct file *file, { int rv; - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (len) { rv = ipmi_heartbeat(); if (rv) @@ -619,10 +615,6 @@ static ssize_t ipmi_read(struct file *file, int rv = 0; wait_queue_t wait; - /* Can't seek (pread) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (count <= 0) return 0; @@ -678,7 +670,7 @@ static int ipmi_open(struct inode *ino, struct file *filep) /* Don't start the timer now, let it start on the first heartbeat. */ ipmi_start_timer_on_heartbeat = 1; - return(0); + return nonseekable_open(ino, filep); default: return (-ENODEV); diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 513777e538f6..4083b781adbf 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c @@ -170,7 +170,7 @@ static irqreturn_t button_handler (int irq, void *dev_id, struct pt_regs *regs) * device at any one time. */ -static int button_read (struct file *filp, char *buffer, +static int button_read (struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { interruptible_sleep_on (&button_wait_queue); diff --git a/drivers/char/nwbutton.h b/drivers/char/nwbutton.h index 91176b5097ab..ddb7b928dcbb 100644 --- a/drivers/char/nwbutton.h +++ b/drivers/char/nwbutton.h @@ -26,8 +26,6 @@ struct button_callback { static void button_sequence_finished (unsigned long parameters); static irqreturn_t button_handler (int irq, void *dev_id, struct pt_regs *regs); -static int button_read (struct file *filp, char *buffer, - size_t count, loff_t *ppos); int button_init (void); int button_add_callback (void (*callback) (void), int count); int button_del_callback (void (*callback) (void)); diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index 8cffbf0d6c51..e75381ec1561 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -43,11 +43,7 @@ static void kick_open(void); static int get_flash_id(void); static int erase_block(int nBlock); -static int write_block(unsigned long p, const char *buf, int count); -static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cmd, unsigned long arg); -static ssize_t flash_read(struct file *file, char *buf, size_t count, loff_t * ppos); -static ssize_t flash_write(struct file *file, const char *buf, size_t count, loff_t * ppos); -static loff_t flash_llseek(struct file *file, loff_t offset, int orig); +static int write_block(unsigned long p, const char __user *buf, int count); #define KFLASH_SIZE 1024*1024 //1 Meg #define KFLASH_SIZE4 4*1024*1024 //4 Meg @@ -132,15 +128,16 @@ static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cm return 0; } -static ssize_t flash_read(struct file *file, char *buf, size_t size, loff_t * ppos) +static ssize_t flash_read(struct file *file, char __user *buf, size_t size, + loff_t *ppos) { unsigned long p = *ppos; unsigned int count = size; int ret = 0; if (flashdebug) - printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, buffer=%p, count=0x%X.\n", - p, buf, count); + printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, " + "buffer=%p, count=0x%X.\n", p, buf, count); if (count) ret = -ENXIO; @@ -166,7 +163,8 @@ static ssize_t flash_read(struct file *file, char *buf, size_t size, loff_t * pp return ret; } -static ssize_t flash_write(struct file *file, const char *buf, size_t size, loff_t * ppos) +static ssize_t flash_write(struct file *file, const char __user *buf, + size_t size, loff_t * ppos) { unsigned long p = *ppos; unsigned int count = size; @@ -244,8 +242,9 @@ static ssize_t flash_write(struct file *file, const char *buf, size_t size, loff break; } if (flashdebug) - printk(KERN_DEBUG "flash_write: writing offset %lX, from buf " - "%p, bytes left %X.\n", p, buf, count - written); + printk(KERN_DEBUG "flash_write: writing offset %lX, " + "from buf %p, bytes left %X.\n", p, buf, + count - written); /* * write_block will limit write to space left in this block @@ -460,7 +459,7 @@ static int erase_block(int nBlock) /* * write_block will limit number of bytes written to the space in this block */ -static int write_block(unsigned long p, const char *buf, int count) +static int write_block(unsigned long p, const char __user *buf, int count) { volatile unsigned int c1; volatile unsigned int c2; diff --git a/drivers/char/random.c b/drivers/char/random.c index f51b541120e2..a86545f32d63 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1894,13 +1894,13 @@ static int change_poolsize(int poolsize) } static int proc_do_poolsize(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int ret; sysctl_poolsize = random_state->poolinfo.POOLBYTES; - ret = proc_dointvec(table, write, filp, buffer, lenp); + ret = proc_dointvec(table, write, filp, buffer, lenp, ppos); if (ret || !write || (sysctl_poolsize == random_state->poolinfo.POOLBYTES)) return ret; @@ -1945,7 +1945,7 @@ static int poolsize_strategy(ctl_table *table, int __user *name, int nlen, * sysctl system call, it is returned as 16 bytes of binary data. */ static int proc_do_uuid(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { ctl_table fake_table; unsigned char buf[64], tmp_uuid[16], *uuid; @@ -1967,7 +1967,7 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp, fake_table.data = buf; fake_table.maxlen = sizeof(buf); - return proc_dostring(&fake_table, write, filp, buffer, lenp); + return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos); } static int uuid_strategy(ctl_table *table, int __user *name, int nlen, diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c index e937346e162b..70b5e94b5df9 100644 --- a/drivers/char/scx200_gpio.c +++ b/drivers/char/scx200_gpio.c @@ -32,9 +32,6 @@ static ssize_t scx200_gpio_write(struct file *file, const char __user *data, unsigned m = iminor(file->f_dentry->d_inode); size_t i; - if (ppos != &file->f_pos) - return -ESPIPE; - for (i = 0; i < len; ++i) { char c; if (get_user(c, data+i)) @@ -83,9 +80,6 @@ static ssize_t scx200_gpio_read(struct file *file, char __user *buf, unsigned m = iminor(file->f_dentry->d_inode); int value; - if (ppos != &file->f_pos) - return -ESPIPE; - value = scx200_gpio_get(m); if (put_user(value ? '1' : '0', buf)) return -EFAULT; @@ -98,7 +92,7 @@ static int scx200_gpio_open(struct inode *inode, struct file *file) unsigned m = iminor(inode); if (m > 63) return -EINVAL; - return 0; + return nonseekable_open(inode, file); } static int scx200_gpio_release(struct inode *inode, struct file *file) diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 5f821fe0b8a7..48d7a7cc0c2b 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -262,7 +262,7 @@ tipar_open(struct inode *inode, struct file *file) init_ti_parallel(minor); parport_release(table[minor].dev); - return 0; + return nonseekable_open(inode, file); } static int @@ -316,9 +316,6 @@ tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) if (count == 0) return 0; - if (ppos != &file->f_pos) - return -ESPIPE; - parport_claim_or_block(table[minor].dev); while (n < count) { diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index c18aaae5cd3f..91f530c6170e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -345,18 +345,12 @@ EXPORT_SYMBOL(tty_check_change); static ssize_t hung_up_tty_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - /* Can't seek (pread) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; return 0; } static ssize_t hung_up_tty_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; return -EIO; } @@ -648,10 +642,6 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, struct tty_struct * tty; struct inode *inode; - /* Can't seek (pread) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; - tty = (struct tty_struct *)file->private_data; inode = file->f_dentry->d_inode; if (tty_paranoia_check(tty, inode, "tty_read")) @@ -726,10 +716,6 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou struct tty_struct * tty; struct inode *inode = file->f_dentry->d_inode; - /* Can't seek (pwrite) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; - tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_write")) return -EIO; @@ -755,9 +741,6 @@ ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t if (p) { ssize_t res; - /* Can't seek (pwrite) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; res = vfs_write(p, buf, count, &p->f_pos); fput(p); return res; @@ -1339,6 +1322,7 @@ static int tty_open(struct inode * inode, struct file * filp) dev_t device = inode->i_rdev; unsigned short saved_flags = filp->f_flags; + nonseekable_open(inode, filp); retry_open: noctty = filp->f_flags & O_NOCTTY; index = -1; diff --git a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c index 2febb25a4fea..8f302121741b 100644 --- a/drivers/char/watchdog/acquirewdt.c +++ b/drivers/char/watchdog/acquirewdt.c @@ -113,10 +113,6 @@ static void acq_stop(void) static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if(count) { if (!nowayout) { @@ -206,7 +202,7 @@ static int acq_open(struct inode *inode, struct file *file) /* Activate */ acq_keepalive(); - return 0; + return nonseekable_open(inode, file); } static int acq_close(struct inode *inode, struct file *file) diff --git a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c index 4090794ee141..ea73c8379bdd 100644 --- a/drivers/char/watchdog/advantechwdt.c +++ b/drivers/char/watchdog/advantechwdt.c @@ -102,10 +102,6 @@ advwdt_disable(void) static ssize_t advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { if (!nowayout) { size_t i; @@ -200,7 +196,7 @@ advwdt_open(struct inode *inode, struct file *file) */ advwdt_ping(); - return 0; + return nonseekable_open(inode, file); } static int diff --git a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c index f093a698f96f..35dcbf8be7d1 100644 --- a/drivers/char/watchdog/alim1535_wdt.c +++ b/drivers/char/watchdog/alim1535_wdt.c @@ -141,10 +141,6 @@ static int ali_settimer(int t) static ssize_t ali_write(struct file *file, const char __user *data, size_t len, loff_t * ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if (len) { if (!nowayout) { @@ -266,7 +262,7 @@ static int ali_open(struct inode *inode, struct file *file) /* Activate */ ali_start(); - return 0; + return nonseekable_open(inode, file); } /* diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c index c137cd3bc6b3..5ff6a6e4a4f7 100644 --- a/drivers/char/watchdog/alim7101_wdt.c +++ b/drivers/char/watchdog/alim7101_wdt.c @@ -150,10 +150,6 @@ static void wdt_keepalive(void) static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { - /* We can't seek */ - if(ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if(count) { if (!nowayout) { @@ -185,7 +181,7 @@ static int fop_open(struct inode * inode, struct file * file) return -EBUSY; /* Good, fire up the show */ wdt_startup(); - return 0; + return nonseekable_open(inode, file); } static int fop_close(struct inode * inode, struct file * file) diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c index 01df6566b702..d10e554a14d6 100644 --- a/drivers/char/watchdog/eurotechwdt.c +++ b/drivers/char/watchdog/eurotechwdt.c @@ -199,10 +199,6 @@ static void eurwdt_ping(void) static ssize_t eurwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { if (!nowayout) { size_t i; @@ -310,7 +306,7 @@ static int eurwdt_open(struct inode *inode, struct file *file) eurwdt_timeout = WDT_TIMEOUT; /* initial timeout */ /* Activate the WDT */ eurwdt_activate_timer(); - return 0; + return nonseekable_open(inode, file); } /** diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index 8a63f7fb75d1..5fc054700c4d 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c @@ -193,7 +193,7 @@ static int i8xx_tco_open (struct inode *inode, struct file *file) */ tco_timer_keepalive (); tco_timer_start (); - return 0; + return nonseekable_open(inode, file); } static int i8xx_tco_release (struct inode *inode, struct file *file) @@ -215,10 +215,6 @@ static int i8xx_tco_release (struct inode *inode, struct file *file) static ssize_t i8xx_tco_write (struct file *file, const char __user *data, size_t len, loff_t * ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if (len) { if (!nowayout) { diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c index 0d48439c9729..cd6467eb425d 100644 --- a/drivers/char/watchdog/ib700wdt.c +++ b/drivers/char/watchdog/ib700wdt.c @@ -141,10 +141,6 @@ ibwdt_ping(void) static ssize_t ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { if (!nowayout) { size_t i; @@ -228,7 +224,7 @@ ibwdt_open(struct inode *inode, struct file *file) /* Activate */ ibwdt_ping(); spin_unlock(&ibwdt_lock); - return 0; + return nonseekable_open(inode, file); } static int diff --git a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c index 23fc36473f34..4e9093b4af8d 100644 --- a/drivers/char/watchdog/indydog.c +++ b/drivers/char/watchdog/indydog.c @@ -81,7 +81,7 @@ static int indydog_open(struct inode *inode, struct file *file) indydog_alive = 1; printk(KERN_INFO "Started watchdog timer.\n"); - return 0; + return nonseekable_open(inode, file); } static int indydog_release(struct inode *inode, struct file *file) @@ -98,10 +98,6 @@ static int indydog_release(struct inode *inode, struct file *file) static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* Refresh the timer. */ if (len) { indydog_ping(); diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c index 499fffa3e41c..ebcaf79ce8bc 100644 --- a/drivers/char/watchdog/ixp2000_wdt.c +++ b/drivers/char/watchdog/ixp2000_wdt.c @@ -74,16 +74,12 @@ ixp2000_wdt_open(struct inode *inode, struct file *file) wdt_enable(); - return 0; + return nonseekable_open(inode, file); } static ssize_t ixp2000_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (len) { if (!nowayout) { size_t i; diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c index 79493650f1bd..b8e3d91d3066 100644 --- a/drivers/char/watchdog/ixp4xx_wdt.c +++ b/drivers/char/watchdog/ixp4xx_wdt.c @@ -69,16 +69,12 @@ ixp4xx_wdt_open(struct inode *inode, struct file *file) wdt_enable(); - return 0; + return nonseekable_open(inode, file); } static ssize_t ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (len) { if (!nowayout) { size_t i; diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index e8dc517b4412..3782930e6f1f 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c @@ -305,10 +305,6 @@ static void zf_ping(unsigned long data) static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character */ if(count){ @@ -389,7 +385,7 @@ static int zf_open(struct inode *inode, struct file *file) zf_timer_on(); - return 0; + return nonseekable_open(inode, file); } static int zf_close(struct inode *inode, struct file *file) diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index 2790f9c563f6..15a3547f24c1 100644 --- a/drivers/char/watchdog/mixcomwd.c +++ b/drivers/char/watchdog/mixcomwd.c @@ -108,7 +108,7 @@ static int mixcomwd_open(struct inode *inode, struct file *file) mixcomwd_timer_alive=0; } } - return 0; + return nonseekable_open(inode, file); } static int mixcomwd_release(struct inode *inode, struct file *file) @@ -136,10 +136,6 @@ static int mixcomwd_release(struct inode *inode, struct file *file) static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - if (ppos != &file->f_pos) { - return -ESPIPE; - } - if(len) { if (!nowayout) { diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 295e11461ec1..88bdbda92e49 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -485,10 +485,6 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (len) { if (!nowayout) { size_t i; @@ -523,7 +519,7 @@ static int pcwd_open(struct inode *inode, struct file *file) /* Activate */ pcwd_start(); pcwd_keepalive(); - return(0); + return nonseekable_open(inode, file); } static int pcwd_close(struct inode *inode, struct file *file) @@ -548,10 +544,6 @@ static ssize_t pcwd_temp_read(struct file *file, char __user *buf, size_t count, { int temperature; - /* Can't seek (pread) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (pcwd_get_temperature(&temperature)) return -EFAULT; @@ -566,7 +558,7 @@ static int pcwd_temp_open(struct inode *inode, struct file *file) if (!supports_temp) return -ENODEV; - return 0; + return nonseekable_open(inode, file); } static int pcwd_temp_close(struct inode *inode, struct file *file) diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index ddfeee878751..7216e4836193 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c @@ -261,10 +261,6 @@ static int pcipcwd_get_temperature(int *temperature) static ssize_t pcipcwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if (len) { if (!nowayout) { @@ -392,7 +388,7 @@ static int pcipcwd_open(struct inode *inode, struct file *file) /* Activate */ pcipcwd_start(); pcipcwd_keepalive(); - return 0; + return nonseekable_open(inode, file); } static int pcipcwd_release(struct inode *inode, struct file *file) @@ -420,10 +416,6 @@ static ssize_t pcipcwd_temp_read(struct file *file, char __user *data, { int temperature; - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (pcipcwd_get_temperature(&temperature)) return -EFAULT; @@ -438,7 +430,7 @@ static int pcipcwd_temp_open(struct inode *inode, struct file *file) if (!pcipcwd_private.supports_temp) return -ENODEV; - return 0; + return nonseekable_open(inode, file); } static int pcipcwd_temp_release(struct inode *inode, struct file *file) diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index 50325530e0e0..cdfe0db28784 100644 --- a/drivers/char/watchdog/pcwd_usb.c +++ b/drivers/char/watchdog/pcwd_usb.c @@ -329,10 +329,6 @@ static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temp static ssize_t usb_pcwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if (len) { if (!nowayout) { @@ -445,7 +441,7 @@ static int usb_pcwd_open(struct inode *inode, struct file *file) /* Activate */ usb_pcwd_start(usb_pcwd_device); usb_pcwd_keepalive(usb_pcwd_device); - return 0; + return nonseekable_open(inode, file); } static int usb_pcwd_release(struct inode *inode, struct file *file) @@ -473,10 +469,6 @@ static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data, { int temperature; - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) return -EFAULT; @@ -488,7 +480,7 @@ static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data, static int usb_pcwd_temperature_open(struct inode *inode, struct file *file) { - return 0; + return nonseekable_open(inode, file); } static int usb_pcwd_temperature_release(struct inode *inode, struct file *file) diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index aa3901fbab26..1adf09f83f95 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -49,6 +49,7 @@ static int nowayout = 0; */ static int sa1100dog_open(struct inode *inode, struct file *file) { + nonseekable_open(inode, file); if (test_and_set_bit(1,&sa1100wdt_users)) return -EBUSY; @@ -84,10 +85,6 @@ static int sa1100dog_release(struct inode *inode, struct file *file) static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (len) { if (!nowayout) { size_t i; diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c index b1c29907b83c..d7de9880605a 100644 --- a/drivers/char/watchdog/sbc60xxwdt.c +++ b/drivers/char/watchdog/sbc60xxwdt.c @@ -168,10 +168,6 @@ static void wdt_keepalive(void) static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { - /* We can't seek */ - if(ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if(count) { @@ -202,6 +198,8 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou static int fop_open(struct inode * inode, struct file * file) { + nonseekable_open(inode, file); + /* Just in case we're already talking to someone... */ if(test_and_set_bit(0, &wdt_is_open)) return -EBUSY; diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index df3816173a29..9ddebaebeaf5 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -157,6 +157,8 @@ static inline int sc1200wdt_status(void) static int sc1200wdt_open(struct inode *inode, struct file *file) { + nonseekable_open(inode, file); + /* allow one at a time */ if (down_trylock(&open_sem)) return -EBUSY; @@ -258,9 +260,6 @@ static int sc1200wdt_release(struct inode *inode, struct file *file) static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - if (ppos != &file->f_pos) - return -ESPIPE; - if (len) { if (!nowayout) { size_t i; diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c index ebd0bb14c0cb..8b68721f9a0d 100644 --- a/drivers/char/watchdog/sc520_wdt.c +++ b/drivers/char/watchdog/sc520_wdt.c @@ -227,10 +227,6 @@ static int wdt_set_heartbeat(int t) static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { - /* We can't seek */ - if(ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if(count) { if (!nowayout) { @@ -258,6 +254,8 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou static int fop_open(struct inode * inode, struct file * file) { + nonseekable_open(inode, file); + /* Just in case we're already talking to someone... */ if(test_and_set_bit(0, &wdt_is_open)) return -EBUSY; diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c index bc61e82c3a81..ed1800cff85b 100644 --- a/drivers/char/watchdog/scx200_wdt.c +++ b/drivers/char/watchdog/scx200_wdt.c @@ -101,7 +101,7 @@ static int scx200_wdt_open(struct inode *inode, struct file *file) return -EBUSY; scx200_wdt_enable(); - return 0; + return nonseekable_open(inode, file); } static int scx200_wdt_release(struct inode *inode, struct file *file) @@ -135,9 +135,6 @@ static struct notifier_block scx200_wdt_notifier = static ssize_t scx200_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - if (ppos != &file->f_pos) - return -ESPIPE; - /* check for a magic close character */ if (len) { diff --git a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c index e4c235de7dca..3bc9272a474c 100644 --- a/drivers/char/watchdog/shwdt.c +++ b/drivers/char/watchdog/shwdt.c @@ -209,7 +209,7 @@ static int sh_wdt_open(struct inode *inode, struct file *file) sh_wdt_start(); - return 0; + return nonseekable_open(inode, file); } /** @@ -248,10 +248,6 @@ static int sh_wdt_close(struct inode *inode, struct file *file) static ssize_t sh_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { if (!nowayout) { size_t i; diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c index 832590d417d3..117903498a01 100644 --- a/drivers/char/watchdog/softdog.c +++ b/drivers/char/watchdog/softdog.c @@ -141,7 +141,7 @@ static int softdog_open(struct inode *inode, struct file *file) * Activate timer */ softdog_keepalive(); - return 0; + return nonseekable_open(inode, file); } static int softdog_release(struct inode *inode, struct file *file) @@ -163,10 +163,6 @@ static int softdog_release(struct inode *inode, struct file *file) static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* * Refresh the timer. */ diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index 0a2196231d11..813c97038f84 100644 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ b/drivers/char/watchdog/w83627hf_wdt.c @@ -144,10 +144,6 @@ wdt_set_heartbeat(int t) static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { if (!nowayout) { size_t i; @@ -241,7 +237,7 @@ wdt_open(struct inode *inode, struct file *file) */ wdt_ping(); - return 0; + return nonseekable_open(inode, file); } static int diff --git a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c index 21270dad0859..bccbd4d6ac2d 100644 --- a/drivers/char/watchdog/w83877f_wdt.c +++ b/drivers/char/watchdog/w83877f_wdt.c @@ -190,10 +190,6 @@ static void wdt_keepalive(void) static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { - /* We can't seek */ - if(ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if(count) { @@ -230,7 +226,7 @@ static int fop_open(struct inode * inode, struct file * file) /* Good, fire up the show */ wdt_startup(); - return 0; + return nonseekable_open(inode, file); } static int fop_close(struct inode * inode, struct file * file) diff --git a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c index 26e232b74d0c..abb0bea45c02 100644 --- a/drivers/char/watchdog/wafer5823wdt.c +++ b/drivers/char/watchdog/wafer5823wdt.c @@ -97,10 +97,6 @@ wafwdt_stop(void) static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* See if we got the magic character 'V' and reload the timer */ if (count) { if (!nowayout) { @@ -197,7 +193,7 @@ static int wafwdt_open(struct inode *inode, struct file *file) * Activate */ wafwdt_start(); - return 0; + return nonseekable_open(inode, file); } static int diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c index 407690ba01f4..5684aa379886 100644 --- a/drivers/char/watchdog/wdt.c +++ b/drivers/char/watchdog/wdt.c @@ -288,10 +288,6 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if(count) { if (!nowayout) { size_t i; @@ -397,7 +393,7 @@ static int wdt_open(struct inode *inode, struct file *file) * Activate */ wdt_start(); - return 0; + return nonseekable_open(inode, file); } /** @@ -441,10 +437,6 @@ static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, { int temperature; - /* Can't seek (pread) on this device */ - if (ptr != &file->f_pos) - return -ESPIPE; - if (wdt_get_temperature(&temperature)) return -EFAULT; @@ -464,7 +456,7 @@ static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, static int wdt_temp_open(struct inode *inode, struct file *file) { - return 0; + return nonseekable_open(inode, file); } /** diff --git a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c index b61d9e1cc43f..d3fced33d364 100644 --- a/drivers/char/watchdog/wdt285.c +++ b/drivers/char/watchdog/wdt285.c @@ -97,6 +97,7 @@ static int watchdog_open(struct inode *inode, struct file *file) ret = 0; #endif + nonseekable_open(inode, file); return ret; } @@ -117,10 +118,6 @@ static int watchdog_release(struct inode *inode, struct file *file) static ssize_t watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - /* * Refresh the timer. */ diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c index 5de016ebe2b6..388c548c255b 100644 --- a/drivers/char/watchdog/wdt977.c +++ b/drivers/char/watchdog/wdt977.c @@ -240,7 +240,7 @@ static int wdt977_open(struct inode *inode, struct file *file) __module_get(THIS_MODULE); wdt977_start(); - return 0; + return nonseekable_open(inode, file); } static int wdt977_release(struct inode *inode, struct file *file) @@ -273,12 +273,9 @@ static int wdt977_release(struct inode *inode, struct file *file) * write of data will do, as we we don't define content meaning. */ -static ssize_t wdt977_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t wdt977_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { if (!nowayout) { size_t i; @@ -325,6 +322,12 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, int status; int new_options, retval = -EINVAL; int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; switch(cmd) { @@ -332,22 +335,22 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, + return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: wdt977_get_status(&status); - return put_user(status, (int *) arg); + return put_user(status, uarg.i); case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *) arg); + return put_user(0, uarg.i); case WDIOC_KEEPALIVE: wdt977_keepalive(); return 0; case WDIOC_SETOPTIONS: - if (get_user (new_options, (int *) arg)) + if (get_user (new_options, uarg.i)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { @@ -363,7 +366,7 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, return retval; case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, (int *) arg)) + if (get_user(new_timeout, uarg.i)) return -EFAULT; if (wdt977_set_timeout(new_timeout)) @@ -373,7 +376,7 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, uarg.i); } } diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c index c63d17ff68fc..9d5b5f4e5a7f 100644 --- a/drivers/char/watchdog/wdt_pci.c +++ b/drivers/char/watchdog/wdt_pci.c @@ -333,10 +333,6 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs) static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { if (!nowayout) { size_t i; @@ -446,7 +442,7 @@ static int wdtpci_open(struct inode *inode, struct file *file) * Activate */ wdtpci_start(); - return 0; + return nonseekable_open(inode, file); } /** @@ -490,10 +486,6 @@ static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t coun { int temperature; - /* Can't seek (pread) on this device */ - if (ptr != &file->f_pos) - return -ESPIPE; - if (wdtpci_get_temperature(&temperature)) return -EFAULT; @@ -513,7 +505,7 @@ static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t coun static int wdtpci_temp_open(struct inode *inode, struct file *file) { - return 0; + return nonseekable_open(inode, file); } /** diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 510214470955..161e8a27c6c5 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -151,13 +151,13 @@ EXPORT_SYMBOL_GPL(cpufreq_setmax); /*********************** cpufreq_sysctl interface ********************/ static int cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { char buf[16], *p; int cpu = (long) ctl->extra1; unsigned int len, left = *lenp; - if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) { + if (!left || (*ppos && !write) || !cpu_online(cpu)) { *lenp = 0; return 0; } @@ -183,7 +183,7 @@ cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, } *lenp = len; - filp->f_pos += len; + *ppos += len; return 0; } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 480426f43887..f86ffc4b356b 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -3755,10 +3755,6 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, idetape_tape_t *tape = drive->driver_data; ssize_t bytes_read,temp, actually_read = 0, rc; - if (ppos != &file->f_pos) { - /* "A request was outside the capabilities of the device." */ - return -ENXIO; - } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) printk(KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count); @@ -3818,11 +3814,6 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, idetape_tape_t *tape = drive->driver_data; ssize_t retval, actually_written = 0; - if (ppos != &file->f_pos) { - /* "A request was outside the capabilities of the device." */ - return -ENXIO; - } - /* The drive is write protected. */ if (tape->write_prot) return -EACCES; @@ -4187,6 +4178,7 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp) idetape_pc_t pc; int retval; + nonseekable_open(inode, filp); #if IDETAPE_DEBUG_LOG printk(KERN_INFO "ide-tape: Reached idetape_chrdev_open\n"); #endif /* IDETAPE_DEBUG_LOG */ diff --git a/drivers/ide/pci/hpt366.h b/drivers/ide/pci/hpt366.h index 7b3d8b4109df..388d6ae49dc7 100644 --- a/drivers/ide/pci/hpt366.h +++ b/drivers/ide/pci/hpt366.h @@ -470,6 +470,15 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .channels = 2, /* 4 */ .autodma = AUTODMA, .bootable = OFF_BOARD, + },{ /* 5 */ + .name = "HPT372N", + .init_setup = init_setup_hpt37x, + .init_chipset = init_chipset_hpt366, + .init_hwif = init_hwif_hpt366, + .init_dma = init_dma_hpt366, + .channels = 2, /* 4 */ + .autodma = AUTODMA, + .bootable = OFF_BOARD, } }; diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 42d7c6b97eb2..3429d57e297e 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -656,9 +656,6 @@ capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) struct sk_buff *skb; size_t copied; - if (ppos != &file->f_pos) - return -ESPIPE; - if (!cdev->ap.applid) return -ENODEV; @@ -699,9 +696,6 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos struct sk_buff *skb; u16 mlen; - if (ppos != &file->f_pos) - return -ESPIPE; - if (!cdev->ap.applid) return -ENODEV; @@ -965,7 +959,7 @@ capi_open(struct inode *inode, struct file *file) if ((file->private_data = capidev_alloc()) == 0) return -ENOMEM; - return 0; + return nonseekable_open(inode, file); } static int diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index d89a94b964cb..d3506ee8543d 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -94,7 +94,7 @@ isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off) if ((len = strlen(inf->info_start)) <= count) { if (copy_to_user(buf, inf->info_start, len)) return -EFAULT; - file->f_pos += len; + *off += len; return (len); } return (0); @@ -142,7 +142,7 @@ isdn_divert_open(struct inode *ino, struct file *filep) (struct divert_info **) filep->private_data = &divert_info_head; spin_unlock_irqrestore( &divert_info_lock, flags ); /* start_divert(); */ - return (0); + return nonseekable_open(ino, filep); } /* isdn_divert_open */ /*******************/ diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c index 1d664813f7b6..6b22a8a5f307 100644 --- a/drivers/isdn/hardware/eicon/divamnt.c +++ b/drivers/isdn/hardware/eicon/divamnt.c @@ -151,9 +151,6 @@ maint_read(struct file *file, char __user *buf, size_t count, loff_t * off) int str_length; int *str_msg; - if (off != &file->f_pos) - return -ESPIPE; - if (!file->private_data) { for (;;) { while ( @@ -306,7 +303,7 @@ static int maint_open(struct inode *ino, struct file *filep) filep->private_data = NULL; - return (0); + return nonseekable_open(ino, filep); } static int maint_close(struct inode *ino, struct file *filep) diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c index 192fae4c6465..55e83d1885d0 100644 --- a/drivers/isdn/hardware/eicon/divasproc.c +++ b/drivers/isdn/hardware/eicon/divasproc.c @@ -63,8 +63,6 @@ divas_read(struct file *file, char __user *buf, size_t count, loff_t * off) if (*off) return 0; - if (off != &file->f_pos) - return -ESPIPE; divas_get_version(tmpbuf); if (copy_to_user(buf + len, &tmpbuf, strlen(tmpbuf))) @@ -107,7 +105,7 @@ static unsigned int divas_poll(struct file *file, poll_table * wait) static int divas_open(struct inode *inode, struct file *file) { - return (0); + return nonseekable_open(inode, file); } static int divas_close(struct inode *inode, struct file *file) diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index a0983206dcf9..5da507e532fc 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -95,8 +95,6 @@ hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t int i; uchar ch, *cp; - if (&file->f_pos != off) /* fs error check */ - return (-ESPIPE); if (!count) return (0); /* nothing to handle */ @@ -214,9 +212,6 @@ hysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t * off) char *cp; int i; - if (off != &file->f_pos) /* fs error check */ - return -ESPIPE; - if (file->f_mode & FMODE_READ) { if (!(cp = file->private_data)) return (-EFAULT); /* should never happen */ @@ -320,7 +315,7 @@ hysdn_conf_open(struct inode *ino, struct file *filep) return (-EPERM); /* no permission this time */ } unlock_kernel(); - return (0); + return nonseekable_open(ino, filep); } /* hysdn_conf_open */ /***************************/ diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index 648e032868f1..8ef2b7c952a6 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -158,9 +158,6 @@ hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t long base = 10; hysdn_card *card = (hysdn_card *) file->private_data; - if (&file->f_pos != off) /* fs error check */ - return (-ESPIPE); - if (count > (sizeof(valbuf) - 1)) count = sizeof(valbuf) - 1; /* limit length */ if (copy_from_user(valbuf, buf, count)) @@ -237,7 +234,7 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t * off) if ((len = strlen(inf->log_start)) <= count) { if (copy_to_user(buf, inf->log_start, len)) return -EFAULT; - file->f_pos += len; + *off += len; return (len); } return (0); @@ -285,7 +282,7 @@ hysdn_log_open(struct inode *ino, struct file *filep) return (-EPERM); /* no permission this time */ } unlock_kernel(); - return (0); + return nonseekable_open(ino, filep); } /* hysdn_log_open */ /*******************************************************************************/ diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index eb71c80924a0..4956e2e02018 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -946,9 +946,6 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off) int retval; char *p; - if (off != &file->f_pos) - return -ESPIPE; - lock_kernel(); if (minor == ISDN_MINOR_STATUS) { if (!file->private_data) { @@ -1051,9 +1048,6 @@ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off int chidx; int retval; - if (off != &file->f_pos) - return -ESPIPE; - if (minor == ISDN_MINOR_STATUS) return -EPERM; if (!dev->drivers) @@ -1659,6 +1653,7 @@ isdn_open(struct inode *ino, struct file *filep) } #endif out: + nonseekable_open(ino, filep); return retval; } diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index e35059511941..657d5579b16b 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -179,7 +179,7 @@ static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed, neq |= f->maskandnotmode[i] & xor; } - if (f->doneq & !neq) + if (f->doneq && !neq) return 0; return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen, diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6c406e407fc7..651601105567 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1026,11 +1026,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) /* check if we should pass this packet */ /* the filter instructions are constructed assuming a four-byte PPP header on each packet */ - { - u_int16_t *p = (u_int16_t *) skb_push(skb, 2); - - *p = htons(4); /* indicate outbound in DLT_LINUX_SLL */; - } + *skb_push(skb, 2) = 1; if (ppp->pass_filter && sk_run_filter(skb, ppp->pass_filter, ppp->pass_len) == 0) { @@ -1573,11 +1569,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) /* check if the packet passes the pass and active filters */ /* the filter instructions are constructed assuming a four-byte PPP header on each packet */ - { - u_int16_t *p = (u_int16_t *) skb_push(skb, 2); - - *p = 0; /* indicate inbound in DLT_LINUX_SLL */ - } + *skb_push(skb, 2) = 0; if (ppp->pass_filter && sk_run_filter(skb, ppp->pass_filter, ppp->pass_len) == 0) { diff --git a/drivers/net/wireless/arlan-proc.c b/drivers/net/wireless/arlan-proc.c index b2e01523cb2b..86da31cac5ee 100644 --- a/drivers/net/wireless/arlan-proc.c +++ b/drivers/net/wireless/arlan-proc.c @@ -399,7 +399,7 @@ static int arlan_setup_card_by_book(struct net_device *dev) static char arlan_drive_info[ARLAN_STR_SIZE] = "A655\n\0"; static int arlan_sysctl_info(ctl_table * ctl, int write, struct file *filp, - void __user *buffer, size_t * lenp) + void __user *buffer, size_t * lenp, loff_t *ppos) { int i; int retv, pos, devnum; @@ -625,7 +625,7 @@ final: *lenp = pos; if (!write) - retv = proc_dostring(ctl, write, filp, buffer, lenp); + retv = proc_dostring(ctl, write, filp, buffer, lenp, ppos); else { *lenp = 0; @@ -636,7 +636,7 @@ final: static int arlan_sysctl_info161719(ctl_table * ctl, int write, struct file *filp, - void __user *buffer, size_t * lenp) + void __user *buffer, size_t * lenp, loff_t *ppos) { int i; int retv, pos, devnum; @@ -665,12 +665,12 @@ static int arlan_sysctl_info161719(ctl_table * ctl, int write, struct file *filp final: *lenp = pos; - retv = proc_dostring(ctl, write, filp, buffer, lenp); + retv = proc_dostring(ctl, write, filp, buffer, lenp, ppos); return retv; } static int arlan_sysctl_infotxRing(ctl_table * ctl, int write, struct file *filp, - void __user *buffer, size_t * lenp) + void __user *buffer, size_t * lenp, loff_t *ppos) { int i; int retv, pos, devnum; @@ -694,12 +694,12 @@ static int arlan_sysctl_infotxRing(ctl_table * ctl, int write, struct file *filp SARLBNpln(u_char, txBuffer, 0x800); final: *lenp = pos; - retv = proc_dostring(ctl, write, filp, buffer, lenp); + retv = proc_dostring(ctl, write, filp, buffer, lenp, ppos); return retv; } static int arlan_sysctl_inforxRing(ctl_table * ctl, int write, struct file *filp, - void __user *buffer, size_t * lenp) + void __user *buffer, size_t * lenp, loff_t *ppos) { int i; int retv, pos, devnum; @@ -722,12 +722,12 @@ static int arlan_sysctl_inforxRing(ctl_table * ctl, int write, struct file *filp SARLBNpln(u_char, rxBuffer, 0x800); final: *lenp = pos; - retv = proc_dostring(ctl, write, filp, buffer, lenp); + retv = proc_dostring(ctl, write, filp, buffer, lenp, ppos); return retv; } static int arlan_sysctl_info18(ctl_table * ctl, int write, struct file *filp, - void __user *buffer, size_t * lenp) + void __user *buffer, size_t * lenp, loff_t *ppos) { int i; int retv, pos, devnum; @@ -752,7 +752,7 @@ static int arlan_sysctl_info18(ctl_table * ctl, int write, struct file *filp, final: *lenp = pos; - retv = proc_dostring(ctl, write, filp, buffer, lenp); + retv = proc_dostring(ctl, write, filp, buffer, lenp, ppos); return retv; } @@ -763,7 +763,7 @@ final: static char conf_reset_result[200]; static int arlan_configure(ctl_table * ctl, int write, struct file *filp, - void __user *buffer, size_t * lenp) + void __user *buffer, size_t * lenp, loff_t *ppos) { int pos = 0; int devnum = ctl->procname[6] - '0'; @@ -784,11 +784,11 @@ static int arlan_configure(ctl_table * ctl, int write, struct file *filp, return -1; *lenp = pos; - return proc_dostring(ctl, write, filp, buffer, lenp); + return proc_dostring(ctl, write, filp, buffer, lenp, ppos); } static int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp, - void __user *buffer, size_t * lenp) + void __user *buffer, size_t * lenp, loff_t *ppos) { int pos = 0; int devnum = ctl->procname[5] - '0'; @@ -807,7 +807,7 @@ static int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp, } else return -1; *lenp = pos + 3; - return proc_dostring(ctl, write, filp, buffer, lenp); + return proc_dostring(ctl, write, filp, buffer, lenp, ppos); } diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index afa6ac45a5da..061097fd8117 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -33,7 +33,7 @@ #define PARPORT_MAX_SPINTIME_VALUE 1000 static int do_active_device(ctl_table *table, int write, struct file *filp, - void __user *result, size_t *lenp) + void __user *result, size_t *lenp, loff_t *ppos) { struct parport *port = (struct parport *)table->extra1; char buffer[256]; @@ -43,7 +43,7 @@ static int do_active_device(ctl_table *table, int write, struct file *filp, if (write) /* can't happen anyway */ return -EACCES; - if (filp->f_pos) { + if (*ppos) { *lenp = 0; return 0; } @@ -63,14 +63,14 @@ static int do_active_device(ctl_table *table, int write, struct file *filp, else *lenp = len; - filp->f_pos += len; + *ppos += len; return copy_to_user(result, buffer, len) ? -EFAULT : 0; } #ifdef CONFIG_PARPORT_1284 static int do_autoprobe(ctl_table *table, int write, struct file *filp, - void __user *result, size_t *lenp) + void __user *result, size_t *lenp, loff_t *ppos) { struct parport_device_info *info = table->extra2; const char *str; @@ -80,7 +80,7 @@ static int do_autoprobe(ctl_table *table, int write, struct file *filp, if (write) /* permissions stop this */ return -EACCES; - if (filp->f_pos) { + if (*ppos) { *lenp = 0; return 0; } @@ -105,7 +105,7 @@ static int do_autoprobe(ctl_table *table, int write, struct file *filp, else *lenp = len; - filp->f_pos += len; + *ppos += len; return copy_to_user (result, buffer, len) ? -EFAULT : 0; } @@ -113,13 +113,13 @@ static int do_autoprobe(ctl_table *table, int write, struct file *filp, static int do_hardware_base_addr (ctl_table *table, int write, struct file *filp, void __user *result, - size_t *lenp) + size_t *lenp, loff_t *ppos) { struct parport *port = (struct parport *)table->extra1; char buffer[20]; int len = 0; - if (filp->f_pos) { + if (*ppos) { *lenp = 0; return 0; } @@ -134,20 +134,20 @@ static int do_hardware_base_addr (ctl_table *table, int write, else *lenp = len; - filp->f_pos += len; + *ppos += len; return copy_to_user(result, buffer, len) ? -EFAULT : 0; } static int do_hardware_irq (ctl_table *table, int write, struct file *filp, void __user *result, - size_t *lenp) + size_t *lenp, loff_t *ppos) { struct parport *port = (struct parport *)table->extra1; char buffer[20]; int len = 0; - if (filp->f_pos) { + if (*ppos) { *lenp = 0; return 0; } @@ -162,20 +162,20 @@ static int do_hardware_irq (ctl_table *table, int write, else *lenp = len; - filp->f_pos += len; + *ppos += len; return copy_to_user(result, buffer, len) ? -EFAULT : 0; } static int do_hardware_dma (ctl_table *table, int write, struct file *filp, void __user *result, - size_t *lenp) + size_t *lenp, loff_t *ppos) { struct parport *port = (struct parport *)table->extra1; char buffer[20]; int len = 0; - if (filp->f_pos) { + if (*ppos) { *lenp = 0; return 0; } @@ -190,20 +190,20 @@ static int do_hardware_dma (ctl_table *table, int write, else *lenp = len; - filp->f_pos += len; + *ppos += len; return copy_to_user(result, buffer, len) ? -EFAULT : 0; } static int do_hardware_modes (ctl_table *table, int write, struct file *filp, void __user *result, - size_t *lenp) + size_t *lenp, loff_t *ppos) { struct parport *port = (struct parport *)table->extra1; char buffer[40]; int len = 0; - if (filp->f_pos) { + if (*ppos) { *lenp = 0; return 0; } @@ -229,7 +229,7 @@ static int do_hardware_modes (ctl_table *table, int write, else *lenp = len; - filp->f_pos += len; + *ppos += len; return copy_to_user(result, buffer, len) ? -EFAULT : 0; } diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 0d0343b87a00..86262a13f7c6 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -145,16 +145,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) DBF_EVENT(6, "TCHAR:read\n"); device = (struct tape_device *) filp->private_data; - /* Check position. */ - if (ppos != &filp->f_pos) { - /* - * "A request was outside the capabilities of the device." - * This check uses internal knowledge about how pread and - * read work... - */ - DBF_EVENT(6, "TCHAR:ppos wrong\n"); - return -EOVERFLOW; - } /* * If the tape isn't terminated yet, do it now. And since we then @@ -221,12 +211,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t DBF_EVENT(6, "TCHAR:write\n"); device = (struct tape_device *) filp->private_data; - /* Check position */ - if (ppos != &filp->f_pos) { - /* "A request was outside the capabilities of the device." */ - DBF_EVENT(6, "TCHAR:ppos wrong\n"); - return -EOVERFLOW; - } /* Find out block size and number of blocks */ if (device->char_data.block_size != 0) { if (count < device->char_data.block_size) { @@ -329,7 +313,7 @@ tapechar_open (struct inode *inode, struct file *filp) rc = tape_open(device); if (rc == 0) { filp->private_data = device; - return 0; + return nonseekable_open(inode, filp); } tape_put_device(device); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index e5a9b0158748..de60cfd4550a 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.114 $ + * $Revision: 1.115 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -906,8 +906,6 @@ new_channel_path(int chpid) return -ENOMEM; memset(chp, 0, sizeof(struct channel_path)); - chps[chpid] = chp; - /* fill in status, etc. */ chp->id = chpid; chp->state = 1; @@ -922,12 +920,17 @@ new_channel_path(int chpid) if (ret) { printk(KERN_WARNING "%s: could not register %02x\n", __func__, chpid); - return ret; + goto out_free; } ret = device_create_file(&chp->dev, &dev_attr_status); - if (ret) + if (ret) { device_unregister(&chp->dev); - + goto out_free; + } else + chps[chpid] = chp; + return ret; +out_free: + kfree(chp); return ret; } diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index f653fe5e8629..8e09ce4b5e53 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -127,10 +127,15 @@ extern int cio_set_options (struct subchannel *, int); extern int cio_get_options (struct subchannel *); extern int cio_modify (struct subchannel *); /* Use with care. */ +#ifdef CONFIG_CCW_CONSOLE extern struct subchannel *cio_probe_console(void); extern void cio_release_console(void); extern int cio_is_console(int irq); extern struct subchannel *cio_get_console_subchannel(void); +#else +#define cio_is_console(irq) 0 +#define cio_get_console_subchannel() NULL +#endif extern int cio_show_msg; diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 35e584c45400..6a8db84505b3 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -244,6 +244,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) }; if (notify) { /* Get device online again. */ + cdev->private->state = DEV_STATE_OFFLINE; ccw_device_online(cdev); wake_up(&cdev->private->wait_q); return; diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 44d43119371c..07a3d2258e76 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.49 $ + * $Revision: 1.50 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -295,7 +295,7 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic) break; /* Try again later. */ spin_unlock_irq(&sch->lock); - schedule_timeout(1); + msleep(10); spin_lock_irq(&sch->lock); } while (1); diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index cf8e573dec74..4ab2e0d95009 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c @@ -348,7 +348,8 @@ ccw_device_accumulate_basic_sense(struct ccw_device *cdev, struct irb *irb) (irb->scsw.actl & SCSW_ACTL_SUSPENDED))) ccw_device_path_notoper(cdev); - if (!(irb->scsw.dstat & DEV_STAT_UNIT_CHECK)) { + if (!(irb->scsw.dstat & DEV_STAT_UNIT_CHECK) && + (irb->scsw.dstat & DEV_STAT_CHN_END)) { cdev->private->irb.esw.esw0.erw.cons = 1; cdev->private->flags.dosense = 0; } diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 4c788065d815..bc768b62af96 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.83 $" +#define VERSION_QDIO_C "$Revision: 1.84 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); @@ -87,10 +87,10 @@ static debug_info_t *qdio_dbf_setup; static debug_info_t *qdio_dbf_sbal; static debug_info_t *qdio_dbf_trace; static debug_info_t *qdio_dbf_sense; -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG static debug_info_t *qdio_dbf_slsb_out; static debug_info_t *qdio_dbf_slsb_in; -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ /* iQDIO stuff: */ static volatile struct qdio_q *tiq_list=NULL; /* volatile as it could change @@ -514,10 +514,13 @@ inline static int qdio_is_outbound_q_done(struct qdio_q *q) { int no_used; +#ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; +#endif no_used=atomic_read(&q->number_of_buffers_used); +#ifdef CONFIG_QDIO_DEBUG if (no_used) { sprintf(dbf_text,"oqisnt%02x",no_used); QDIO_DBF_TEXT4(0,trace,dbf_text); @@ -525,6 +528,7 @@ qdio_is_outbound_q_done(struct qdio_q *q) QDIO_DBF_TEXT4(0,trace,"oqisdone"); } QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); +#endif /* CONFIG_QDIO_DEBUG */ return (no_used==0); } @@ -552,10 +556,12 @@ inline static void qdio_kick_outbound_q(struct qdio_q *q) { int result; +#ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; QDIO_DBF_TEXT4(0,trace,"kickoutq"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); +#endif /* CONFIG_QDIO_DEBUG */ if (!q->siga_out) return; @@ -593,16 +599,18 @@ qdio_kick_outbound_q(struct qdio_q *q) switch (result) { case 0: - /* went smooth this time, reset timestamp */ + /* went smooth this time, reset timestamp */ +#ifdef CONFIG_QDIO_DEBUG QDIO_DBF_TEXT3(0,trace,"cc2reslv"); sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, atomic_read(&q->busy_siga_counter)); QDIO_DBF_TEXT3(0,trace,dbf_text); q->timing.busy_start=0; +#endif /* CONFIG_QDIO_DEBUG */ break; case (2|QDIO_SIGA_ERROR_B_BIT_SET): /* cc=2 and busy bit: */ - atomic_inc(&q->busy_siga_counter); + atomic_inc(&q->busy_siga_counter); /* if the last siga was successful, save * timestamp here */ @@ -616,9 +624,11 @@ qdio_kick_outbound_q(struct qdio_q *q) break; } QDIO_DBF_TEXT2(0,trace,"cc2REPRT"); +#ifdef CONFIG_QDIO_DEBUG sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, atomic_read(&q->busy_siga_counter)); QDIO_DBF_TEXT3(0,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ /* else fallthrough and report error */ default: /* for plain cc=1, 2 or 3: */ @@ -635,7 +645,9 @@ inline static void qdio_kick_outbound_handler(struct qdio_q *q) { int start, end, real_end, count; +#ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; +#endif start = q->first_element_to_kick; /* last_move_ftc was just updated */ @@ -645,11 +657,13 @@ qdio_kick_outbound_handler(struct qdio_q *q) count = (end+QDIO_MAX_BUFFERS_PER_Q+1-start)& (QDIO_MAX_BUFFERS_PER_Q-1); +#ifdef CONFIG_QDIO_DEBUG QDIO_DBF_TEXT4(0,trace,"kickouth"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); sprintf(dbf_text,"s=%2xc=%2x",start,count); QDIO_DBF_TEXT4(0,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ if (q->state==QDIO_IRQ_STATE_ACTIVE) q->handler(q->cdev,QDIO_STATUS_OUTBOUND_INT| @@ -732,7 +746,9 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q) int f,f_mod_no; volatile char *slsb; int first_not_to_check; +#ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; +#endif /* CONFIG_QDIO_DEBUG */ #ifdef QDIO_USE_PROCESSING_STATE int last_position=-1; #endif /* QDIO_USE_PROCESSING_STATE */ @@ -806,8 +822,10 @@ check_next: /* P_ERROR means frontier is reached, break and report error */ case SLSB_P_INPUT_ERROR: +#ifdef CONFIG_QDIO_DEBUG sprintf(dbf_text,"inperr%2x",f_mod_no); QDIO_DBF_TEXT3(1,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); /* kind of process the buffer */ @@ -884,13 +902,16 @@ inline static int iqdio_is_inbound_q_done(struct qdio_q *q) { int no_used; +#ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; +#endif no_used=atomic_read(&q->number_of_buffers_used); /* propagate the change from 82 to 80 through VM */ SYNC_MEMORY; +#ifdef CONFIG_QDIO_DEBUG if (no_used) { sprintf(dbf_text,"iqisnt%02x",no_used); QDIO_DBF_TEXT4(0,trace,dbf_text); @@ -898,6 +919,7 @@ iqdio_is_inbound_q_done(struct qdio_q *q) QDIO_DBF_TEXT4(0,trace,"iniqisdo"); } QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); +#endif /* CONFIG_QDIO_DEBUG */ if (!no_used) return 1; @@ -933,7 +955,9 @@ inline static int qdio_is_inbound_q_done(struct qdio_q *q) { int no_used; +#ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; +#endif no_used=atomic_read(&q->number_of_buffers_used); @@ -968,16 +992,20 @@ qdio_is_inbound_q_done(struct qdio_q *q) * has (probably) not moved (see qdio_inbound_processing) */ if (NOW>GET_SAVED_TIMESTAMP(q)+q->timing.threshold) { +#ifdef CONFIG_QDIO_DEBUG QDIO_DBF_TEXT4(0,trace,"inqisdon"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); sprintf(dbf_text,"pf%02xcn%02x",q->first_to_check,no_used); QDIO_DBF_TEXT4(0,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ return 1; } else { +#ifdef CONFIG_QDIO_DEBUG QDIO_DBF_TEXT4(0,trace,"inqisntd"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); sprintf(dbf_text,"pf%02xcn%02x",q->first_to_check,no_used); QDIO_DBF_TEXT4(0,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ return 0; } } @@ -986,7 +1014,9 @@ inline static void qdio_kick_inbound_handler(struct qdio_q *q) { int count, start, end, real_end, i; +#ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; +#endif QDIO_DBF_TEXT4(0,trace,"kickinh"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -1004,8 +1034,10 @@ qdio_kick_inbound_handler(struct qdio_q *q) i=(i+1)&(QDIO_MAX_BUFFERS_PER_Q-1); } +#ifdef CONFIG_QDIO_DEBUG sprintf(dbf_text,"s=%2xc=%2x",start,count); QDIO_DBF_TEXT4(0,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ if (likely(q->state==QDIO_IRQ_STATE_ACTIVE)) q->handler(q->cdev, @@ -1622,11 +1654,13 @@ static void qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state) { int i; +#ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; QDIO_DBF_TEXT5(0,trace,"newstate"); sprintf(dbf_text,"%4x%4x",irq_ptr->irq,state); QDIO_DBF_TEXT5(0,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ irq_ptr->state=state; for (i=0;i<irq_ptr->no_input_qs;i++) @@ -1791,9 +1825,11 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) int cstat,dstat; char dbf_text[15]; +#ifdef CONFIG_QDIO_DEBUG QDIO_DBF_TEXT4(0, trace, "qint"); sprintf(dbf_text, "%s", cdev->dev.bus_id); QDIO_DBF_TEXT4(0, trace, dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ if (!intparm) { QDIO_PRINT_ERR("got unsolicited interrupt in qdio " \ @@ -1830,8 +1866,10 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) qdio_irq_check_sense(irq_ptr->irq, irb); +#ifdef CONFIG_QDIO_DEBUG sprintf(dbf_text, "state:%d", irq_ptr->state); QDIO_DBF_TEXT4(0, trace, dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ cstat = irb->scsw.cstat; dstat = irb->scsw.dstat; @@ -1872,18 +1910,22 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags, int cc; struct qdio_q *q; struct qdio_irq *irq_ptr; - char dbf_text[15]="SyncXXXX"; void *ptr; +#ifdef CONFIG_QDIO_DEBUG + char dbf_text[15]="SyncXXXX"; +#endif irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; +#ifdef CONFIG_QDIO_DEBUG *((int*)(&dbf_text[4])) = irq_ptr->irq; QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN); *((int*)(&dbf_text[0]))=flags; *((int*)(&dbf_text[4]))=queue_number; QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN); +#endif /* CONFIG_QDIO_DEBUG */ if (flags&QDIO_FLAG_SYNC_INPUT) { q=irq_ptr->input_qs[queue_number]; @@ -3083,11 +3125,12 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags, unsigned int count,struct qdio_buffer *buffers) { struct qdio_irq *irq_ptr; - +#ifdef CONFIG_QDIO_DEBUG char dbf_text[20]; sprintf(dbf_text,"doQD%04x",cdev->private->irq); - QDIO_DBF_TEXT3(0,trace,dbf_text); + QDIO_DBF_TEXT3(0,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ if ( (qidx>QDIO_MAX_BUFFERS_PER_Q) || (count>QDIO_MAX_BUFFERS_PER_Q) || @@ -3101,6 +3144,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags, if (!irq_ptr) return -ENODEV; +#ifdef CONFIG_QDIO_DEBUG if (callflags&QDIO_FLAG_SYNC_INPUT) QDIO_DBF_HEX3(0,trace,&irq_ptr->input_qs[queue_number], sizeof(void*)); @@ -3111,6 +3155,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags, QDIO_DBF_TEXT3(0,trace,dbf_text); sprintf(dbf_text,"qi%02xct%02x",qidx,count); QDIO_DBF_TEXT3(0,trace,dbf_text); +#endif /* CONFIG_QDIO_DEBUG */ if (irq_ptr->state!=QDIO_IRQ_STATE_ACTIVE) return -EBUSY; @@ -3261,12 +3306,12 @@ qdio_unregister_dbf_views(void) debug_unregister(qdio_dbf_sense); if (qdio_dbf_trace) debug_unregister(qdio_dbf_trace); -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG if (qdio_dbf_slsb_out) debug_unregister(qdio_dbf_slsb_out); if (qdio_dbf_slsb_in) debug_unregister(qdio_dbf_slsb_in); -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ } static int @@ -3311,7 +3356,7 @@ qdio_register_dbf_views(void) debug_register_view(qdio_dbf_trace,&debug_hex_ascii_view); debug_set_level(qdio_dbf_trace,QDIO_DBF_TRACE_LEVEL); -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG qdio_dbf_slsb_out=debug_register(QDIO_DBF_SLSB_OUT_NAME, QDIO_DBF_SLSB_OUT_INDEX, QDIO_DBF_SLSB_OUT_NR_AREAS, @@ -3329,7 +3374,7 @@ qdio_register_dbf_views(void) goto oom; debug_register_view(qdio_dbf_slsb_in,&debug_hex_ascii_view); debug_set_level(qdio_dbf_slsb_in,QDIO_DBF_SLSB_IN_LEVEL); -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ return 0; oom: QDIO_PRINT_ERR("not enough memory for dbf.\n"); diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 4c75d4428046..9ad14db24143 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -1,15 +1,13 @@ #ifndef _CIO_QDIO_H #define _CIO_QDIO_H -#define VERSION_CIO_QDIO_H "$Revision: 1.24 $" +#define VERSION_CIO_QDIO_H "$Revision: 1.26 $" -//#define QDIO_DBF_LIKE_HELL - -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define QDIO_VERBOSE_LEVEL 9 -#else /* QDIO_DBF_LIKE_HELL */ +#else /* CONFIG_QDIO_DEBUG */ #define QDIO_VERBOSE_LEVEL 5 -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ #define QDIO_USE_PROCESSING_STATE @@ -103,75 +101,75 @@ enum qdio_irq_states { #define QDIO_DBF_HEX0(ex,name,addr,len) QDIO_DBF_HEX(ex,name,0,addr,len) #define QDIO_DBF_HEX1(ex,name,addr,len) QDIO_DBF_HEX(ex,name,1,addr,len) #define QDIO_DBF_HEX2(ex,name,addr,len) QDIO_DBF_HEX(ex,name,2,addr,len) -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define QDIO_DBF_HEX3(ex,name,addr,len) QDIO_DBF_HEX(ex,name,3,addr,len) #define QDIO_DBF_HEX4(ex,name,addr,len) QDIO_DBF_HEX(ex,name,4,addr,len) #define QDIO_DBF_HEX5(ex,name,addr,len) QDIO_DBF_HEX(ex,name,5,addr,len) #define QDIO_DBF_HEX6(ex,name,addr,len) QDIO_DBF_HEX(ex,name,6,addr,len) -#else /* QDIO_DBF_LIKE_HELL */ +#else /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_HEX3(ex,name,addr,len) do {} while (0) #define QDIO_DBF_HEX4(ex,name,addr,len) do {} while (0) #define QDIO_DBF_HEX5(ex,name,addr,len) do {} while (0) #define QDIO_DBF_HEX6(ex,name,addr,len) do {} while (0) -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_TEXT0(ex,name,text) QDIO_DBF_TEXT(ex,name,0,text) #define QDIO_DBF_TEXT1(ex,name,text) QDIO_DBF_TEXT(ex,name,1,text) #define QDIO_DBF_TEXT2(ex,name,text) QDIO_DBF_TEXT(ex,name,2,text) -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define QDIO_DBF_TEXT3(ex,name,text) QDIO_DBF_TEXT(ex,name,3,text) #define QDIO_DBF_TEXT4(ex,name,text) QDIO_DBF_TEXT(ex,name,4,text) #define QDIO_DBF_TEXT5(ex,name,text) QDIO_DBF_TEXT(ex,name,5,text) #define QDIO_DBF_TEXT6(ex,name,text) QDIO_DBF_TEXT(ex,name,6,text) -#else /* QDIO_DBF_LIKE_HELL */ +#else /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_TEXT3(ex,name,text) do {} while (0) #define QDIO_DBF_TEXT4(ex,name,text) do {} while (0) #define QDIO_DBF_TEXT5(ex,name,text) do {} while (0) #define QDIO_DBF_TEXT6(ex,name,text) do {} while (0) -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_SETUP_NAME "qdio_setup" #define QDIO_DBF_SETUP_LEN 8 #define QDIO_DBF_SETUP_INDEX 2 #define QDIO_DBF_SETUP_NR_AREAS 1 -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define QDIO_DBF_SETUP_LEVEL 6 -#else /* QDIO_DBF_LIKE_HELL */ +#else /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_SETUP_LEVEL 2 -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_SBAL_NAME "qdio_labs" /* sbal */ #define QDIO_DBF_SBAL_LEN 256 #define QDIO_DBF_SBAL_INDEX 2 #define QDIO_DBF_SBAL_NR_AREAS 2 -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define QDIO_DBF_SBAL_LEVEL 6 -#else /* QDIO_DBF_LIKE_HELL */ +#else /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_SBAL_LEVEL 2 -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_TRACE_NAME "qdio_trace" #define QDIO_DBF_TRACE_LEN 8 #define QDIO_DBF_TRACE_NR_AREAS 2 -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define QDIO_DBF_TRACE_INDEX 4 #define QDIO_DBF_TRACE_LEVEL 4 /* -------- could be even more verbose here */ -#else /* QDIO_DBF_LIKE_HELL */ +#else /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_TRACE_INDEX 2 #define QDIO_DBF_TRACE_LEVEL 2 -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_SENSE_NAME "qdio_sense" #define QDIO_DBF_SENSE_LEN 64 #define QDIO_DBF_SENSE_INDEX 1 #define QDIO_DBF_SENSE_NR_AREAS 1 -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define QDIO_DBF_SENSE_LEVEL 6 -#else /* QDIO_DBF_LIKE_HELL */ +#else /* CONFIG_QDIO_DEBUG */ #define QDIO_DBF_SENSE_LEVEL 2 -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define QDIO_TRACE_QTYPE QDIO_ZFCP_QFMT #define QDIO_DBF_SLSB_OUT_NAME "qdio_slsb_out" @@ -185,7 +183,7 @@ enum qdio_irq_states { #define QDIO_DBF_SLSB_IN_INDEX 8 #define QDIO_DBF_SLSB_IN_NR_AREAS 1 #define QDIO_DBF_SLSB_IN_LEVEL 6 -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ #define QDIO_PRINTK_HEADER QDIO_NAME ": " @@ -494,7 +492,7 @@ struct qdio_perf_stats { #define QDIO_GET_ADDR(x) ((__u32)(long)x) #endif /* CONFIG_ARCH_S390X */ -#ifdef QDIO_DBF_LIKE_HELL +#ifdef CONFIG_QDIO_DEBUG #define set_slsb(x,y) \ if(q->queue_type==QDIO_TRACE_QTYPE) { \ if(q->is_input_q) { \ @@ -511,9 +509,9 @@ struct qdio_perf_stats { QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ } \ } -#else /* QDIO_DBF_LIKE_HELL */ +#else /* CONFIG_QDIO_DEBUG */ #define set_slsb(x,y) qdio_set_slsb(x,y) -#endif /* QDIO_DBF_LIKE_HELL */ +#endif /* CONFIG_QDIO_DEBUG */ struct qdio_q { volatile struct slsb slsb; diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c index 107bc2f30105..2c86bfa11b2f 100644 --- a/drivers/s390/net/ctcdbug.c +++ b/drivers/s390/net/ctcdbug.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.2 $) + * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.4 $) * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,7 +9,7 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.2 $ $Date: 2004/07/15 16:03:08 $ + * $Revision: 1.4 $ $Date: 2004/08/04 10:11:59 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,51 +31,51 @@ /** * Debug Facility Stuff */ -debug_info_t *dbf_setup = NULL; -debug_info_t *dbf_data = NULL; -debug_info_t *dbf_trace = NULL; +debug_info_t *ctc_dbf_setup = NULL; +debug_info_t *ctc_dbf_data = NULL; +debug_info_t *ctc_dbf_trace = NULL; -DEFINE_PER_CPU(char[256], dbf_txt_buf); +DEFINE_PER_CPU(char[256], ctc_dbf_txt_buf); void -unregister_dbf_views(void) +ctc_unregister_dbf_views(void) { - if (dbf_setup) - debug_unregister(dbf_setup); - if (dbf_data) - debug_unregister(dbf_data); - if (dbf_trace) - debug_unregister(dbf_trace); + if (ctc_dbf_setup) + debug_unregister(ctc_dbf_setup); + if (ctc_dbf_data) + debug_unregister(ctc_dbf_data); + if (ctc_dbf_trace) + debug_unregister(ctc_dbf_trace); } int -register_dbf_views(void) +ctc_register_dbf_views(void) { - dbf_setup = debug_register(CTC_DBF_SETUP_NAME, + ctc_dbf_setup = debug_register(CTC_DBF_SETUP_NAME, CTC_DBF_SETUP_INDEX, CTC_DBF_SETUP_NR_AREAS, CTC_DBF_SETUP_LEN); - dbf_data = debug_register(CTC_DBF_DATA_NAME, + ctc_dbf_data = debug_register(CTC_DBF_DATA_NAME, CTC_DBF_DATA_INDEX, CTC_DBF_DATA_NR_AREAS, CTC_DBF_DATA_LEN); - dbf_trace = debug_register(CTC_DBF_TRACE_NAME, + ctc_dbf_trace = debug_register(CTC_DBF_TRACE_NAME, CTC_DBF_TRACE_INDEX, CTC_DBF_TRACE_NR_AREAS, CTC_DBF_TRACE_LEN); - if ((dbf_setup == NULL) || (dbf_data == NULL) || - (dbf_trace == NULL)) { - unregister_dbf_views(); + if ((ctc_dbf_setup == NULL) || (ctc_dbf_data == NULL) || + (ctc_dbf_trace == NULL)) { + ctc_unregister_dbf_views(); return -ENOMEM; } - debug_register_view(dbf_setup, &debug_hex_ascii_view); - debug_set_level(dbf_setup, CTC_DBF_SETUP_LEVEL); + debug_register_view(ctc_dbf_setup, &debug_hex_ascii_view); + debug_set_level(ctc_dbf_setup, CTC_DBF_SETUP_LEVEL); - debug_register_view(dbf_data, &debug_hex_ascii_view); - debug_set_level(dbf_data, CTC_DBF_DATA_LEVEL); + debug_register_view(ctc_dbf_data, &debug_hex_ascii_view); + debug_set_level(ctc_dbf_data, CTC_DBF_DATA_LEVEL); - debug_register_view(dbf_trace, &debug_hex_ascii_view); - debug_set_level(dbf_trace, CTC_DBF_TRACE_LEVEL); + debug_register_view(ctc_dbf_trace, &debug_hex_ascii_view); + debug_set_level(ctc_dbf_trace, CTC_DBF_TRACE_LEVEL); return 0; } diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h index 3763b039d3ab..5c0fcfc0562b 100644 --- a/drivers/s390/net/ctcdbug.h +++ b/drivers/s390/net/ctcdbug.h @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.2 $) + * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.3 $) * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,7 +9,7 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.2 $ $Date: 2004/07/15 16:03:08 $ + * $Revision: 1.3 $ $Date: 2004/07/28 12:27:54 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,38 +51,38 @@ #define DBF_TEXT(name,level,text) \ do { \ - debug_text_event(dbf_##name,level,text); \ + debug_text_event(ctc_dbf_##name,level,text); \ } while (0) #define DBF_HEX(name,level,addr,len) \ do { \ - debug_event(dbf_##name,level,(void*)(addr),len); \ + debug_event(ctc_dbf_##name,level,(void*)(addr),len); \ } while (0) -extern DEFINE_PER_CPU(char[256], dbf_txt_buf); -extern debug_info_t *dbf_setup; -extern debug_info_t *dbf_data; -extern debug_info_t *dbf_trace; +extern DEFINE_PER_CPU(char[256], ctc_dbf_txt_buf); +extern debug_info_t *ctc_dbf_setup; +extern debug_info_t *ctc_dbf_data; +extern debug_info_t *ctc_dbf_trace; #define DBF_TEXT_(name,level,text...) \ do { \ - char* dbf_txt_buf = get_cpu_var(dbf_txt_buf); \ - sprintf(dbf_txt_buf, text); \ - debug_text_event(dbf_##name,level,dbf_txt_buf); \ - put_cpu_var(dbf_txt_buf); \ + char* ctc_dbf_txt_buf = get_cpu_var(ctc_dbf_txt_buf); \ + sprintf(ctc_dbf_txt_buf, text); \ + debug_text_event(ctc_dbf_##name,level,ctc_dbf_txt_buf); \ + put_cpu_var(ctc_dbf_txt_buf); \ } while (0) #define DBF_SPRINTF(name,level,text...) \ do { \ - debug_sprintf_event(dbf_trace, level, ##text ); \ - debug_sprintf_event(dbf_trace, level, text ); \ + debug_sprintf_event(ctc_dbf_trace, level, ##text ); \ + debug_sprintf_event(ctc_dbf_trace, level, text ); \ } while (0) -int register_dbf_views(void); +int ctc_register_dbf_views(void); -void unregister_dbf_views(void); +void ctc_unregister_dbf_views(void); /** * some more debug stuff diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 8e2a3abbba9f..6a1cb3f86be9 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.62 2004/07/15 16:03:08 ptiedem Exp $ + * $Id: ctcmain.c,v 1.63 2004/07/28 12:27:54 ptiedem Exp $ * * CTC / ESCON network driver * @@ -36,7 +36,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.62 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.63 $ * */ @@ -320,7 +320,7 @@ static void print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.62 $"; + char vbuf[] = "$Revision: 1.63 $"; char *version = vbuf; if (printed) @@ -3250,7 +3250,7 @@ ctc_exit(void) { unregister_cu3088_discipline(&ctc_group_driver); ctc_tty_cleanup(); - unregister_dbf_views(); + ctc_unregister_dbf_views(); ctc_pr_info("CTC driver unloaded\n"); } @@ -3267,16 +3267,16 @@ ctc_init(void) print_banner(); - ret = register_dbf_views(); + ret = ctc_register_dbf_views(); if (ret){ - ctc_pr_crit("ctc_init failed with register_dbf_views rc = %d\n", ret); + ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret); return ret; } ctc_tty_init(); ret = register_cu3088_discipline(&ctc_group_driver); if (ret) { ctc_tty_cleanup(); - unregister_dbf_views(); + ctc_unregister_dbf_views(); } return ret; } diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c index 2ebe0982aefa..6290b5c56d56 100644 --- a/drivers/s390/net/ctctty.c +++ b/drivers/s390/net/ctctty.c @@ -1,5 +1,5 @@ /* - * $Id: ctctty.c,v 1.24 2004/07/15 16:03:08 ptiedem Exp $ + * $Id: ctctty.c,v 1.26 2004/08/04 11:06:55 mschwide Exp $ * * CTC / ESCON network driver, tty interface. * @@ -27,6 +27,7 @@ #include <linux/tty.h> #include <linux/serial_reg.h> #include <linux/interrupt.h> +#include <linux/delay.h> #include <asm/uaccess.h> #include <linux/devfs_fs_kernel.h> #include "ctctty.h" @@ -1053,9 +1054,8 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp) */ timeout = jiffies + HZ; while (!(info->lsr & UART_LSR_TEMT)) { - set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(&ctc_tty_lock, flags); - schedule_timeout(HZ/2); + msleep(500); spin_lock_irqsave(&ctc_tty_lock, flags); if (time_after(jiffies,timeout)) break; diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index a3e4d0f83a95..8c63753c35e6 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c @@ -1,5 +1,5 @@ /* - * $Id: iucv.c,v 1.39 2004/07/12 06:54:14 braunu Exp $ + * $Id: iucv.c,v 1.40 2004/08/04 12:29:33 cborntra Exp $ * * IUCV network driver * @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.39 $ + * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.40 $ * */ @@ -53,6 +53,7 @@ #include <asm/io.h> #include <asm/s390_ext.h> #include <asm/ebcdic.h> +#include <asm/smp.h> #include <asm/ccwdev.h> //for root device stuff /* FLAGS: @@ -354,7 +355,7 @@ do { \ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.39 $"; + char vbuf[] = "$Revision: 1.40 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index f26c9a661766..cac57951ae28 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -11,7 +11,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Martin Schwidefsky <schwidefsky@de.ibm.com> * - * $Revision: 1.84 $ $Date: 2004/07/14 07:23:15 $ + * $Revision: 1.85 $ $Date: 2004/08/04 11:05:43 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ #include <linux/inetdevice.h> #include <linux/in.h> #include <linux/igmp.h> +#include <linux/delay.h> #include <net/arp.h> #include <net/ip.h> @@ -58,7 +59,7 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.84 $" +#define VERSION_LCS_C "$Revision: 1.85 $" static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; static char debug_buffer[255]; @@ -1420,7 +1421,7 @@ lcs_resetcard(struct lcs_card *card) card->dev->name); return 0; } - msleep(30); + msleep(3000); } PRINT_ERR("Error in Reseting LCS card!\n"); return -EIO; diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index dc5a6f98c2ab..eaae2afab174 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -23,7 +23,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.111 $" +#define VERSION_QETH_H "$Revision: 1.113 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -150,6 +150,8 @@ qeth_hex_dump(unsigned char *buf, size_t len) #define SENSE_RESETTING_EVENT_BYTE 1 #define SENSE_RESETTING_EVENT_FLAG 0x80 +#define atomic_swap(a,b) xchg((int *)a.counter, b) + /* * Common IO related definitions */ @@ -425,12 +427,18 @@ struct qeth_qdio_out_buffer { struct qeth_card; +enum qeth_out_q_states { + QETH_OUT_Q_UNLOCKED, + QETH_OUT_Q_LOCKED, + QETH_OUT_Q_LOCKED_FLUSH, +}; + struct qeth_qdio_out_q { struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q]; int queue_no; struct qeth_card *card; - spinlock_t lock; + atomic_t state; volatile int do_pack; /* * index of buffer to be filled by driver; state EMPTY or PACKING diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 7e30658d0e8f..17f0f67d8e55 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.127 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.130 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier <tspat@de.ibm.com> * - * $Revision: 1.127 $ $Date: 2004/07/14 21:46:40 $ + * $Revision: 1.130 $ $Date: 2004/08/05 11:21:50 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -78,7 +78,7 @@ qeth_eyecatcher(void) #include "qeth_mpc.h" #include "qeth_fs.h" -#define VERSION_QETH_C "$Revision: 1.127 $" +#define VERSION_QETH_C "$Revision: 1.130 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -1801,7 +1801,7 @@ qeth_send_control_data(struct qeth_card *card, int len, } add_timer(&timer); wait_event(reply->wait_q, reply->received); - del_timer(&timer); + del_timer_sync(&timer); rc = reply->rc; qeth_put_reply(reply); return rc; @@ -2105,7 +2105,7 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, QETH_DBF_TEXT(qerr,2,"unexeob"); QETH_DBF_TEXT_(qerr,2,"%s",CARD_BUS_ID(card)); QETH_DBF_HEX(misc,4,buffer,sizeof(*buffer)); - dev_kfree_skb_irq(skb); + dev_kfree_skb_any(skb); card->stats.rx_errors++; return NULL; } @@ -2297,7 +2297,7 @@ qeth_process_inbound_buffer(struct qeth_card *card, qeth_rebuild_skb(card, skb, hdr); /* is device UP ? */ if (!(card->dev->flags & IFF_UP)){ - dev_kfree_skb_irq(skb); + dev_kfree_skb_any(skb); continue; } skb->dev = card->dev; @@ -2311,16 +2311,16 @@ qeth_process_inbound_buffer(struct qeth_card *card, static inline struct qeth_buffer_pool_entry * qeth_get_buffer_pool_entry(struct qeth_card *card) { - struct qeth_buffer_pool_entry *entry, *tmp; + struct qeth_buffer_pool_entry *entry; QETH_DBF_TEXT(trace, 6, "gtbfplen"); - entry = NULL; - list_for_each_entry_safe(entry, tmp, - &card->qdio.in_buf_pool.entry_list, list){ + if (!list_empty(&card->qdio.in_buf_pool.entry_list)) { + entry = list_entry(card->qdio.in_buf_pool.entry_list.next, + struct qeth_buffer_pool_entry, list); list_del_init(&entry->list); - break; + return entry; } - return entry; + return NULL; } static inline void @@ -2367,7 +2367,7 @@ qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, buf->buffer->element[i].flags = 0; while ((skb = skb_dequeue(&buf->skb_list))){ atomic_dec(&skb->users); - dev_kfree_skb_irq(skb); + dev_kfree_skb_any(skb); } } buf->next_element_to_fill = 0; @@ -2588,14 +2588,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, QETH_DBF_TEXT(trace, 2, "flushbuf"); QETH_DBF_TEXT_(trace, 2, " err%d", rc); queue->card->stats.tx_errors += count; - /* ok, since do_QDIO went wrong the buffers have not been given - * to the hardware. they still belong to us, so we can clear - * them and reuse then, i.e. set back next_buf_to_fill*/ - for (i = index; i < index + count; ++i) { - buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; - qeth_clear_output_buffer(queue, buf); - } - queue->next_buf_to_fill = index; + /* this must not happen under normal circumstances. if it + * happens something is really wrong -> recover */ + qeth_schedule_recovery(queue->card); return; } atomic_add(count, &queue->used_buffers); @@ -2605,16 +2600,12 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, } /* - * switches between PACKING and non-PACKING state if needed. - * has to be called holding queue->lock + * Switched to packing state if the number of used buffers on a queue + * reaches a certain limit. */ -static inline int -qeth_switch_packing_state(struct qeth_qdio_out_q *queue) +static inline void +qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) { - struct qeth_qdio_out_buffer *buffer; - int flush_count = 0; - - QETH_DBF_TEXT(trace, 6, "swipack"); if (!queue->do_pack) { if (atomic_read(&queue->used_buffers) >= QETH_HIGH_WATERMARK_PACK){ @@ -2625,7 +2616,22 @@ qeth_switch_packing_state(struct qeth_qdio_out_q *queue) #endif queue->do_pack = 1; } - } else { + } +} + +/* + * Switches from packing to non-packing mode. If there is a packing + * buffer on the queue this buffer will be prepared to be flushed. + * In that case 1 is returned to inform the caller. If no buffer + * has to be flushed, zero is returned. + */ +static inline int +qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) +{ + struct qeth_qdio_out_buffer *buffer; + int flush_count = 0; + + if (queue->do_pack) { if (atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) { /* switch PACKING -> non-PACKING */ @@ -2650,21 +2656,62 @@ qeth_switch_packing_state(struct qeth_qdio_out_q *queue) return flush_count; } -static inline void -qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue, int under_int) +/* + * Called to flush a packing buffer if no more pci flags are on the queue. + * Checks if there is a packing buffer and prepares it to be flushed. + * In that case returns 1, otherwise zero. + */ +static inline int +qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue) { struct qeth_qdio_out_buffer *buffer; - int index; - index = queue->next_buf_to_fill; - buffer = &queue->bufs[index]; + buffer = &queue->bufs[queue->next_buf_to_fill]; if((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) && (buffer->next_element_to_fill > 0)){ /* it's a packing buffer */ atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; - qeth_flush_buffers(queue, under_int, index, 1); + return 1; + } + return 0; +} + +static inline void +qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) +{ + int index; + int flush_cnt = 0; + + /* + * check if weed have to switch to non-packing mode or if + * we have to get a pci flag out on the queue + */ + if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) || + !atomic_read(&queue->set_pci_flags_count)){ + if (atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) == + QETH_OUT_Q_UNLOCKED) { + /* + * If we get in here, there was no action in + * do_send_packet. So, we check if there is a + * packing buffer to be flushed here. + */ + /* TODO: try if we get a performance improvement + * by calling netif_stop_queue here */ + /* save start index for flushing */ + index = queue->next_buf_to_fill; + flush_cnt += qeth_switch_to_nonpacking_if_needed(queue); + if (!flush_cnt && + !atomic_read(&queue->set_pci_flags_count)) + flush_cnt += + qeth_flush_buffers_on_no_pci(queue); + /* were done with updating critical queue members */ + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); + /* flushing can be done outside the lock */ + if (flush_cnt) + qeth_flush_buffers(queue, 1, index, flush_cnt); + } } } @@ -2710,6 +2757,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, qeth_clear_output_buffer(queue, buffer); } atomic_sub(count, &queue->used_buffers); + /* check if we need to do something on this outbound queue */ + qeth_check_outbound_queue(queue); netif_wake_queue(card->dev); #ifdef CONFIG_QETH_PERF_STATS @@ -2981,7 +3030,8 @@ qeth_init_qdio_queues(struct qeth_card *card) card->qdio.out_qs[i]->do_pack = 0; atomic_set(&card->qdio.out_qs[i]->used_buffers,0); atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0); - spin_lock_init(&card->qdio.out_qs[i]->lock); + atomic_set(&card->qdio.out_qs[i]->state, + QETH_OUT_Q_UNLOCKED); } return 0; } @@ -3295,12 +3345,12 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) card->perf_stats.outbound_start_time = qeth_get_micros(); #endif /* - * dev_queue_xmit should ensure that we are called packet - * after packet + * We only call netif_stop_queue in case of errors. Since we've + * got our own synchronization on queues we can keep the stack's + * queue running. */ - netif_stop_queue(dev); - if (!(rc = qeth_send_packet(card, skb))) - netif_wake_queue(dev); + if ((rc = qeth_send_packet(card, skb))) + netif_stop_queue(dev); #ifdef CONFIG_QETH_PERF_STATS card->perf_stats.outbound_time += qeth_get_micros() - @@ -3714,7 +3764,11 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, QETH_DBF_TEXT(trace, 6, "dosndpfa"); - spin_lock(&queue->lock); + /* spin until we get the queue ... */ + while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED, + QETH_OUT_Q_LOCKED, + &queue->state)); + /* ... now we've got the queue */ index = queue->next_buf_to_fill; buffer = &queue->bufs[queue->next_buf_to_fill]; /* @@ -3723,14 +3777,14 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, */ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { card->stats.tx_dropped++; - spin_unlock(&queue->lock); + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); return -EBUSY; } queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); qeth_fill_buffer(queue, buffer, (char *)hdr, skb); qeth_flush_buffers(queue, 0, index, 1); - spin_unlock(&queue->lock); return 0; } @@ -3746,7 +3800,10 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, QETH_DBF_TEXT(trace, 6, "dosndpkt"); - spin_lock(&queue->lock); + /* spin until we get the queue ... */ + while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED, + QETH_OUT_Q_LOCKED, + &queue->state)); start_index = queue->next_buf_to_fill; buffer = &queue->bufs[queue->next_buf_to_fill]; /* @@ -3755,9 +3812,11 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, */ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ card->stats.tx_dropped++; - spin_unlock(&queue->lock); + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); return -EBUSY; } + /* check if we need to switch packing state of this queue */ + qeth_switch_to_packing_if_needed(queue); if (queue->do_pack){ /* does packet fit in current buffer? */ if((QETH_MAX_BUFFER_ELEMENTS(card) - @@ -3772,11 +3831,10 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, /* we did a step forward, so check buffer state again */ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ card->stats.tx_dropped++; - qeth_flush_buffers(queue, 0, start_index, 1); - spin_unlock(&queue->lock); /* return EBUSY because we sent old packet, not * the current one */ - return -EBUSY; + rc = -EBUSY; + goto out; } } } @@ -3787,16 +3845,27 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; } - /* check if we need to switch packing state of this queue */ - flush_count += qeth_switch_packing_state(queue); - + /* + * queue->state will go from LOCKED -> UNLOCKED or from + * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us + * (switch packing state or flush buffer to get another pci flag out). + * In that case we will enter this loop + */ + while (atomic_dec_return(&queue->state)){ + /* check if we can go back to non-packing state */ + flush_count += qeth_switch_to_nonpacking_if_needed(queue); + /* + * check if we need to flush a packing buffer to get a pci + * flag out on the queue + */ + if (!flush_count && !atomic_read(&queue->set_pci_flags_count)) + flush_count += qeth_flush_buffers_on_no_pci(queue); + } + /* at this point the queue is UNLOCKED again */ +out: if (flush_count) qeth_flush_buffers(queue, 0, start_index, flush_count); - if (!atomic_read(&queue->set_pci_flags_count)) - qeth_flush_buffers_on_no_pci(queue, 0); - - spin_unlock(&queue->lock); return rc; } diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 939bbad0f549..dad02890ef01 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -29,7 +29,7 @@ */ /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_AUX_REVISION "$Revision: 1.114 $" +#define ZFCP_AUX_REVISION "$Revision: 1.115 $" #include "zfcp_ext.h" @@ -41,8 +41,6 @@ static char *device; /* written against the module interface */ static int __init zfcp_module_init(void); -int zfcp_reboot_handler(struct notifier_block *, unsigned long, void *); - /* FCP related */ static void zfcp_ns_gid_pn_handler(unsigned long); @@ -338,9 +336,6 @@ zfcp_module_init(void) /* initialise configuration rw lock */ rwlock_init(&zfcp_data.config_lock); - zfcp_data.reboot_notifier.notifier_call = zfcp_reboot_handler; - register_reboot_notifier(&zfcp_data.reboot_notifier); - /* save address of data structure managing the driver module */ zfcp_data.scsi_host_template.module = THIS_MODULE; @@ -357,7 +352,6 @@ zfcp_module_init(void) goto out; out_ccw_register: - unregister_reboot_notifier(&zfcp_data.reboot_notifier); misc_deregister(&zfcp_cfdc_misc); out_misc_register: #ifdef CONFIG_S390_SUPPORT @@ -370,23 +364,6 @@ zfcp_module_init(void) } /* - * This function is called automatically by the kernel whenever a reboot or a - * shut-down is initiated and zfcp is still loaded - * - * locks: zfcp_data.config_sema is taken prior to shutting down the module - * and removing all structures - * returns: NOTIFY_DONE in all cases - */ -int -zfcp_reboot_handler(struct notifier_block *notifier, unsigned long code, - void *ptr) -{ - zfcp_ccw_unregister(); - return NOTIFY_DONE; -} - - -/* * function: zfcp_cfdc_dev_ioctl * * purpose: Handle control file upload/download transaction via IOCTL diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 84a5e37e7026..001d8067ca95 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -26,7 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_CCW_C_REVISION "$Revision: 1.55 $" +#define ZFCP_CCW_C_REVISION "$Revision: 1.56 $" #include "zfcp_ext.h" @@ -37,6 +37,7 @@ static void zfcp_ccw_remove(struct ccw_device *); static int zfcp_ccw_set_online(struct ccw_device *); static int zfcp_ccw_set_offline(struct ccw_device *); static int zfcp_ccw_notify(struct ccw_device *, int); +static void zfcp_ccw_shutdown(struct device *); static struct ccw_device_id zfcp_ccw_device_id[] = { {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, @@ -59,6 +60,9 @@ static struct ccw_driver zfcp_ccw_driver = { .set_online = zfcp_ccw_set_online, .set_offline = zfcp_ccw_set_offline, .notify = zfcp_ccw_notify, + .driver = { + .shutdown = zfcp_ccw_shutdown, + }, }; MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id); @@ -287,4 +291,19 @@ zfcp_ccw_unregister(void) ccw_driver_unregister(&zfcp_ccw_driver); } +/** + * zfcp_ccw_shutdown - gets called on reboot/shutdown + * + * Makes sure that QDIO queues are down when the system gets stopped. + */ +static void +zfcp_ccw_shutdown(struct device *dev) +{ + struct zfcp_adapter *adapter; + + adapter = dev_get_drvdata(dev); + zfcp_erp_adapter_shutdown(adapter, 0); + zfcp_erp_wait(adapter); +} + #undef ZFCP_LOG_AREA diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index eb65b928825e..dda20bf00406 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -33,7 +33,7 @@ #define ZFCP_DEF_H /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_DEF_REVISION "$Revision: 1.78 $" +#define ZFCP_DEF_REVISION "$Revision: 1.81 $" /*************************** INCLUDES *****************************************/ @@ -42,6 +42,7 @@ #include <linux/miscdevice.h> #include <linux/major.h> #include <linux/blkdev.h> +#include <linux/delay.h> #include <scsi/scsi.h> #include <scsi/scsi_tcq.h> #include <scsi/scsi_cmnd.h> @@ -55,7 +56,6 @@ #include <asm/qdio.h> #include <asm/debug.h> #include <asm/ebcdic.h> -#include <linux/reboot.h> #include <linux/mempool.h> #include <linux/syscalls.h> #include <linux/ioctl.h> @@ -70,7 +70,7 @@ /********************* GENERAL DEFINES *********************************/ /* zfcp version number, it consists of major, minor, and patch-level number */ -#define ZFCP_VERSION "4.0.0" +#define ZFCP_VERSION "4.1.3" static inline void * zfcp_sg_to_address(struct scatterlist *list) @@ -1074,8 +1074,6 @@ struct zfcp_data { lists */ struct semaphore config_sema; /* serialises configuration changes */ - struct notifier_block reboot_notifier; /* used to register cleanup - functions */ atomic_t loglevel; /* current loglevel */ char init_busid[BUS_ID_SIZE]; wwn_t init_wwpn; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 52d11563ee76..e0766777e5d2 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -31,7 +31,7 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_ERP_REVISION "$Revision: 1.60 $" +#define ZFCP_ERP_REVISION "$Revision: 1.61 $" #include "zfcp_ext.h" @@ -2170,7 +2170,6 @@ static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action) { int retval; - unsigned long timeout; struct zfcp_adapter *adapter = erp_action->adapter; retval = zfcp_erp_adapter_strategy_close(erp_action); @@ -2187,9 +2186,7 @@ zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action) ZFCP_LOG_INFO("Waiting to allow the adapter %s " "to recover itself\n", zfcp_get_busid_by_adapter(adapter)); - timeout = ZFCP_TYPE2_RECOVERY_TIME; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); + msleep(jiffies_to_msecs(ZFCP_TYPE2_RECOVERY_TIME)); } return retval; @@ -2365,10 +2362,8 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) failed_qdio_activate: debug_text_event(adapter->erp_dbf, 3, "qdio_down1a"); while (qdio_shutdown(adapter->ccw_device, - QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); - } + QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) + msleep(1000); debug_text_event(adapter->erp_dbf, 3, "qdio_down1b"); failed_qdio_establish: @@ -2414,10 +2409,8 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) debug_text_event(adapter->erp_dbf, 3, "qdio_down2a"); while (qdio_shutdown(adapter->ccw_device, - QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); - } + QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) + msleep(1000); debug_text_event(adapter->erp_dbf, 3, "qdio_down2b"); /* @@ -2528,8 +2521,7 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) ZFCP_LOG_DEBUG("host connection still initialising... " "waiting and retrying...\n"); /* sleep a little bit before retry */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(ZFCP_EXCHANGE_CONFIG_DATA_SLEEP); + msleep(jiffies_to_msecs(ZFCP_EXCHANGE_CONFIG_DATA_SLEEP)); } } while ((retries--) && atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 3488a9118f58..79451af65f5e 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -29,7 +29,7 @@ */ /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_FSF_C_REVISION "$Revision: 1.53 $" +#define ZFCP_FSF_C_REVISION "$Revision: 1.55 $" #include "zfcp_ext.h" @@ -180,8 +180,7 @@ zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) ZFCP_LOG_DEBUG("fsf req list of adapter %s not yet empty\n", zfcp_get_busid_by_adapter(adapter)); /* wait for woken intiators to clean up their requests */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(ZFCP_FSFREQ_CLEANUP_TIMEOUT); + msleep(jiffies_to_msecs(ZFCP_FSFREQ_CLEANUP_TIMEOUT)); } /* consistency check */ @@ -2620,6 +2619,7 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) { int retval = 0; unsigned long lock_flags; + volatile struct qdio_buffer_element *sbale; /* setup new FSF request */ retval = zfcp_fsf_req_create(erp_action->adapter, @@ -2636,6 +2636,11 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) goto out; } + sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, + erp_action->fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + /* mark port as being closed */ atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, &erp_action->port->status); diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c index e0ace9349c70..11a27c1ff32a 100644 --- a/drivers/s390/scsi/zfcp_sysfs_port.c +++ b/drivers/s390/scsi/zfcp_sysfs_port.c @@ -26,7 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.40 $" +#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.41 $" #include "zfcp_ext.h" @@ -125,7 +125,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count) struct zfcp_unit *unit; fcp_lun_t fcp_lun; char *endp; - int retval = -EINVAL; + int retval = 0; down(&zfcp_data.config_sema); @@ -136,8 +136,10 @@ zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count) } fcp_lun = simple_strtoull(buf, &endp, 0); - if ((endp + 1) < (buf + count)) + if ((endp + 1) < (buf + count)) { + retval = -EINVAL; goto out; + } write_lock_irq(&zfcp_data.config_lock); unit = zfcp_get_unit_by_lun(port, fcp_lun); diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c index 323755498867..ad870a300a1a 100644 --- a/drivers/sbus/char/cpwatchdog.c +++ b/drivers/sbus/char/cpwatchdog.c @@ -324,7 +324,7 @@ static int wd_open(struct inode *inode, struct file *f) wd_dev.initialized = 1; } - return(0); + return(nonseekable_open(inode, f)); } static int wd_release(struct inode *inode, struct file *file) @@ -419,9 +419,6 @@ static ssize_t wd_write(struct file *file, return(-EINVAL); } - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { wd_pingtimer(pTimer); return 1; diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c index 0e8d06ea8d61..7f8e109f93c1 100644 --- a/drivers/sbus/char/riowatchdog.c +++ b/drivers/sbus/char/riowatchdog.c @@ -116,6 +116,7 @@ static void riowd_starttimer(void) static int riowd_open(struct inode *inode, struct file *filp) { + nonseekable_open(inode, filp); return 0; } @@ -184,9 +185,6 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, static ssize_t riowd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - if (ppos != &file->f_pos) - return -ESPIPE; - if (count) { riowd_pingtimer(); return 1; diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c index 925061c75427..c095308dbd91 100644 --- a/drivers/sbus/dvma.c +++ b/drivers/sbus/dvma.c @@ -121,7 +121,6 @@ void __init dvma_init(struct sbus_bus *sbus) void __init sun4_dvma_init(void) { struct sbus_dma *dma; - struct sbus_dma *dchain; struct resource r; if(sun4_dma_physaddr) { diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 9d0cab9ced29..fb74a2f64cd5 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -3185,12 +3185,6 @@ static ssize_t osst_write(struct file * filp, const char __user * buf, size_t co goto out; } - if (ppos != &filp->f_pos) { - /* "A request was outside the capabilities of the device." */ - retval = (-ENXIO); - goto out; - } - if (STp->ready != ST_READY) { if (STp->ready == ST_NO_TAPE) retval = (-ENOMEDIUM); @@ -3512,12 +3506,6 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo goto out; } - if (ppos != &filp->f_pos) { - /* "A request was outside the capabilities of the device." */ - retval = (-ENXIO); - goto out; - } - if (STp->ready != ST_READY) { if (STp->ready == ST_NO_TAPE) retval = (-ENOMEDIUM); @@ -4254,6 +4242,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) int dev = TAPE_NR(inode); int mode = TAPE_MODE(inode); + nonseekable_open(inode, filp); write_lock(&os_scsi_tapes_lock); if (dev >= osst_max_dev || os_scsi_tapes == NULL || (STp = os_scsi_tapes[dev]) == NULL || !STp->device) { diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 8ccc7d9142c9..7b0665d8ba1e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -234,6 +234,7 @@ sg_open(struct inode *inode, struct file *filp) int res; int retval; + nonseekable_open(inode, filp); SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags)); sdp = sg_get_dev(dev); if ((!sdp) || (!sdp->device)) @@ -343,7 +344,6 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) return -ENXIO; SCSI_LOG_TIMEOUT(3, printk("sg_read: %s, count=%d\n", sdp->disk->disk_name, (int) count)); - if (ppos != &filp->f_pos) ; /* FIXME: Hmm. Seek to the right place, or fail? */ if ((k = verify_area(VERIFY_WRITE, buf, count))) return k; if (sfp->force_packid && (count >= SZ_SG_HEADER)) { @@ -501,7 +501,6 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (!((filp->f_flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) return -ENXIO; - if (ppos != &filp->f_pos) ; /* FIXME: Hmm. Seek to the right place, or fail? */ if ((k = verify_area(VERIFY_READ, buf, count))) return k; /* protects following copy_from_user()s + get_user()s */ diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index fe114ba4ed94..6e87d6226626 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1001,6 +1001,7 @@ static int st_open(struct inode *inode, struct file *filp) int dev = TAPE_NR(inode); char *name; + nonseekable_open(inode, filp); write_lock(&st_dev_arr_lock); if (dev >= st_dev_max || scsi_tapes == NULL || ((STp = scsi_tapes[dev]) == NULL)) { @@ -1203,7 +1204,7 @@ static int st_release(struct inode *inode, struct file *filp) } /* The checks common to both reading and writing */ -static ssize_t rw_checks(Scsi_Tape *STp, struct file *filp, size_t count, loff_t *ppos) +static ssize_t rw_checks(Scsi_Tape *STp, struct file *filp, size_t count) { ssize_t retval = 0; @@ -1218,12 +1219,6 @@ static ssize_t rw_checks(Scsi_Tape *STp, struct file *filp, size_t count, loff_t goto out; } - if (ppos != &filp->f_pos) { - /* "A request was outside the capabilities of the device." */ - retval = (-ENXIO); - goto out; - } - if (STp->ready != ST_READY) { if (STp->ready == ST_NO_TAPE) retval = (-ENOMEDIUM); @@ -1367,7 +1362,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (down_interruptible(&STp->lock)) return -ERESTARTSYS; - retval = rw_checks(STp, filp, count, ppos); + retval = rw_checks(STp, filp, count); if (retval || count == 0) goto out; @@ -1833,7 +1828,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) if (down_interruptible(&STp->lock)) return -ERESTARTSYS; - retval = rw_checks(STp, filp, count, ppos); + retval = rw_checks(STp, filp, count); if (retval || count == 0) goto out; diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 8639c7dd0e78..34b367778dc9 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -574,8 +574,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, static int __devinit pci_xircom_init(struct pci_dev *dev) { - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); return 0; } diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c index 648bbb033bb2..42f60fa37d24 100644 --- a/drivers/usb/class/audio.c +++ b/drivers/usb/class/audio.c @@ -1974,7 +1974,7 @@ static int usb_audio_open_mixdev(struct inode *inode, struct file *file) s->count++; up(&open_sem); - return 0; + return nonseekable_open(inode, file); } static int usb_audio_release_mixdev(struct inode *inode, struct file *file) @@ -2147,8 +2147,6 @@ static ssize_t usb_audio_read(struct file *file, char __user *buffer, size_t cou unsigned int ptr; int cnt, err; - if (ppos != &file->f_pos) - return -ESPIPE; if (as->usbin.dma.mapped) return -ENXIO; if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as))) @@ -2216,8 +2214,6 @@ static ssize_t usb_audio_write(struct file *file, const char __user *buffer, siz unsigned int start_thr; int cnt, err; - if (ppos != &file->f_pos) - return -ESPIPE; if (as->usbout.dma.mapped) return -ENXIO; if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as))) @@ -2688,7 +2684,7 @@ static int usb_audio_open(struct inode *inode, struct file *file) as->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); s->count++; up(&open_sem); - return 0; + return nonseekable_open(inode, file); } static int usb_audio_release(struct inode *inode, struct file *file) diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c index 0223d3c4b14a..6a6dbac4987e 100644 --- a/drivers/usb/class/usb-midi.c +++ b/drivers/usb/class/usb-midi.c @@ -646,9 +646,6 @@ static ssize_t usb_midi_read(struct file *file, char __user *buffer, size_t coun ssize_t ret; DECLARE_WAITQUEUE(wait, current); - if ( ppos != &file->f_pos ) { - return -ESPIPE; - } if ( !access_ok(VERIFY_READ, buffer, count) ) { return -EFAULT; } @@ -728,9 +725,6 @@ static ssize_t usb_midi_write(struct file *file, const char __user *buffer, size ssize_t ret; unsigned long int flags; - if ( ppos != &file->f_pos ) { - return -ESPIPE; - } if ( !access_ok(VERIFY_READ, buffer, count) ) { return -EFAULT; } @@ -920,7 +914,7 @@ static int usb_midi_open(struct inode *inode, struct file *file) printk(KERN_INFO "usb-midi: Open Succeeded. minor= %d.\n", minor); #endif - return 0; /** Success. **/ + return nonseekable_open(inode, file); /** Success. **/ } diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c index 2c021bfec27f..01f77cbc4d1c 100644 --- a/drivers/usb/media/dabusb.c +++ b/drivers/usb/media/dabusb.c @@ -616,7 +616,7 @@ static int dabusb_open (struct inode *inode, struct file *file) file->f_pos = 0; file->private_data = s; - return 0; + return nonseekable_open(inode, file); } static int dabusb_release (struct inode *inode, struct file *file) diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 3a61a0b77f87..310c5a96c6f5 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -1435,7 +1435,7 @@ static int auerchar_open (struct inode *inode, struct file *file) /* file IO stuff */ file->f_pos = 0; file->private_data = ccp; - return 0; + return nonseekable_open(inode, file); /* Error exit */ ofail: up (&cp->mutex); diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 8e266eba061c..cd7b548b9cc2 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -344,6 +344,7 @@ static int tower_open (struct inode *inode, struct file *file) dbg(2, "%s: enter", __FUNCTION__); + nonseekable_open(inode, file); subminor = iminor(inode); down (&disconnect_sem); diff --git a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c index 51717375a8c0..cdf5919f8865 100644 --- a/drivers/usb/misc/tiglusb.c +++ b/drivers/usb/misc/tiglusb.c @@ -132,7 +132,7 @@ tiglusb_open (struct inode *inode, struct file *filp) filp->f_pos = 0; filp->private_data = s; - return 0; + return nonseekable_open(inode, filp); } static int diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index a15f0c4302aa..ae8fb7aef251 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -1291,8 +1291,7 @@ static void sa1100fb_enable_controller(struct sa1100fb_info *fbi) #error Where is GPIO24 set as an output? Can we fit this in somewhere else? if (machine_is_graphicsclient()) { // From ADS doc again...same as disable - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(20 * HZ / 1000); + msleep(20); GPSR |= GPIO_GPIO24; } #endif @@ -1327,8 +1326,7 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi) * We'll wait 20msec. */ GPCR |= GPIO_GPIO24; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(20 * HZ / 1000); + msleep(20); } #endif #ifdef CONFIG_SA1100_HUW_WEBPANEL diff --git a/fs/Kconfig b/fs/Kconfig index 083ee1440ad2..a4035fba9b18 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -554,6 +554,44 @@ menu "DOS/FAT/NT Filesystems" config FAT_FS tristate select NLS + help + If you want to use one of the FAT-based file systems (the MS-DOS, + VFAT (Windows 95) and UMSDOS (used to run Linux on top of an + ordinary DOS partition) file systems), then you must say Y or M here + to include FAT support. You will then be able to mount partitions or + diskettes with FAT-based file systems and transparently access the + files on them, i.e. MSDOS files will look and behave just like all + other Unix files. + + This FAT support is not a file system in itself, it only provides + the foundation for the other file systems. You will have to say Y or + M to at least one of "MSDOS fs support" or "VFAT fs support" in + order to make use of it. + + Another way to read and write MSDOS floppies and hard drive + partitions from within Linux (but not transparently) is with the + mtools ("man mtools") program suite. You don't need to say Y here in + order to do that. + + If you need to move large files on floppies between a DOS and a + Linux box, say Y here, mount the floppy under Linux with an MSDOS + file system and use GNU tar's M option. GNU tar is a program + available for Unix and DOS ("man tar" or "info tar"). + + It is now also becoming possible to read and write compressed FAT + file systems; read <file:Documentation/filesystems/fat_cvf.txt> for + details. + + The FAT support will enlarge your kernel by about 37 KB. If unsure, + say Y. + + To compile this as a module, choose M here: the module will be called + fat. Note that if you compile the FAT support as a module, you + cannot compile any of the FAT-based file systems into the kernel + -- they will have to be modules as well. + The file system of your root partition (the one containing the + directory /) cannot be a module, so don't say M here if you intend + to use UMSDOS as your root file system. config MSDOS_FS tristate "MSDOS fs support" @@ -606,6 +644,25 @@ config VFAT_FS To compile this as a module, choose M here: the module will be called vfat. +config FAT_DEFAULT_CODEPAGE + int "Default codepage for FAT" + depends on MSDOS_FS || VFAT_FS + default 437 + help + This option should be set to the codepage of your FAT filesystems. + It can be overridden with the 'codepage' mount option. + +config FAT_DEFAULT_IOCHARSET + string "Default iocharset for FAT" + depends on VFAT_FS + default "iso8859-1" + help + Set this to the default I/O character set you'd like FAT to use. + It should probably match the character set that most of your + FAT filesystems use, and can be overridded with the 'iocharset' + mount option for FAT filesystems. Note that UTF8 is *not* a + supported charset for FAT filesystems. + config UMSDOS_FS #dep_tristate ' UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS # UMSDOS is temprory broken diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index 60fc6f9ce240..fd98626ba280 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -69,12 +69,12 @@ void reset_coda_cache_inv_stats( void ) } int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, - void __user * buffer, size_t * lenp ) + void __user * buffer, size_t * lenp, loff_t * ppos ) { if ( write ) { reset_coda_vfs_stats(); - filp->f_pos += *lenp; + *ppos += *lenp; } else { *lenp = 0; } @@ -84,12 +84,12 @@ int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, int do_reset_coda_cache_inv_stats( ctl_table * table, int write, struct file * filp, void __user * buffer, - size_t * lenp ) + size_t * lenp, loff_t * ppos ) { if ( write ) { reset_coda_cache_inv_stats(); - filp->f_pos += *lenp; + *ppos += *lenp; } else { *lenp = 0; } diff --git a/fs/devfs/base.c b/fs/devfs/base.c index b0fb34873825..a62d9412e73e 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -857,12 +857,14 @@ static int devfsd_close(struct inode *inode, struct file *file); static ssize_t stat_read(struct file *file, char __user *buf, size_t len, loff_t * ppos); static struct file_operations stat_fops = { + .open = nonseekable_open, .read = stat_read, }; #endif /* Devfs daemon file operations */ static struct file_operations devfsd_fops = { + .open = nonseekable_open, .read = devfsd_read, .ioctl = devfsd_ioctl, .release = devfsd_close, @@ -2574,9 +2576,6 @@ static ssize_t devfsd_read(struct file *file, char __user *buf, size_t len, struct devfsd_notify_struct *info = fs_info->devfsd_info; DECLARE_WAITQUEUE(wait, current); - /* Can't seek (pread) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; /* Verify the task has grabbed the queue */ if (fs_info->devfsd_task != current) return -EPERM; @@ -2763,9 +2762,6 @@ static ssize_t stat_read(struct file *file, char __user *buf, size_t len, num = sprintf(txt, "Number of entries: %u number of bytes: %u\n", stat_num_entries, stat_num_bytes) + 1; - /* Can't seek (pread) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; if (*ppos >= num) return 0; if (*ppos + len > num) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index b4ee8c93e67f..c0fc6b7d6a98 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -23,6 +23,14 @@ #include <linux/parser.h> #include <asm/unaligned.h> +#ifndef CONFIG_FAT_DEFAULT_IOCHARSET +/* if user don't select VFAT, this is undefined. */ +#define CONFIG_FAT_DEFAULT_IOCHARSET "" +#endif + +static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE; +static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; + /* * New FAT inode stuff. We do the following: * a) i_ino is constant and has nothing with on-disk location. @@ -166,15 +174,15 @@ void fat_put_super(struct super_block *sb) if (sbi->nls_disk) { unload_nls(sbi->nls_disk); sbi->nls_disk = NULL; - sbi->options.codepage = 0; + sbi->options.codepage = fat_default_codepage; } if (sbi->nls_io) { unload_nls(sbi->nls_io); sbi->nls_io = NULL; } - if (sbi->options.iocharset) { + if (sbi->options.iocharset != fat_default_iocharset) { kfree(sbi->options.iocharset); - sbi->options.iocharset = NULL; + sbi->options.iocharset = fat_default_iocharset; } sb->s_fs_info = NULL; @@ -193,10 +201,11 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) seq_printf(m, ",gid=%u", opts->fs_gid); seq_printf(m, ",fmask=%04o", opts->fs_fmask); seq_printf(m, ",dmask=%04o", opts->fs_dmask); - if (sbi->nls_disk && opts->codepage) + if (sbi->nls_disk && opts->codepage != fat_default_codepage) seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); if (isvfat) { - if (sbi->nls_io && opts->iocharset) + if (sbi->nls_io && + strcmp(opts->iocharset, fat_default_iocharset)) seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); switch (opts->shortname) { @@ -327,14 +336,15 @@ static int parse_options(char *options, int is_vfat, int *debug, char *p; substring_t args[MAX_OPT_ARGS]; int option; + char *iocharset; opts->isvfat = is_vfat; opts->fs_uid = current->uid; opts->fs_gid = current->gid; opts->fs_fmask = opts->fs_dmask = current->fs->umask; - opts->codepage = 0; - opts->iocharset = NULL; + opts->codepage = fat_default_codepage; + opts->iocharset = fat_default_iocharset; if (is_vfat) opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; else @@ -433,11 +443,12 @@ static int parse_options(char *options, int is_vfat, int *debug, /* vfat specific */ case Opt_charset: - if (opts->iocharset) + if (opts->iocharset != fat_default_iocharset) kfree(opts->iocharset); - opts->iocharset = match_strdup(&args[0]); - if (opts->iocharset == NULL) + iocharset = match_strdup(&args[0]); + if (!iocharset) return -ENOMEM; + opts->iocharset = iocharset; break; case Opt_shortname_lower: opts->shortname = VFAT_SFN_DISPLAY_LOWER @@ -486,9 +497,15 @@ static int parse_options(char *options, int is_vfat, int *debug, return -EINVAL; } } + /* UTF8 doesn't provide FAT semantics */ + if (!strcmp(opts->iocharset, "utf8")) { + printk(KERN_ERR "FAT: utf8 is not a recommended IO charset" + " for FAT filesystems, filesystem will be case sensitive!\n"); + } + if (opts->unicode_xlate) opts->utf8 = 0; - + return 0; } @@ -768,66 +785,6 @@ static struct export_operations fat_export_ops = { .get_parent = fat_get_parent, }; -static int fat_load_nls(struct super_block *sb) -{ - struct msdos_sb_info *sbi = MSDOS_SB(sb); - struct fat_mount_options *opts = &sbi->options; - char codepage[50], *iocharset; - int error = 0, not_specified = 0; - - if (opts->codepage) - snprintf(codepage, sizeof(codepage), "cp%d", opts->codepage); - else { - not_specified = 1; - strcpy(codepage, "default"); - } - sbi->nls_disk = load_nls(codepage); - if (sbi->nls_disk == NULL) { - printk(KERN_ERR "FAT: codepage %s not found\n", codepage); - error = -EINVAL; - goto out; - } - - if (opts->isvfat) { - if (opts->iocharset) - iocharset = opts->iocharset; - else { - not_specified = 1; - iocharset = "default"; - } - /* - * FIXME: utf8 is using iocharset for upper/lower conversion - * UTF8 doesn't provide FAT semantics - */ - if (!strcmp(iocharset, "utf8")) { - printk(KERN_WARNING - "FAT: utf8 is not a recommended IO charset" - " for FAT filesystem," - " filesystem will be case sensitive!\n"); - } - sbi->nls_io = load_nls(iocharset); - if (sbi->nls_io == NULL) { - printk(KERN_ERR "FAT: IO charset %s not found\n", - iocharset); - error = -EINVAL; - goto out; - } - } - - if (not_specified) { - unsigned long not_ro = !(sb->s_flags & MS_RDONLY); - if (not_ro) - sb->s_flags |= MS_RDONLY; - - printk(KERN_INFO "FAT: %s option didn't specified\n" - " File name can not access proper%s\n", - opts->isvfat ? "codepage or iocharset" : "codepage", - not_ro ? " (mounted as read-only)" : ""); - } -out: - return error; -} - /* * Read the super block of an MS-DOS FS. */ @@ -843,6 +800,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int debug, first; unsigned int media; long error; + char buf[50]; sbi = kmalloc(sizeof(struct msdos_sb_info), GFP_KERNEL); if (!sbi) @@ -1057,9 +1015,23 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, goto out_invalid; } - error = fat_load_nls(sb); - if (error) + error = -EINVAL; + sprintf(buf, "cp%d", sbi->options.codepage); + sbi->nls_disk = load_nls(buf); + if (!sbi->nls_disk) { + printk(KERN_ERR "FAT: codepage %s not found\n", buf); goto out_fail; + } + + /* FIXME: utf8 is using iocharset for upper/lower conversion */ + if (sbi->options.isvfat) { + sbi->nls_io = load_nls(sbi->options.iocharset); + if (!sbi->nls_io) { + printk(KERN_ERR "FAT: IO charset %s not found\n", + sbi->options.iocharset); + goto out_fail; + } + } error = -ENOMEM; root_inode = new_inode(sb); @@ -1093,7 +1065,7 @@ out_fail: unload_nls(sbi->nls_io); if (sbi->nls_disk) unload_nls(sbi->nls_disk); - if (sbi->options.iocharset) + if (sbi->options.iocharset != fat_default_iocharset) kfree(sbi->options.iocharset); sb->s_fs_info = NULL; kfree(sbi); diff --git a/fs/fifo.c b/fs/fifo.c index 7a6a018303d7..a045fa71630c 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -45,6 +45,9 @@ static int fifo_open(struct inode *inode, struct file *filp) } filp->f_version = 0; + /* We can only do regular read/write on fifos */ + filp->f_mode &= (FMODE_READ | FMODE_WRITE); + switch (filp->f_mode) { case 1: /* diff --git a/fs/file_table.c b/fs/file_table.c index 5d56ec5db141..6e97427ff0d8 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -117,7 +117,7 @@ int open_private_file(struct file *filp, struct dentry *dentry, int flags) memset(filp, 0, sizeof(*filp)); eventpoll_init_file(filp); filp->f_flags = flags; - filp->f_mode = (flags+1) & O_ACCMODE; + filp->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; atomic_set(&filp->f_count, 1); filp->f_dentry = dentry; filp->f_mapping = dentry->d_inode->i_mapping; diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 8f69595f9f0a..18a678ce2591 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1773,14 +1773,10 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); - /* - * Now we have the locks, check again to see whether kjournald has - * taken the buffer off the transaction. - */ - if (!buffer_jbd(bh)) - goto zap_buffer; + jh = journal_grab_journal_head(bh); + if (!jh) + goto zap_buffer_no_jh; - jh = bh2jh(bh); transaction = jh->b_transaction; if (transaction == NULL) { /* First case: not on any transaction. If it @@ -1811,6 +1807,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); + journal_put_journal_head(jh); return ret; } else { /* There is no currently-running transaction. So the @@ -1824,6 +1821,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); + journal_put_journal_head(jh); return ret; } else { /* The orphan record's transaction has @@ -1847,6 +1845,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); + journal_put_journal_head(jh); return 0; } else { /* Good, the buffer belongs to the running transaction. @@ -1860,6 +1859,8 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } zap_buffer: + journal_put_journal_head(jh); +zap_buffer_no_jh: spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 8d6b1f49bc24..9764dfa1c563 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -74,7 +74,7 @@ decode_fh(u32 *p, struct svc_fh *fhp) static inline u32 * encode_fh(u32 *p, struct svc_fh *fhp) { - int size = fhp->fh_handle.fh_size; + unsigned int size = fhp->fh_handle.fh_size; *p++ = htonl(size); if (size) p[XDR_QUADLEN(size)-1]=0; memcpy(p, &fhp->fh_handle.fh_base, size); @@ -328,7 +328,7 @@ int nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p, struct nfsd3_readargs *args) { - int len; + unsigned int len; int v,pn; if (!(p = decode_fh(p, &args->fh)) @@ -358,7 +358,7 @@ int nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, struct nfsd3_writeargs *args) { - int len, v; + unsigned int len, v, hdr; if (!(p = decode_fh(p, &args->fh)) || !(p = xdr_decode_hyper(p, &args->offset))) @@ -368,9 +368,12 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, args->stable = ntohl(*p++); len = args->len = ntohl(*p++); + hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; + if (rqstp->rq_arg.len < len + hdr) + return 0; + args->vec[0].iov_base = (void*)p; - args->vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - - (((void*)p) - rqstp->rq_arg.head[0].iov_base); + args->vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; if (len > NFSSVC_MAXBLKSIZE) len = NFSSVC_MAXBLKSIZE; @@ -427,7 +430,7 @@ int nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd3_symlinkargs *args) { - int len; + unsigned int len; int avail; char *old, *new; struct kvec *vec; @@ -444,7 +447,7 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p, */ svc_take_page(rqstp); len = ntohl(*p++); - if (len <= 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE) + if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE) return 0; args->tname = new = page_address(rqstp->rq_respages[rqstp->rq_resused-1]); args->tlen = len; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 4df0dedef709..0ff4425cae9a 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1140,10 +1140,9 @@ int status; if (share_access & NFS4_SHARE_ACCESS_WRITE) { status = get_write_access(filp->f_dentry->d_inode); - if (!status) - filp->f_mode = FMODE_WRITE; - else + if (status) return nfserrno(status); + filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ; } return nfs_ok; } @@ -1153,7 +1152,7 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access) { if (share_access & NFS4_SHARE_ACCESS_WRITE) { put_write_access(filp->f_dentry->d_inode); - filp->f_mode = FMODE_READ; + filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE; } } diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 1d582f746bea..d978123a6867 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -234,7 +234,7 @@ int nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_readargs *args) { - int len; + unsigned int len; int v,pn; if (!(p = decode_fh(p, &args->fh))) return 0; @@ -266,7 +266,7 @@ int nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_writeargs *args) { - int len; + unsigned int len; int v; if (!(p = decode_fh(p, &args->fh))) return 0; diff --git a/fs/open.c b/fs/open.c index 854c5de744db..8e539937ceca 100644 --- a/fs/open.c +++ b/fs/open.c @@ -781,7 +781,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) if (!f) goto cleanup_dentry; f->f_flags = flags; - f->f_mode = (flags+1) & O_ACCMODE; + f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; inode = dentry->d_inode; if (f->f_mode & FMODE_WRITE) { error = get_write_access(inode); @@ -1070,3 +1070,15 @@ int generic_file_open(struct inode * inode, struct file * filp) } EXPORT_SYMBOL(generic_file_open); + +/* + * This is used by subsystems that don't want seekable + * file descriptors + */ +int nonseekable_open(struct inode *inode, struct file *filp) +{ + filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); + return 0; +} + +EXPORT_SYMBOL(nonseekable_open); diff --git a/fs/pipe.c b/fs/pipe.c index 737271c0c9b9..2b42a25a414e 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -94,10 +94,6 @@ pipe_readv(struct file *filp, const struct iovec *_iov, struct iovec *iov = (struct iovec *)_iov; size_t total_len; - /* pread is not allowed on pipes. */ - if (unlikely(ppos != &filp->f_pos)) - return -ESPIPE; - total_len = iov_length(iov, nr_segs); /* Null read succeeds. */ if (unlikely(total_len == 0)) @@ -187,10 +183,6 @@ pipe_writev(struct file *filp, const struct iovec *_iov, struct iovec *iov = (struct iovec *)_iov; size_t total_len; - /* pwrite is not allowed on pipes. */ - if (unlikely(ppos != &filp->f_pos)) - return -ESPIPE; - total_len = iov_length(iov, nr_segs); /* Null write succeeds. */ if (unlikely(total_len == 0)) @@ -656,13 +648,13 @@ int do_pipe(int *fd) f1->f_pos = f2->f_pos = 0; f1->f_flags = O_RDONLY; f1->f_op = &read_pipe_fops; - f1->f_mode = 1; + f1->f_mode = FMODE_READ; f1->f_version = 0; /* write file */ f2->f_flags = O_WRONLY; f2->f_op = &write_pipe_fops; - f2->f_mode = 2; + f2->f_mode = FMODE_WRITE; f2->f_version = 0; fd_install(i, f1); diff --git a/fs/read_write.c b/fs/read_write.c index 481332642515..d85431d5d09e 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -113,9 +113,12 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int origin) { loff_t (*fn)(struct file *, loff_t, int); - fn = default_llseek; - if (file->f_op && file->f_op->llseek) - fn = file->f_op->llseek; + fn = no_llseek; + if (file->f_mode & FMODE_LSEEK) { + fn = default_llseek; + if (file->f_op && file->f_op->llseek) + fn = file->f_op->llseek; + } return fn(file, offset, origin); } EXPORT_SYMBOL(vfs_llseek); @@ -267,6 +270,16 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ EXPORT_SYMBOL(vfs_write); +static inline loff_t file_pos_read(struct file *file) +{ + return file->f_pos; +} + +static inline void file_pos_write(struct file *file, loff_t pos) +{ + file->f_pos = pos; +} + asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) { struct file *file; @@ -275,7 +288,9 @@ asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) file = fget_light(fd, &fput_needed); if (file) { - ret = vfs_read(file, buf, count, &file->f_pos); + loff_t pos = file_pos_read(file); + ret = vfs_read(file, buf, count, &pos); + file_pos_write(file, pos); fput_light(file, fput_needed); } @@ -291,7 +306,9 @@ asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t co file = fget_light(fd, &fput_needed); if (file) { - ret = vfs_write(file, buf, count, &file->f_pos); + loff_t pos = file_pos_read(file); + ret = vfs_write(file, buf, count, &pos); + file_pos_write(file, pos); fput_light(file, fput_needed); } @@ -310,7 +327,9 @@ asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf, file = fget_light(fd, &fput_needed); if (file) { - ret = vfs_read(file, buf, count, &pos); + ret = -ESPIPE; + if (file->f_mode & FMODE_PREAD) + ret = vfs_read(file, buf, count, &pos); fput_light(file, fput_needed); } @@ -329,7 +348,9 @@ asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf, file = fget_light(fd, &fput_needed); if (file) { - ret = vfs_write(file, buf, count, &pos); + ret = -ESPIPE; + if (file->f_mode & FMODE_PWRITE) + ret = vfs_write(file, buf, count, &pos); fput_light(file, fput_needed); } @@ -513,7 +534,9 @@ sys_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen) file = fget_light(fd, &fput_needed); if (file) { - ret = vfs_readv(file, vec, vlen, &file->f_pos); + loff_t pos = file_pos_read(file); + ret = vfs_readv(file, vec, vlen, &pos); + file_pos_write(file, pos); fput_light(file, fput_needed); } @@ -529,7 +552,9 @@ sys_writev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen) file = fget_light(fd, &fput_needed); if (file) { - ret = vfs_writev(file, vec, vlen, &file->f_pos); + loff_t pos = file_pos_read(file); + ret = vfs_writev(file, vec, vlen, &pos); + file_pos_write(file, pos); fput_light(file, fput_needed); } @@ -560,8 +585,12 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, goto fput_in; if (!in_file->f_op || !in_file->f_op->sendfile) goto fput_in; + retval = -ESPIPE; if (!ppos) ppos = &in_file->f_pos; + else + if (!(in_file->f_mode & FMODE_PREAD)) + goto fput_in; retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, *ppos, count); if (retval) goto fput_in; diff --git a/fs/seq_file.c b/fs/seq_file.c index 8bd7097f3cfb..5a73e085fb4e 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -35,6 +35,9 @@ int seq_open(struct file *file, struct seq_operations *op) sema_init(&p->sem, 1); p->op = op; file->private_data = p; + + /* SEQ files support lseek, but not pread/pwrite */ + file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); return 0; } EXPORT_SYMBOL(seq_open); @@ -54,9 +57,6 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) void *p; int err = 0; - if (ppos != &file->f_pos) - return -EPIPE; - down(&m->sem); /* grab buffer if we didn't have one */ if (!m->buf) { diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index 570d1a942507..4a173d3d8916 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c @@ -46,12 +46,13 @@ xfs_stats_clear_proc_handler( int write, struct file *filp, void *buffer, - size_t *lenp) + size_t *lenp, + loff_t *ppos) { int c, ret, *valp = ctl->data; __uint32_t vn_active; - ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp); + ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp, ppos); if (!ret && write && *valp) { printk("XFS Clearing xfsstats\n"); diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h index 68be9d57c7d0..973316828f02 100644 --- a/include/asm-ia64/pgalloc.h +++ b/include/asm-ia64/pgalloc.h @@ -37,14 +37,20 @@ static inline pgd_t* pgd_alloc_one_fast (struct mm_struct *mm) { - unsigned long *ret = pgd_quicklist; + unsigned long *ret = NULL; + preempt_disable(); + + ret = pgd_quicklist; if (likely(ret != NULL)) { pgd_quicklist = (unsigned long *)(*ret); ret[0] = 0; --pgtable_cache_size; } else ret = NULL; + + preempt_enable(); + return (pgd_t *) ret; } @@ -65,9 +71,11 @@ pgd_alloc (struct mm_struct *mm) static inline void pgd_free (pgd_t *pgd) { + preempt_disable(); *(unsigned long *)pgd = (unsigned long) pgd_quicklist; pgd_quicklist = (unsigned long *) pgd; ++pgtable_cache_size; + preempt_enable(); } static inline void @@ -80,13 +88,19 @@ pgd_populate (struct mm_struct *mm, pgd_t *pgd_entry, pmd_t *pmd) static inline pmd_t* pmd_alloc_one_fast (struct mm_struct *mm, unsigned long addr) { - unsigned long *ret = (unsigned long *)pmd_quicklist; + unsigned long *ret = NULL; + preempt_disable(); + + ret = (unsigned long *)pmd_quicklist; if (likely(ret != NULL)) { pmd_quicklist = (unsigned long *)(*ret); ret[0] = 0; --pgtable_cache_size; } + + preempt_enable(); + return (pmd_t *)ret; } @@ -103,9 +117,11 @@ pmd_alloc_one (struct mm_struct *mm, unsigned long addr) static inline void pmd_free (pmd_t *pmd) { + preempt_disable(); *(unsigned long *)pmd = (unsigned long) pmd_quicklist; pmd_quicklist = (unsigned long *) pmd; ++pgtable_cache_size; + preempt_enable(); } #define __pmd_free_tlb(tlb, pmd) pmd_free(pmd) diff --git a/include/asm-ppc/ppc405_dma.h b/include/asm-ppc/ppc405_dma.h deleted file mode 100644 index 489eec55be3d..000000000000 --- a/include/asm-ppc/ppc405_dma.h +++ /dev/null @@ -1,1271 +0,0 @@ -/* - * Author: Pete Popov <ppopov@mvista.com> - * - * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - * - * Data structures specific to the IBM PowerPC 405 on-chip DMA controller - * and API. - */ - -#ifdef __KERNEL__ -#ifndef __ASMPPC_405_DMA_H -#define __ASMPPC_405_DMA_H - -#include <linux/types.h> - -/* #define DEBUG_405DMA */ - -#define TRUE 1 -#define FALSE 0 - -#define SGL_LIST_SIZE 4096 -/* #define PCI_ALLOC_IS_NONCONSISTENT */ - -#define MAX_405GP_DMA_CHANNELS 4 - -/* The maximum address that we can perform a DMA transfer to on this platform */ -/* Doesn't really apply... */ -#define MAX_DMA_ADDRESS 0xFFFFFFFF - -extern unsigned long ISA_DMA_THRESHOLD; - -#define dma_outb outb -#define dma_inb inb - - -/* - * Function return status codes - * These values are used to indicate whether or not the function - * call was successful, or a bad/invalid parameter was passed. - */ -#define DMA_STATUS_GOOD 0 -#define DMA_STATUS_BAD_CHANNEL 1 -#define DMA_STATUS_BAD_HANDLE 2 -#define DMA_STATUS_BAD_MODE 3 -#define DMA_STATUS_NULL_POINTER 4 -#define DMA_STATUS_OUT_OF_MEMORY 5 -#define DMA_STATUS_SGL_LIST_EMPTY 6 -#define DMA_STATUS_GENERAL_ERROR 7 - - -/* - * These indicate status as returned from the DMA Status Register. - */ -#define DMA_STATUS_NO_ERROR 0 -#define DMA_STATUS_CS 1 /* Count Status */ -#define DMA_STATUS_TS 2 /* Transfer Status */ -#define DMA_STATUS_DMA_ERROR 3 /* DMA Error Occurred */ -#define DMA_STATUS_DMA_BUSY 4 /* The channel is busy */ - - -/* - * Transfer Modes - * These modes are defined in a way that makes it possible to - * simply "or" in the value in the control register. - */ -#define DMA_MODE_READ DMA_TD /* Peripheral to Memory */ -#define DMA_MODE_WRITE 0 /* Memory to Peripheral */ -#define DMA_MODE_MM (SET_DMA_TM(TM_S_MM)) /* memory to memory */ - - /* Device-paced memory to memory, */ - /* device is at source address */ -#define DMA_MODE_MM_DEVATSRC (DMA_TD | SET_DMA_TM(TM_D_MM)) - - /* Device-paced memory to memory, */ - /* device is at destination address */ -#define DMA_MODE_MM_DEVATDST (SET_DMA_TM(TM_D_MM)) - - -/* - * DMA Polarity Configuration Register - */ -#define DMAReq0_ActiveLow (1<<31) -#define DMAAck0_ActiveLow (1<<30) -#define EOT0_ActiveLow (1<<29) /* End of Transfer */ - -#define DMAReq1_ActiveLow (1<<28) -#define DMAAck1_ActiveLow (1<<27) -#define EOT1_ActiveLow (1<<26) - -#define DMAReq2_ActiveLow (1<<25) -#define DMAAck2_ActiveLow (1<<24) -#define EOT2_ActiveLow (1<<23) - -#define DMAReq3_ActiveLow (1<<22) -#define DMAAck3_ActiveLow (1<<21) -#define EOT3_ActiveLow (1<<20) - -/* - * DMA Sleep Mode Register - */ -#define SLEEP_MODE_ENABLE (1<<21) - - -/* - * DMA Status Register - */ -#define DMA_CS0 (1<<31) /* Terminal Count has been reached */ -#define DMA_CS1 (1<<30) -#define DMA_CS2 (1<<29) -#define DMA_CS3 (1<<28) - -#define DMA_TS0 (1<<27) /* End of Transfer has been requested */ -#define DMA_TS1 (1<<26) -#define DMA_TS2 (1<<25) -#define DMA_TS3 (1<<24) - -#define DMA_CH0_ERR (1<<23) /* DMA Chanel 0 Error */ -#define DMA_CH1_ERR (1<<22) -#define DMA_CH2_ERR (1<<21) -#define DMA_CH3_ERR (1<<20) - -#define DMA_IN_DMA_REQ0 (1<<19) /* Internal DMA Request is pending */ -#define DMA_IN_DMA_REQ1 (1<<18) -#define DMA_IN_DMA_REQ2 (1<<17) -#define DMA_IN_DMA_REQ3 (1<<16) - -#define DMA_EXT_DMA_REQ0 (1<<15) /* External DMA Request is pending */ -#define DMA_EXT_DMA_REQ1 (1<<14) -#define DMA_EXT_DMA_REQ2 (1<<13) -#define DMA_EXT_DMA_REQ3 (1<<12) - -#define DMA_CH0_BUSY (1<<11) /* DMA Channel 0 Busy */ -#define DMA_CH1_BUSY (1<<10) -#define DMA_CH2_BUSY (1<<9) -#define DMA_CH3_BUSY (1<<8) - -#define DMA_SG0 (1<<7) /* DMA Channel 0 Scatter/Gather in progress */ -#define DMA_SG1 (1<<6) -#define DMA_SG2 (1<<5) -#define DMA_SG3 (1<<4) - - - -/* - * DMA Channel Control Registers - */ -#define DMA_CH_ENABLE (1<<31) /* DMA Channel Enable */ -#define SET_DMA_CH_ENABLE(x) (((x)&0x1)<<31) -#define GET_DMA_CH_ENABLE(x) (((x)&DMA_CH_ENABLE)>>31) - -#define DMA_CIE_ENABLE (1<<30) /* DMA Channel Interrupt Enable */ -#define SET_DMA_CIE_ENABLE(x) (((x)&0x1)<<30) -#define GET_DMA_CIE_ENABLE(x) (((x)&DMA_CIE_ENABLE)>>30) - -#define DMA_TD (1<<29) -#define SET_DMA_TD(x) (((x)&0x1)<<29) -#define GET_DMA_TD(x) (((x)&DMA_TD)>>29) - -#define DMA_PL (1<<28) /* Peripheral Location */ -#define SET_DMA_PL(x) (((x)&0x1)<<28) -#define GET_DMA_PL(x) (((x)&DMA_PL)>>28) - -#define EXTERNAL_PERIPHERAL 0 -#define INTERNAL_PERIPHERAL 1 - - -#define SET_DMA_PW(x) (((x)&0x3)<<26) /* Peripheral Width */ -#define DMA_PW_MASK SET_DMA_PW(3) -#define PW_8 0 -#define PW_16 1 -#define PW_32 2 -#define PW_64 3 -#define GET_DMA_PW(x) (((x)&DMA_PW_MASK)>>26) - -#define DMA_DAI (1<<25) /* Destination Address Increment */ -#define SET_DMA_DAI(x) (((x)&0x1)<<25) - -#define DMA_SAI (1<<24) /* Source Address Increment */ -#define SET_DMA_SAI(x) (((x)&0x1)<<24) - -#define DMA_BEN (1<<23) /* Buffer Enable */ -#define SET_DMA_BEN(x) (((x)&0x1)<<23) - -#define SET_DMA_TM(x) (((x)&0x3)<<21) /* Transfer Mode */ -#define DMA_TM_MASK SET_DMA_TM(3) -#define TM_PERIPHERAL 0 /* Peripheral */ -#define TM_RESERVED 1 /* Reserved */ -#define TM_S_MM 2 /* Memory to Memory */ -#define TM_D_MM 3 /* Device Paced Memory to Memory */ -#define GET_DMA_TM(x) (((x)&DMA_TM_MASK)>>21) - -#define SET_DMA_PSC(x) (((x)&0x3)<<19) /* Peripheral Setup Cycles */ -#define DMA_PSC_MASK SET_DMA_PSC(3) -#define GET_DMA_PSC(x) (((x)&DMA_PSC_MASK)>>19) - -#define SET_DMA_PWC(x) (((x)&0x3F)<<13) /* Peripheral Wait Cycles */ -#define DMA_PWC_MASK SET_DMA_PWC(0x3F) -#define GET_DMA_PWC(x) (((x)&DMA_PWC_MASK)>>13) - -#define SET_DMA_PHC(x) (((x)&0x7)<<10) /* Peripheral Hold Cycles */ -#define DMA_PHC_MASK SET_DMA_PHC(0x7) -#define GET_DMA_PHC(x) (((x)&DMA_PHC_MASK)>>10) - -#define DMA_ETD_OUTPUT (1<<9) /* EOT pin is a TC output */ -#define SET_DMA_ETD(x) (((x)&0x1)<<9) - -#define DMA_TCE_ENABLE (1<<8) -#define SET_DMA_TCE(x) (((x)&0x1)<<8) - -#define SET_DMA_PRIORITY(x) (((x)&0x3)<<6) /* DMA Channel Priority */ -#define DMA_PRIORITY_MASK SET_DMA_PRIORITY(3) -#define PRIORITY_LOW 0 -#define PRIORITY_MID_LOW 1 -#define PRIORITY_MID_HIGH 2 -#define PRIORITY_HIGH 3 -#define GET_DMA_PRIORITY(x) (((x)&DMA_PRIORITY_MASK)>>6) - -#define SET_DMA_PREFETCH(x) (((x)&0x3)<<4) /* Memory Read Prefetch */ -#define DMA_PREFETCH_MASK SET_DMA_PREFETCH(3) -#define PREFETCH_1 0 /* Prefetch 1 Double Word */ -#define PREFETCH_2 1 -#define PREFETCH_4 2 -#define GET_DMA_PREFETCH(x) (((x)&DMA_PREFETCH_MASK)>>4) - -#define DMA_PCE (1<<3) /* Parity Check Enable */ -#define SET_DMA_PCE(x) (((x)&0x1)<<3) -#define GET_DMA_PCE(x) (((x)&DMA_PCE)>>3) - -#define DMA_DEC (1<<2) /* Address Decrement */ -#define SET_DMA_DEC(x) (((x)&0x1)<<2) -#define GET_DMA_DEC(x) (((x)&DMA_DEC)>>2) - -/* - * DMA SG Command Register - */ -#define SSG0_ENABLE (1<<31) /* Start Scatter Gather */ -#define SSG1_ENABLE (1<<30) -#define SSG2_ENABLE (1<<29) -#define SSG3_ENABLE (1<<28) -#define SSG0_MASK_ENABLE (1<<15) /* Enable writing to SSG0 bit */ -#define SSG1_MASK_ENABLE (1<<14) -#define SSG2_MASK_ENABLE (1<<13) -#define SSG3_MASK_ENABLE (1<<12) - - -/* - * DMA Scatter/Gather Descriptor Bit fields - */ -#define SG_LINK (1<<31) /* Link */ -#define SG_TCI_ENABLE (1<<29) /* Enable Terminal Count Interrupt */ -#define SG_ETI_ENABLE (1<<28) /* Enable End of Transfer Interrupt */ -#define SG_ERI_ENABLE (1<<27) /* Enable Error Interrupt */ -#define SG_COUNT_MASK 0xFFFF /* Count Field */ - - - - -typedef uint32_t sgl_handle_t; - -typedef struct { - - /* - * Valid polarity settings: - * DMAReq0_ActiveLow - * DMAAck0_ActiveLow - * EOT0_ActiveLow - * - * DMAReq1_ActiveLow - * DMAAck1_ActiveLow - * EOT1_ActiveLow - * - * DMAReq2_ActiveLow - * DMAAck2_ActiveLow - * EOT2_ActiveLow - * - * DMAReq3_ActiveLow - * DMAAck3_ActiveLow - * EOT3_ActiveLow - */ - unsigned int polarity; - - char buffer_enable; /* Boolean: buffer enable */ - char tce_enable; /* Boolean: terminal count enable */ - char etd_output; /* Boolean: eot pin is a tc output */ - char pce; /* Boolean: parity check enable */ - - /* - * Peripheral location: - * INTERNAL_PERIPHERAL (UART0 on the 405GP) - * EXTERNAL_PERIPHERAL - */ - char pl; /* internal/external peripheral */ - - /* - * Valid pwidth settings: - * PW_8 - * PW_16 - * PW_32 - * PW_64 - */ - unsigned int pwidth; - - char dai; /* Boolean: dst address increment */ - char sai; /* Boolean: src address increment */ - - /* - * Valid psc settings: 0-3 - */ - unsigned int psc; /* Peripheral Setup Cycles */ - - /* - * Valid pwc settings: - * 0-63 - */ - unsigned int pwc; /* Peripheral Wait Cycles */ - - /* - * Valid phc settings: - * 0-7 - */ - unsigned int phc; /* Peripheral Hold Cycles */ - - /* - * Valid cp (channel priority) settings: - * PRIORITY_LOW - * PRIORITY_MID_LOW - * PRIORITY_MID_HIGH - * PRIORITY_HIGH - */ - unsigned int cp; /* channel priority */ - - /* - * Valid pf (memory read prefetch) settings: - * - * PREFETCH_1 - * PREFETCH_2 - * PREFETCH_4 - */ - unsigned int pf; /* memory read prefetch */ - - /* - * Boolean: channel interrupt enable - * NOTE: for sgl transfers, only the last descriptor will be setup to - * interrupt. - */ - char int_enable; - - char shift; /* easy access to byte_count shift, based on */ - /* the width of the channel */ - - uint32_t control; /* channel control word */ - - - /* These variabled are used ONLY in single dma transfers */ - unsigned int mode; /* transfer mode */ - dma_addr_t addr; - -} ppc_dma_ch_t; - - -typedef struct { - uint32_t control; - uint32_t src_addr; - uint32_t dst_addr; - uint32_t control_count; - uint32_t next; -} ppc_sgl_t; - - - -typedef struct { - unsigned int dmanr; - uint32_t control; /* channel ctrl word; loaded from each descrptr */ - uint32_t sgl_control; /* LK, TCI, ETI, and ERI bits in sgl descriptor */ - dma_addr_t dma_addr; /* dma (physical) address of this list */ - ppc_sgl_t *phead; - ppc_sgl_t *ptail; - -} sgl_list_info_t; - - -typedef struct { - unsigned int *src_addr; - unsigned int *dst_addr; - dma_addr_t dma_src_addr; - dma_addr_t dma_dst_addr; -} pci_alloc_desc_t; - - -extern ppc_dma_ch_t dma_channels[]; - -/* - * - * DMA API inline functions - * These functions are implemented here as inline functions for - * performance reasons. - * - */ - -static __inline__ int get_405gp_dma_status(void) -{ - return (mfdcr(DCRN_DMASR)); -} - - -static __inline__ int enable_405gp_dma(unsigned int dmanr) -{ - unsigned int control; - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - -#ifdef DEBUG_405DMA - if (dmanr >= MAX_405GP_DMA_CHANNELS) { - printk("enable_dma: bad channel: %d\n", dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif - - - switch (dmanr) { - case 0: - if (p_dma_ch->mode == DMA_MODE_READ) { - /* peripheral to memory */ - mtdcr(DCRN_DMASA0, NULL); - mtdcr(DCRN_DMADA0, p_dma_ch->addr); - } - else if (p_dma_ch->mode == DMA_MODE_WRITE) { - /* memory to peripheral */ - mtdcr(DCRN_DMASA0, p_dma_ch->addr); - mtdcr(DCRN_DMADA0, NULL); - } - /* for other xfer modes, the addresses are already set */ - control = mfdcr(DCRN_DMACR0); - control &= ~(DMA_TM_MASK | DMA_TD); /* clear all mode bits */ - control |= (p_dma_ch->mode | DMA_CH_ENABLE); - mtdcr(DCRN_DMACR0, control); - break; - case 1: - if (p_dma_ch->mode == DMA_MODE_READ) { - mtdcr(DCRN_DMASA1, NULL); - mtdcr(DCRN_DMADA1, p_dma_ch->addr); - } else if (p_dma_ch->mode == DMA_MODE_WRITE) { - mtdcr(DCRN_DMASA1, p_dma_ch->addr); - mtdcr(DCRN_DMADA1, NULL); - } - control = mfdcr(DCRN_DMACR1); - control &= ~(DMA_TM_MASK | DMA_TD); - control |= (p_dma_ch->mode | DMA_CH_ENABLE); - mtdcr(DCRN_DMACR1, control); - break; - case 2: - if (p_dma_ch->mode == DMA_MODE_READ) { - mtdcr(DCRN_DMASA2, NULL); - mtdcr(DCRN_DMADA2, p_dma_ch->addr); - } else if (p_dma_ch->mode == DMA_MODE_WRITE) { - mtdcr(DCRN_DMASA2, p_dma_ch->addr); - mtdcr(DCRN_DMADA2, NULL); - } - control = mfdcr(DCRN_DMACR2); - control &= ~(DMA_TM_MASK | DMA_TD); - control |= (p_dma_ch->mode | DMA_CH_ENABLE); - mtdcr(DCRN_DMACR2, control); - break; - case 3: - if (p_dma_ch->mode == DMA_MODE_READ) { - mtdcr(DCRN_DMASA3, NULL); - mtdcr(DCRN_DMADA3, p_dma_ch->addr); - } else if (p_dma_ch->mode == DMA_MODE_WRITE) { - mtdcr(DCRN_DMASA3, p_dma_ch->addr); - mtdcr(DCRN_DMADA3, NULL); - } - control = mfdcr(DCRN_DMACR3); - control &= ~(DMA_TM_MASK | DMA_TD); - control |= (p_dma_ch->mode | DMA_CH_ENABLE); - mtdcr(DCRN_DMACR3, control); - break; - default: - return DMA_STATUS_BAD_CHANNEL; - } - return DMA_STATUS_GOOD; -} - - - -static __inline__ void disable_405gp_dma(unsigned int dmanr) -{ - unsigned int control; - - switch (dmanr) { - case 0: - control = mfdcr(DCRN_DMACR0); - control &= ~DMA_CH_ENABLE; - mtdcr(DCRN_DMACR0, control); - break; - case 1: - control = mfdcr(DCRN_DMACR1); - control &= ~DMA_CH_ENABLE; - mtdcr(DCRN_DMACR1, control); - break; - case 2: - control = mfdcr(DCRN_DMACR2); - control &= ~DMA_CH_ENABLE; - mtdcr(DCRN_DMACR2, control); - break; - case 3: - control = mfdcr(DCRN_DMACR3); - control &= ~DMA_CH_ENABLE; - mtdcr(DCRN_DMACR3, control); - break; - default: -#ifdef DEBUG_405DMA - printk("disable_dma: bad channel: %d\n", dmanr); -#endif - } -} - - - -/* - * Sets the dma mode for single DMA transfers only. - * For scatter/gather transfers, the mode is passed to the - * alloc_dma_handle() function as one of the parameters. - * - * The mode is simply saved and used later. This allows - * the driver to call set_dma_mode() and set_dma_addr() in - * any order. - * - * Valid mode values are: - * - * DMA_MODE_READ peripheral to memory - * DMA_MODE_WRITE memory to peripheral - * DMA_MODE_MM memory to memory - * DMA_MODE_MM_DEVATSRC device-paced memory to memory, device at src - * DMA_MODE_MM_DEVATDST device-paced memory to memory, device at dst - */ -static __inline__ int set_405gp_dma_mode(unsigned int dmanr, unsigned int mode) -{ - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - -#ifdef DEBUG_405DMA - switch (mode) { - case DMA_MODE_READ: - case DMA_MODE_WRITE: - case DMA_MODE_MM: - case DMA_MODE_MM_DEVATSRC: - case DMA_MODE_MM_DEVATDST: - break; - default: - printk("set_dma_mode: bad mode 0x%x\n", mode); - return DMA_STATUS_BAD_MODE; - } - if (dmanr >= MAX_405GP_DMA_CHANNELS) { - printk("set_dma_mode: bad channel 0x%x\n", dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif - - p_dma_ch->mode = mode; - return DMA_STATUS_GOOD; -} - - - -/* - * Sets the DMA Count register. Note that 'count' is in bytes. - * However, the DMA Count register counts the number of "transfers", - * where each transfer is equal to the bus width. Thus, count - * MUST be a multiple of the bus width. - */ -static __inline__ void -set_405gp_dma_count(unsigned int dmanr, unsigned int count) -{ - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - -#ifdef DEBUG_405DMA - { - int error = 0; - switch(p_dma_ch->pwidth) { - case PW_8: - break; - case PW_16: - if (count & 0x1) - error = 1; - break; - case PW_32: - if (count & 0x3) - error = 1; - break; - case PW_64: - if (count & 0x7) - error = 1; - break; - default: - printk("set_dma_count: invalid bus width: 0x%x\n", - p_dma_ch->pwidth); - return; - } - if (error) - printk("Warning: set_dma_count count 0x%x bus width %d\n", - count, p_dma_ch->pwidth); - } -#endif - - count = count >> p_dma_ch->shift; - switch (dmanr) { - case 0: - mtdcr(DCRN_DMACT0, count); - break; - case 1: - mtdcr(DCRN_DMACT1, count); - break; - case 2: - mtdcr(DCRN_DMACT2, count); - break; - case 3: - mtdcr(DCRN_DMACT3, count); - break; - default: -#ifdef DEBUG_405DMA - printk("set_dma_count: bad channel: %d\n", dmanr); -#endif - } -} - - - -/* - * Returns the number of bytes left to be transfered. - * After a DMA transfer, this should return zero. - * Reading this while a DMA transfer is still in progress will return - * unpredictable results. - */ -static __inline__ int get_405gp_dma_residue(unsigned int dmanr) -{ - unsigned int count; - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - - switch (dmanr) { - case 0: - count = mfdcr(DCRN_DMACT0); - break; - case 1: - count = mfdcr(DCRN_DMACT1); - break; - case 2: - count = mfdcr(DCRN_DMACT2); - break; - case 3: - count = mfdcr(DCRN_DMACT3); - break; - default: -#ifdef DEBUG_405DMA - printk("get_dma_residue: bad channel: %d\n", dmanr); -#endif - return 0; - } - - return (count << p_dma_ch->shift); -} - - - -/* - * Sets the DMA address for a memory to peripheral or peripheral - * to memory transfer. The address is just saved in the channel - * structure for now and used later in enable_dma(). - */ -static __inline__ void set_405gp_dma_addr(unsigned int dmanr, dma_addr_t addr) -{ - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; -#ifdef DEBUG_405DMA - { - int error = 0; - switch(p_dma_ch->pwidth) { - case PW_8: - break; - case PW_16: - if ((unsigned)addr & 0x1) - error = 1; - break; - case PW_32: - if ((unsigned)addr & 0x3) - error = 1; - break; - case PW_64: - if ((unsigned)addr & 0x7) - error = 1; - break; - default: - printk("set_dma_addr: invalid bus width: 0x%x\n", - p_dma_ch->pwidth); - return; - } - if (error) - printk("Warning: set_dma_addr addr 0x%x bus width %d\n", - addr, p_dma_ch->pwidth); - } -#endif - - /* save dma address and program it later after we know the xfer mode */ - p_dma_ch->addr = addr; -} - - - - -/* - * Sets both DMA addresses for a memory to memory transfer. - * For memory to peripheral or peripheral to memory transfers - * the function set_dma_addr() should be used instead. - */ -static __inline__ void -set_405gp_dma_addr2(unsigned int dmanr, dma_addr_t src_dma_addr, - dma_addr_t dst_dma_addr) -{ -#ifdef DEBUG_405DMA - { - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - int error = 0; - switch(p_dma_ch->pwidth) { - case PW_8: - break; - case PW_16: - if (((unsigned)src_dma_addr & 0x1) || - ((unsigned)dst_dma_addr & 0x1) - ) - error = 1; - break; - case PW_32: - if (((unsigned)src_dma_addr & 0x3) || - ((unsigned)dst_dma_addr & 0x3) - ) - error = 1; - break; - case PW_64: - if (((unsigned)src_dma_addr & 0x7) || - ((unsigned)dst_dma_addr & 0x7) - ) - error = 1; - break; - default: - printk("set_dma_addr2: invalid bus width: 0x%x\n", - p_dma_ch->pwidth); - return; - } - if (error) - printk("Warning: set_dma_addr2 src 0x%x dst 0x%x bus width %d\n", - src_dma_addr, dst_dma_addr, p_dma_ch->pwidth); - } -#endif - - switch (dmanr) { - case 0: - mtdcr(DCRN_DMASA0, src_dma_addr); - mtdcr(DCRN_DMADA0, dst_dma_addr); - break; - case 1: - mtdcr(DCRN_DMASA1, src_dma_addr); - mtdcr(DCRN_DMADA1, dst_dma_addr); - break; - case 2: - mtdcr(DCRN_DMASA2, src_dma_addr); - mtdcr(DCRN_DMADA2, dst_dma_addr); - break; - case 3: - mtdcr(DCRN_DMASA3, src_dma_addr); - mtdcr(DCRN_DMADA3, dst_dma_addr); - break; - default: -#ifdef DEBUG_405DMA - printk("set_dma_addr2: bad channel: %d\n", dmanr); -#endif - } -} - - - -/* - * Enables the channel interrupt. - * - * If performing a scatter/gatter transfer, this function - * MUST be called before calling alloc_dma_handle() and building - * the sgl list. Otherwise, interrupts will not be enabled, if - * they were previously disabled. - */ -static __inline__ int -enable_405gp_dma_interrupt(unsigned int dmanr) -{ - unsigned int control; - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - - p_dma_ch->int_enable = TRUE; - switch (dmanr) { - case 0: - control = mfdcr(DCRN_DMACR0); - control|= DMA_CIE_ENABLE; /* Channel Interrupt Enable */ - mtdcr(DCRN_DMACR0, control); - break; - case 1: - control = mfdcr(DCRN_DMACR1); - control|= DMA_CIE_ENABLE; - mtdcr(DCRN_DMACR1, control); - break; - case 2: - control = mfdcr(DCRN_DMACR2); - control|= DMA_CIE_ENABLE; - mtdcr(DCRN_DMACR2, control); - break; - case 3: - control = mfdcr(DCRN_DMACR3); - control|= DMA_CIE_ENABLE; - mtdcr(DCRN_DMACR3, control); - break; - default: -#ifdef DEBUG_405DMA - printk("enable_dma_interrupt: bad channel: %d\n", dmanr); -#endif - return DMA_STATUS_BAD_CHANNEL; - } - return DMA_STATUS_GOOD; -} - - - -/* - * Disables the channel interrupt. - * - * If performing a scatter/gatter transfer, this function - * MUST be called before calling alloc_dma_handle() and building - * the sgl list. Otherwise, interrupts will not be disabled, if - * they were previously enabled. - */ -static __inline__ int -disable_405gp_dma_interrupt(unsigned int dmanr) -{ - unsigned int control; - ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr]; - - p_dma_ch->int_enable = TRUE; - switch (dmanr) { - case 0: - control = mfdcr(DCRN_DMACR0); - control &= ~DMA_CIE_ENABLE; /* Channel Interrupt Enable */ - mtdcr(DCRN_DMACR0, control); - break; - case 1: - control = mfdcr(DCRN_DMACR1); - control &= ~DMA_CIE_ENABLE; - mtdcr(DCRN_DMACR1, control); - break; - case 2: - control = mfdcr(DCRN_DMACR2); - control &= ~DMA_CIE_ENABLE; - mtdcr(DCRN_DMACR2, control); - break; - case 3: - control = mfdcr(DCRN_DMACR3); - control &= ~DMA_CIE_ENABLE; - mtdcr(DCRN_DMACR3, control); - break; - default: -#ifdef DEBUG_405DMA - printk("enable_dma_interrupt: bad channel: %d\n", dmanr); -#endif - return DMA_STATUS_BAD_CHANNEL; - } - return DMA_STATUS_GOOD; -} - - -#ifdef DCRNCAP_DMA_SG - -/* - * Add a new sgl descriptor to the end of a scatter/gather list - * which was created by alloc_dma_handle(). - * - * For a memory to memory transfer, both dma addresses must be - * valid. For a peripheral to memory transfer, one of the addresses - * must be set to NULL, depending on the direction of the transfer: - * memory to peripheral: set dst_addr to NULL, - * peripheral to memory: set src_addr to NULL. - */ -static __inline__ int -add_405gp_dma_sgl(sgl_handle_t handle, dma_addr_t src_addr, dma_addr_t dst_addr, - unsigned int count) -{ - sgl_list_info_t *psgl = (sgl_list_info_t *)handle; - ppc_dma_ch_t *p_dma_ch; - - if (!handle) { -#ifdef DEBUG_405DMA - printk("add_dma_sgl: null handle\n"); -#endif - return DMA_STATUS_BAD_HANDLE; - } - -#ifdef DEBUG_405DMA - if (psgl->dmanr >= MAX_405GP_DMA_CHANNELS) { - printk("add_dma_sgl error: psgl->dmanr == %d\n", psgl->dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif - - p_dma_ch = &dma_channels[psgl->dmanr]; - -#ifdef DEBUG_405DMA - { - int error = 0; - unsigned int aligned = (unsigned)src_addr | (unsigned)dst_addr | count; - switch(p_dma_ch->pwidth) { - case PW_8: - break; - case PW_16: - if (aligned & 0x1) - error = 1; - break; - case PW_32: - if (aligned & 0x3) - error = 1; - break; - case PW_64: - if (aligned & 0x7) - error = 1; - break; - default: - printk("add_dma_sgl: invalid bus width: 0x%x\n", - p_dma_ch->pwidth); - return DMA_STATUS_GENERAL_ERROR; - } - if (error) - printk("Alignment warning: add_dma_sgl src 0x%x dst 0x%x count 0x%x bus width var %d\n", - src_addr, dst_addr, count, p_dma_ch->pwidth); - - } -#endif - - if ((unsigned)(psgl->ptail + 1) >= ((unsigned)psgl + SGL_LIST_SIZE)) { -#ifdef DEBUG_405DMA - printk("sgl handle out of memory \n"); -#endif - return DMA_STATUS_OUT_OF_MEMORY; - } - - - if (!psgl->ptail) { - psgl->phead = (ppc_sgl_t *) - ((unsigned)psgl + sizeof(sgl_list_info_t)); - psgl->ptail = psgl->phead; - } else { - psgl->ptail->next = virt_to_bus(psgl->ptail + 1); - psgl->ptail++; - } - - psgl->ptail->control = psgl->control; - psgl->ptail->src_addr = src_addr; - psgl->ptail->dst_addr = dst_addr; - psgl->ptail->control_count = (count >> p_dma_ch->shift) | - psgl->sgl_control; - psgl->ptail->next = (uint32_t)NULL; - - return DMA_STATUS_GOOD; -} - - - -/* - * Enable (start) the DMA described by the sgl handle. - */ -static __inline__ void enable_405gp_dma_sgl(sgl_handle_t handle) -{ - sgl_list_info_t *psgl = (sgl_list_info_t *)handle; - ppc_dma_ch_t *p_dma_ch; - uint32_t sg_command; - -#ifdef DEBUG_405DMA - if (!handle) { - printk("enable_dma_sgl: null handle\n"); - return; - } else if (psgl->dmanr > (MAX_405GP_DMA_CHANNELS - 1)) { - printk("enable_dma_sgl: bad channel in handle %d\n", - psgl->dmanr); - return; - } else if (!psgl->phead) { - printk("enable_dma_sgl: sg list empty\n"); - return; - } -#endif - - p_dma_ch = &dma_channels[psgl->dmanr]; - psgl->ptail->control_count &= ~SG_LINK; /* make this the last dscrptr */ - sg_command = mfdcr(DCRN_ASGC); - - switch(psgl->dmanr) { - case 0: - mtdcr(DCRN_ASG0, virt_to_bus(psgl->phead)); - sg_command |= SSG0_ENABLE; - break; - case 1: - mtdcr(DCRN_ASG1, virt_to_bus(psgl->phead)); - sg_command |= SSG1_ENABLE; - break; - case 2: - mtdcr(DCRN_ASG2, virt_to_bus(psgl->phead)); - sg_command |= SSG2_ENABLE; - break; - case 3: - mtdcr(DCRN_ASG3, virt_to_bus(psgl->phead)); - sg_command |= SSG3_ENABLE; - break; - default: -#ifdef DEBUG_405DMA - printk("enable_dma_sgl: bad channel: %d\n", psgl->dmanr); -#endif - } - -#if 0 /* debug */ - printk("\n\nenable_dma_sgl at dma_addr 0x%x\n", - virt_to_bus(psgl->phead)); - { - ppc_sgl_t *pnext, *sgl_addr; - - pnext = psgl->phead; - while (pnext) { - printk("dma descriptor at 0x%x, dma addr 0x%x\n", - (unsigned)pnext, (unsigned)virt_to_bus(pnext)); - printk("control 0x%x src 0x%x dst 0x%x c_count 0x%x, next 0x%x\n", - (unsigned)pnext->control, (unsigned)pnext->src_addr, - (unsigned)pnext->dst_addr, - (unsigned)pnext->control_count, (unsigned)pnext->next); - - (unsigned)pnext = bus_to_virt(pnext->next); - } - printk("sg_command 0x%x\n", sg_command); - } -#endif - -#ifdef PCI_ALLOC_IS_NONCONSISTENT - /* - * This is temporary only, until pci_alloc_consistent() really does - * return "consistent" memory. - */ - flush_dcache_range((unsigned)handle, (unsigned)handle + SGL_LIST_SIZE); -#endif - - mtdcr(DCRN_ASGC, sg_command); /* start transfer */ -} - - - -/* - * Halt an active scatter/gather DMA operation. - */ -static __inline__ void disable_405gp_dma_sgl(sgl_handle_t handle) -{ - sgl_list_info_t *psgl = (sgl_list_info_t *)handle; - uint32_t sg_command; - -#ifdef DEBUG_405DMA - if (!handle) { - printk("enable_dma_sgl: null handle\n"); - return; - } else if (psgl->dmanr > (MAX_405GP_DMA_CHANNELS - 1)) { - printk("enable_dma_sgl: bad channel in handle %d\n", - psgl->dmanr); - return; - } -#endif - sg_command = mfdcr(DCRN_ASGC); - switch(psgl->dmanr) { - case 0: - sg_command &= ~SSG0_ENABLE; - break; - case 1: - sg_command &= ~SSG1_ENABLE; - break; - case 2: - sg_command &= ~SSG2_ENABLE; - break; - case 3: - sg_command &= ~SSG3_ENABLE; - break; - default: -#ifdef DEBUG_405DMA - printk("enable_dma_sgl: bad channel: %d\n", psgl->dmanr); -#endif - } - - mtdcr(DCRN_ASGC, sg_command); /* stop transfer */ -} - - - -/* - * Returns number of bytes left to be transferred from the entire sgl list. - * *src_addr and *dst_addr get set to the source/destination address of - * the sgl descriptor where the DMA stopped. - * - * An sgl transfer must NOT be active when this function is called. - */ -static __inline__ int -get_405gp_dma_sgl_residue(sgl_handle_t handle, dma_addr_t *src_addr, - dma_addr_t *dst_addr) -{ - sgl_list_info_t *psgl = (sgl_list_info_t *)handle; - ppc_dma_ch_t *p_dma_ch; - ppc_sgl_t *pnext, *sgl_addr; - uint32_t count_left; - -#ifdef DEBUG_405DMA - if (!handle) { - printk("get_dma_sgl_residue: null handle\n"); - return DMA_STATUS_BAD_HANDLE; - } else if (psgl->dmanr > (MAX_405GP_DMA_CHANNELS - 1)) { - printk("get_dma_sgl_residue: bad channel in handle %d\n", - psgl->dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif - - switch(psgl->dmanr) { - case 0: - sgl_addr = (ppc_sgl_t *)bus_to_virt(mfdcr(DCRN_ASG0)); - count_left = mfdcr(DCRN_DMACT0); - break; - case 1: - sgl_addr = (ppc_sgl_t *)bus_to_virt(mfdcr(DCRN_ASG1)); - count_left = mfdcr(DCRN_DMACT1); - break; - case 2: - sgl_addr = (ppc_sgl_t *)bus_to_virt(mfdcr(DCRN_ASG2)); - count_left = mfdcr(DCRN_DMACT2); - break; - case 3: - sgl_addr = (ppc_sgl_t *)bus_to_virt(mfdcr(DCRN_ASG3)); - count_left = mfdcr(DCRN_DMACT3); - break; - default: -#ifdef DEBUG_405DMA - printk("get_dma_sgl_residue: bad channel: %d\n", psgl->dmanr); -#endif - goto error; - } - - if (!sgl_addr) { -#ifdef DEBUG_405DMA - printk("get_dma_sgl_residue: sgl addr register is null\n"); -#endif - goto error; - } - - pnext = psgl->phead; - while (pnext && - ((unsigned)pnext < ((unsigned)psgl + SGL_LIST_SIZE) && - (pnext != sgl_addr)) - ) { - pnext = pnext++; - } - - if (pnext == sgl_addr) { /* found the sgl descriptor */ - - *src_addr = pnext->src_addr; - *dst_addr = pnext->dst_addr; - - /* - * Now search the remaining descriptors and add their count. - * We already have the remaining count from this descriptor in - * count_left. - */ - pnext++; - - while ((pnext != psgl->ptail) && - ((unsigned)pnext < ((unsigned)psgl + SGL_LIST_SIZE)) - ) { - count_left += pnext->control_count & SG_COUNT_MASK; - } - - if (pnext != psgl->ptail) { /* should never happen */ -#ifdef DEBUG_405DMA - printk("get_dma_sgl_residue error (1) psgl->ptail 0x%x handle 0x%x\n", - (unsigned int)psgl->ptail, - (unsigned int)handle); -#endif - goto error; - } - - /* success */ - p_dma_ch = &dma_channels[psgl->dmanr]; - return (count_left << p_dma_ch->shift); /* count in bytes */ - - } else { - /* this shouldn't happen */ -#ifdef DEBUG_405DMA - printk("get_dma_sgl_residue, unable to match current address 0x%x, handle 0x%x\n", - (unsigned int)sgl_addr, (unsigned int)handle); - -#endif - } - - -error: - *src_addr = (dma_addr_t)NULL; - *dst_addr = (dma_addr_t)NULL; - return 0; -} - - - - -/* - * Returns the address(es) of the buffer(s) contained in the head element of - * the scatter/gather list. The element is removed from the scatter/gather - * list and the next element becomes the head. - * - * This function should only be called when the DMA is not active. - */ -static __inline__ int -delete_405gp_dma_sgl_element(sgl_handle_t handle, dma_addr_t *src_dma_addr, - dma_addr_t *dst_dma_addr) -{ - sgl_list_info_t *psgl = (sgl_list_info_t *)handle; - -#ifdef DEBUG_405DMA - if (!handle) { - printk("delete_sgl_element: null handle\n"); - return DMA_STATUS_BAD_HANDLE; - } else if (psgl->dmanr > (MAX_405GP_DMA_CHANNELS - 1)) { - printk("delete_sgl_element: bad channel in handle %d\n", - psgl->dmanr); - return DMA_STATUS_BAD_CHANNEL; - } -#endif - - if (!psgl->phead) { -#ifdef DEBUG_405DMA - printk("delete_sgl_element: sgl list empty\n"); -#endif - *src_dma_addr = (dma_addr_t)NULL; - *dst_dma_addr = (dma_addr_t)NULL; - return DMA_STATUS_SGL_LIST_EMPTY; - } - - *src_dma_addr = (dma_addr_t)psgl->phead->src_addr; - *dst_dma_addr = (dma_addr_t)psgl->phead->dst_addr; - - if (psgl->phead == psgl->ptail) { - /* last descriptor on the list */ - psgl->phead = NULL; - psgl->ptail = NULL; - } else { - psgl->phead++; - } - - return DMA_STATUS_GOOD; -} - -#endif /* DCRNCAP_DMA_SG */ - -/* - * The rest of the DMA API, in ppc405_dma.c - */ -extern int hw_init_dma_channel(unsigned int, ppc_dma_ch_t *); -extern int get_channel_config(unsigned int, ppc_dma_ch_t *); -extern int set_channel_priority(unsigned int, unsigned int); -extern unsigned int get_peripheral_width(unsigned int); -extern int alloc_dma_handle(sgl_handle_t *, unsigned int, unsigned int); -extern void free_dma_handle(sgl_handle_t); - -#endif -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/ppc4xx_dma.h b/include/asm-ppc/ppc4xx_dma.h new file mode 100644 index 000000000000..5b82faff92dc --- /dev/null +++ b/include/asm-ppc/ppc4xx_dma.h @@ -0,0 +1,570 @@ +/* + * include/asm-ppc/ppc4xx_dma.h + * + * IBM PPC4xx DMA engine library + * + * Copyright 2000-2004 MontaVista Software Inc. + * + * Cleaned up a bit more, Matt Porter <mporter@kernel.crashing.org> + * + * Original code by Armin Kuster <akuster@mvista.com> + * and Pete Popov <ppopov@mvista.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __KERNEL__ +#ifndef __ASMPPC_PPC4xx_DMA_H +#define __ASMPPC_PPC4xx_DMA_H + +#include <linux/config.h> +#include <linux/types.h> +#include <asm/mmu.h> +#include <asm/ibm4xx.h> + +#undef DEBUG_4xxDMA + +#define MAX_PPC4xx_DMA_CHANNELS 4 + +/* in arch/ppc/kernel/setup.c -- Cort */ +extern unsigned long DMA_MODE_WRITE, DMA_MODE_READ; + +/* + * Function return status codes + * These values are used to indicate whether or not the function + * call was successful, or a bad/invalid parameter was passed. + */ +#define DMA_STATUS_GOOD 0 +#define DMA_STATUS_BAD_CHANNEL 1 +#define DMA_STATUS_BAD_HANDLE 2 +#define DMA_STATUS_BAD_MODE 3 +#define DMA_STATUS_NULL_POINTER 4 +#define DMA_STATUS_OUT_OF_MEMORY 5 +#define DMA_STATUS_SGL_LIST_EMPTY 6 +#define DMA_STATUS_GENERAL_ERROR 7 +#define DMA_STATUS_CHANNEL_NOTFREE 8 + +#define DMA_CHANNEL_BUSY 0x80000000 + +/* + * These indicate status as returned from the DMA Status Register. + */ +#define DMA_STATUS_NO_ERROR 0 +#define DMA_STATUS_CS 1 /* Count Status */ +#define DMA_STATUS_TS 2 /* Transfer Status */ +#define DMA_STATUS_DMA_ERROR 3 /* DMA Error Occurred */ +#define DMA_STATUS_DMA_BUSY 4 /* The channel is busy */ + + +/* + * DMA Channel Control Registers + */ + +#ifdef CONFIG_44x +#define PPC4xx_DMA_64BIT +#define DMA_CR_OFFSET 1 +#else +#define DMA_CR_OFFSET 0 +#endif + +#define DMA_CE_ENABLE (1<<31) /* DMA Channel Enable */ +#define SET_DMA_CE_ENABLE(x) (((x)&0x1)<<31) +#define GET_DMA_CE_ENABLE(x) (((x)&DMA_CE_ENABLE)>>31) + +#define DMA_CIE_ENABLE (1<<30) /* DMA Channel Interrupt Enable */ +#define SET_DMA_CIE_ENABLE(x) (((x)&0x1)<<30) +#define GET_DMA_CIE_ENABLE(x) (((x)&DMA_CIE_ENABLE)>>30) + +#define DMA_TD (1<<29) +#define SET_DMA_TD(x) (((x)&0x1)<<29) +#define GET_DMA_TD(x) (((x)&DMA_TD)>>29) + +#define DMA_PL (1<<28) /* Peripheral Location */ +#define SET_DMA_PL(x) (((x)&0x1)<<28) +#define GET_DMA_PL(x) (((x)&DMA_PL)>>28) + +#define EXTERNAL_PERIPHERAL 0 +#define INTERNAL_PERIPHERAL 1 + +#define SET_DMA_PW(x) (((x)&0x3)<<(26-DMA_CR_OFFSET)) /* Peripheral Width */ +#define DMA_PW_MASK SET_DMA_PW(3) +#define PW_8 0 +#define PW_16 1 +#define PW_32 2 +#define PW_64 3 +/* FIXME: Add PW_128 support for 440GP DMA block */ +#define GET_DMA_PW(x) (((x)&DMA_PW_MASK)>>(26-DMA_CR_OFFSET)) + +#define DMA_DAI (1<<(25-DMA_CR_OFFSET)) /* Destination Address Increment */ +#define SET_DMA_DAI(x) (((x)&0x1)<<(25-DMA_CR_OFFSET)) + +#define DMA_SAI (1<<(24-DMA_CR_OFFSET)) /* Source Address Increment */ +#define SET_DMA_SAI(x) (((x)&0x1)<<(24-DMA_CR_OFFSET)) + +#define DMA_BEN (1<<(23-DMA_CR_OFFSET)) /* Buffer Enable */ +#define SET_DMA_BEN(x) (((x)&0x1)<<(23-DMA_CR_OFFSET)) + +#define SET_DMA_TM(x) (((x)&0x3)<<(21-DMA_CR_OFFSET)) /* Transfer Mode */ +#define DMA_TM_MASK SET_DMA_TM(3) +#define TM_PERIPHERAL 0 /* Peripheral */ +#define TM_RESERVED 1 /* Reserved */ +#define TM_S_MM 2 /* Memory to Memory */ +#define TM_D_MM 3 /* Device Paced Memory to Memory */ +#define GET_DMA_TM(x) (((x)&DMA_TM_MASK)>>(21-DMA_CR_OFFSET)) + +#define SET_DMA_PSC(x) (((x)&0x3)<<(19-DMA_CR_OFFSET)) /* Peripheral Setup Cycles */ +#define DMA_PSC_MASK SET_DMA_PSC(3) +#define GET_DMA_PSC(x) (((x)&DMA_PSC_MASK)>>(19-DMA_CR_OFFSET)) + +#define SET_DMA_PWC(x) (((x)&0x3F)<<(13-DMA_CR_OFFSET)) /* Peripheral Wait Cycles */ +#define DMA_PWC_MASK SET_DMA_PWC(0x3F) +#define GET_DMA_PWC(x) (((x)&DMA_PWC_MASK)>>(13-DMA_CR_OFFSET)) + +#define SET_DMA_PHC(x) (((x)&0x7)<<(10-DMA_CR_OFFSET)) /* Peripheral Hold Cycles */ +#define DMA_PHC_MASK SET_DMA_PHC(0x7) +#define GET_DMA_PHC(x) (((x)&DMA_PHC_MASK)>>(10-DMA_CR_OFFSET)) + +#define DMA_ETD_OUTPUT (1<<(9-DMA_CR_OFFSET)) /* EOT pin is a TC output */ +#define SET_DMA_ETD(x) (((x)&0x1)<<(9-DMA_CR_OFFSET)) + +#define DMA_TCE_ENABLE (1<<(8-DMA_CR_OFFSET)) +#define SET_DMA_TCE(x) (((x)&0x1)<<(8-DMA_CR_OFFSET)) + +#define DMA_DEC (1<<(2) /* Address Decrement */ +#define SET_DMA_DEC(x) (((x)&0x1)<<2) +#define GET_DMA_DEC(x) (((x)&DMA_DEC)>>2) + +/* + * Transfer Modes + * These modes are defined in a way that makes it possible to + * simply "or" in the value in the control register. + */ + +#define DMA_MODE_MM (SET_DMA_TM(TM_S_MM)) /* memory to memory */ + + /* Device-paced memory to memory, */ + /* device is at source address */ +#define DMA_MODE_MM_DEVATSRC (DMA_TD | SET_DMA_TM(TM_D_MM)) + + /* Device-paced memory to memory, */ + /* device is at destination address */ +#define DMA_MODE_MM_DEVATDST (SET_DMA_TM(TM_D_MM)) + +/* 405gp/440gp */ +#define SET_DMA_PREFETCH(x) (((x)&0x3)<<(4-DMA_CR_OFFSET)) /* Memory Read Prefetch */ +#define DMA_PREFETCH_MASK SET_DMA_PREFETCH(3) +#define PREFETCH_1 0 /* Prefetch 1 Double Word */ +#define PREFETCH_2 1 +#define PREFETCH_4 2 +#define GET_DMA_PREFETCH(x) (((x)&DMA_PREFETCH_MASK)>>(4-DMA_CR_OFFSET)) + +#define DMA_PCE (1<<(3-DMA_CR_OFFSET)) /* Parity Check Enable */ +#define SET_DMA_PCE(x) (((x)&0x1)<<(3-DMA_CR_OFFSET)) +#define GET_DMA_PCE(x) (((x)&DMA_PCE)>>(3-DMA_CR_OFFSET)) + +/* stb3x */ + +#define DMA_ECE_ENABLE (1<<5) +#define SET_DMA_ECE(x) (((x)&0x1)<<5) +#define GET_DMA_ECE(x) (((x)&DMA_ECE_ENABLE)>>5) + +#define DMA_TCD_DISABLE (1<<4) +#define SET_DMA_TCD(x) (((x)&0x1)<<4) +#define GET_DMA_TCD(x) (((x)&DMA_TCD_DISABLE)>>4) + +typedef uint32_t sgl_handle_t; + +#ifdef CONFIG_PPC4xx_EDMA + +#define SGL_LIST_SIZE 4096 +#define DMA_PPC4xx_SIZE SGL_LIST_SIZE + +#define SET_DMA_PRIORITY(x) (((x)&0x3)<<(6-DMA_CR_OFFSET)) /* DMA Channel Priority */ +#define DMA_PRIORITY_MASK SET_DMA_PRIORITY(3) +#define PRIORITY_LOW 0 +#define PRIORITY_MID_LOW 1 +#define PRIORITY_MID_HIGH 2 +#define PRIORITY_HIGH 3 +#define GET_DMA_PRIORITY(x) (((x)&DMA_PRIORITY_MASK)>>(6-DMA_CR_OFFSET)) + +/* + * DMA Polarity Configuration Register + */ +#define DMAReq_ActiveLow(chan) (1<<(31-(chan*3))) +#define DMAAck_ActiveLow(chan) (1<<(30-(chan*3))) +#define EOT_ActiveLow(chan) (1<<(29-(chan*3))) /* End of Transfer */ + +/* + * DMA Sleep Mode Register + */ +#define SLEEP_MODE_ENABLE (1<<21) + +/* + * DMA Status Register + */ +#define DMA_CS0 (1<<31) /* Terminal Count has been reached */ +#define DMA_CS1 (1<<30) +#define DMA_CS2 (1<<29) +#define DMA_CS3 (1<<28) + +#define DMA_TS0 (1<<27) /* End of Transfer has been requested */ +#define DMA_TS1 (1<<26) +#define DMA_TS2 (1<<25) +#define DMA_TS3 (1<<24) + +#define DMA_CH0_ERR (1<<23) /* DMA Chanel 0 Error */ +#define DMA_CH1_ERR (1<<22) +#define DMA_CH2_ERR (1<<21) +#define DMA_CH3_ERR (1<<20) + +#define DMA_IN_DMA_REQ0 (1<<19) /* Internal DMA Request is pending */ +#define DMA_IN_DMA_REQ1 (1<<18) +#define DMA_IN_DMA_REQ2 (1<<17) +#define DMA_IN_DMA_REQ3 (1<<16) + +#define DMA_EXT_DMA_REQ0 (1<<15) /* External DMA Request is pending */ +#define DMA_EXT_DMA_REQ1 (1<<14) +#define DMA_EXT_DMA_REQ2 (1<<13) +#define DMA_EXT_DMA_REQ3 (1<<12) + +#define DMA_CH0_BUSY (1<<11) /* DMA Channel 0 Busy */ +#define DMA_CH1_BUSY (1<<10) +#define DMA_CH2_BUSY (1<<9) +#define DMA_CH3_BUSY (1<<8) + +#define DMA_SG0 (1<<7) /* DMA Channel 0 Scatter/Gather in progress */ +#define DMA_SG1 (1<<6) +#define DMA_SG2 (1<<5) +#define DMA_SG3 (1<<4) + +/* + * DMA SG Command Register + */ +#define SSG_ENABLE(chan) (1<<(31-chan)) /* Start Scatter Gather */ +#define SSG_MASK_ENABLE(chan) (1<<(15-chan)) /* Enable writing to SSG0 bit */ + +/* + * DMA Scatter/Gather Descriptor Bit fields + */ +#define SG_LINK (1<<31) /* Link */ +#define SG_TCI_ENABLE (1<<29) /* Enable Terminal Count Interrupt */ +#define SG_ETI_ENABLE (1<<28) /* Enable End of Transfer Interrupt */ +#define SG_ERI_ENABLE (1<<27) /* Enable Error Interrupt */ +#define SG_COUNT_MASK 0xFFFF /* Count Field */ + +#define SET_DMA_CONTROL \ + (SET_DMA_CIE_ENABLE(p_init->int_enable) | /* interrupt enable */ \ + SET_DMA_BEN(p_init->buffer_enable) | /* buffer enable */\ + SET_DMA_ETD(p_init->etd_output) | /* end of transfer pin */ \ + SET_DMA_TCE(p_init->tce_enable) | /* terminal count enable */ \ + SET_DMA_PL(p_init->pl) | /* peripheral location */ \ + SET_DMA_DAI(p_init->dai) | /* dest addr increment */ \ + SET_DMA_SAI(p_init->sai) | /* src addr increment */ \ + SET_DMA_PRIORITY(p_init->cp) | /* channel priority */ \ + SET_DMA_PW(p_init->pwidth) | /* peripheral/bus width */ \ + SET_DMA_PSC(p_init->psc) | /* peripheral setup cycles */ \ + SET_DMA_PWC(p_init->pwc) | /* peripheral wait cycles */ \ + SET_DMA_PHC(p_init->phc) | /* peripheral hold cycles */ \ + SET_DMA_PREFETCH(p_init->pf) /* read prefetch */) + +#define GET_DMA_POLARITY(chan) (DMAReq_ActiveLow(chan) | DMAAck_ActiveLow(chan) | EOT_ActiveLow(chan)) + +#elif defined(CONFIG_STBXXX_DMA) /* stb03xxx */ + +#define DMA_PPC4xx_SIZE 4096 + +/* + * DMA Status Register + */ + +#define SET_DMA_PRIORITY(x) (((x)&0x00800001)) /* DMA Channel Priority */ +#define DMA_PRIORITY_MASK 0x00800001 +#define PRIORITY_LOW 0x00000000 +#define PRIORITY_MID_LOW 0x00000001 +#define PRIORITY_MID_HIGH 0x00800000 +#define PRIORITY_HIGH 0x00800001 +#define GET_DMA_PRIORITY(x) (((((x)&DMA_PRIORITY_MASK) &0x00800000) >> 22 ) | (((x)&DMA_PRIORITY_MASK) &0x00000001)) + +#define DMA_CS0 (1<<31) /* Terminal Count has been reached */ +#define DMA_CS1 (1<<30) +#define DMA_CS2 (1<<29) +#define DMA_CS3 (1<<28) + +#define DMA_TS0 (1<<27) /* End of Transfer has been requested */ +#define DMA_TS1 (1<<26) +#define DMA_TS2 (1<<25) +#define DMA_TS3 (1<<24) + +#define DMA_CH0_ERR (1<<23) /* DMA Chanel 0 Error */ +#define DMA_CH1_ERR (1<<22) +#define DMA_CH2_ERR (1<<21) +#define DMA_CH3_ERR (1<<20) + +#define DMA_CT0 (1<<19) /* Chained transfere */ + +#define DMA_IN_DMA_REQ0 (1<<18) /* Internal DMA Request is pending */ +#define DMA_IN_DMA_REQ1 (1<<17) +#define DMA_IN_DMA_REQ2 (1<<16) +#define DMA_IN_DMA_REQ3 (1<<15) + +#define DMA_EXT_DMA_REQ0 (1<<14) /* External DMA Request is pending */ +#define DMA_EXT_DMA_REQ1 (1<<13) +#define DMA_EXT_DMA_REQ2 (1<<12) +#define DMA_EXT_DMA_REQ3 (1<<11) + +#define DMA_CH0_BUSY (1<<10) /* DMA Channel 0 Busy */ +#define DMA_CH1_BUSY (1<<9) +#define DMA_CH2_BUSY (1<<8) +#define DMA_CH3_BUSY (1<<7) + +#define DMA_CT1 (1<<6) /* Chained transfere */ +#define DMA_CT2 (1<<5) +#define DMA_CT3 (1<<4) + +#define DMA_CH_ENABLE (1<<7) +#define SET_DMA_CH(x) (((x)&0x1)<<7) +#define GET_DMA_CH(x) (((x)&DMA_CH_ENABLE)>>7) + +/* STBx25xxx dma unique */ +/* enable device port on a dma channel + * example ext 0 on dma 1 + */ + +#define SSP0_RECV 15 +#define SSP0_XMIT 14 +#define EXT_DMA_0 12 +#define SC1_XMIT 11 +#define SC1_RECV 10 +#define EXT_DMA_2 9 +#define EXT_DMA_3 8 +#define SERIAL2_XMIT 7 +#define SERIAL2_RECV 6 +#define SC0_XMIT 5 +#define SC0_RECV 4 +#define SERIAL1_XMIT 3 +#define SERIAL1_RECV 2 +#define SERIAL0_XMIT 1 +#define SERIAL0_RECV 0 + +#define DMA_CHAN_0 1 +#define DMA_CHAN_1 2 +#define DMA_CHAN_2 3 +#define DMA_CHAN_3 4 + +/* end STBx25xx */ + +/* + * Bit 30 must be one for Redwoods, otherwise transfers may receive errors. + */ +#define DMA_CR_MB0 0x2 + +#define SET_DMA_CONTROL \ + (SET_DMA_CIE_ENABLE(p_init->int_enable) | /* interrupt enable */ \ + SET_DMA_ETD(p_init->etd_output) | /* end of transfer pin */ \ + SET_DMA_TCE(p_init->tce_enable) | /* terminal count enable */ \ + SET_DMA_PL(p_init->pl) | /* peripheral location */ \ + SET_DMA_DAI(p_init->dai) | /* dest addr increment */ \ + SET_DMA_SAI(p_init->sai) | /* src addr increment */ \ + SET_DMA_PRIORITY(p_init->cp) | /* channel priority */ \ + SET_DMA_PW(p_init->pwidth) | /* peripheral/bus width */ \ + SET_DMA_PSC(p_init->psc) | /* peripheral setup cycles */ \ + SET_DMA_PWC(p_init->pwc) | /* peripheral wait cycles */ \ + SET_DMA_PHC(p_init->phc) | /* peripheral hold cycles */ \ + SET_DMA_TCD(p_init->tcd_disable) | /* TC chain mode disable */ \ + SET_DMA_ECE(p_init->ece_enable) | /* ECE chanin mode enable */ \ + SET_DMA_CH(p_init->ch_enable) | /* Chain enable */ \ + DMA_CR_MB0 /* must be one */) + +#define GET_DMA_POLARITY(chan) chan + +#endif + +typedef struct { + unsigned short in_use; /* set when channel is being used, clr when + * available. + */ + /* + * Valid polarity settings: + * DMAReq_ActiveLow(n) + * DMAAck_ActiveLow(n) + * EOT_ActiveLow(n) + * + * n is 0 to max dma chans + */ + unsigned int polarity; + + char buffer_enable; /* Boolean: buffer enable */ + char tce_enable; /* Boolean: terminal count enable */ + char etd_output; /* Boolean: eot pin is a tc output */ + char pce; /* Boolean: parity check enable */ + + /* + * Peripheral location: + * INTERNAL_PERIPHERAL (UART0 on the 405GP) + * EXTERNAL_PERIPHERAL + */ + char pl; /* internal/external peripheral */ + + /* + * Valid pwidth settings: + * PW_8 + * PW_16 + * PW_32 + * PW_64 + */ + unsigned int pwidth; + + char dai; /* Boolean: dst address increment */ + char sai; /* Boolean: src address increment */ + + /* + * Valid psc settings: 0-3 + */ + unsigned int psc; /* Peripheral Setup Cycles */ + + /* + * Valid pwc settings: + * 0-63 + */ + unsigned int pwc; /* Peripheral Wait Cycles */ + + /* + * Valid phc settings: + * 0-7 + */ + unsigned int phc; /* Peripheral Hold Cycles */ + + /* + * Valid cp (channel priority) settings: + * PRIORITY_LOW + * PRIORITY_MID_LOW + * PRIORITY_MID_HIGH + * PRIORITY_HIGH + */ + unsigned int cp; /* channel priority */ + + /* + * Valid pf (memory read prefetch) settings: + * + * PREFETCH_1 + * PREFETCH_2 + * PREFETCH_4 + */ + unsigned int pf; /* memory read prefetch */ + + /* + * Boolean: channel interrupt enable + * NOTE: for sgl transfers, only the last descriptor will be setup to + * interrupt. + */ + char int_enable; + + char shift; /* easy access to byte_count shift, based on */ + /* the width of the channel */ + + uint32_t control; /* channel control word */ + + /* These variabled are used ONLY in single dma transfers */ + unsigned int mode; /* transfer mode */ + phys_addr_t addr; + char ce; /* channel enable */ +#ifdef CONFIG_STB03xxx + char ch_enable; + char tcd_disable; + char ece_enable; + char td; /* transfer direction */ +#endif + +} ppc_dma_ch_t; + +/* + * PPC44x DMA implementations have a slightly different + * descriptor layout. Probably moved about due to the + * change to 64-bit addresses and link pointer. I don't + * know why they didn't just leave control_count after + * the dst_addr. + */ +#ifdef PPC4xx_DMA_64BIT +typedef struct { + uint32_t control; + uint32_t control_count; + phys_addr_t src_addr; + phys_addr_t dst_addr; + phys_addr_t next; +} ppc_sgl_t; +#else +typedef struct { + uint32_t control; + phys_addr_t src_addr; + phys_addr_t dst_addr; + uint32_t control_count; + uint32_t next; +} ppc_sgl_t; +#endif + +typedef struct { + unsigned int dmanr; + uint32_t control; /* channel ctrl word; loaded from each descrptr */ + uint32_t sgl_control; /* LK, TCI, ETI, and ERI bits in sgl descriptor */ + dma_addr_t dma_addr; /* dma (physical) address of this list */ + ppc_sgl_t *phead; + dma_addr_t phead_dma; + ppc_sgl_t *ptail; + dma_addr_t ptail_dma; +} sgl_list_info_t; + +typedef struct { + phys_addr_t *src_addr; + phys_addr_t *dst_addr; + phys_addr_t dma_src_addr; + phys_addr_t dma_dst_addr; +} pci_alloc_desc_t; + +extern ppc_dma_ch_t dma_channels[]; + +/* + * The DMA API are in ppc4xx_dma.c and ppc4xx_sgdma.c + */ +extern int ppc4xx_init_dma_channel(unsigned int, ppc_dma_ch_t *); +extern int ppc4xx_get_channel_config(unsigned int, ppc_dma_ch_t *); +extern int ppc4xx_set_channel_priority(unsigned int, unsigned int); +extern unsigned int ppc4xx_get_peripheral_width(unsigned int); +extern void ppc4xx_set_sg_addr(int, phys_addr_t); +extern int ppc4xx_add_dma_sgl(sgl_handle_t, phys_addr_t, phys_addr_t, unsigned int); +extern void ppc4xx_enable_dma_sgl(sgl_handle_t); +extern void ppc4xx_disable_dma_sgl(sgl_handle_t); +extern int ppc4xx_get_dma_sgl_residue(sgl_handle_t, phys_addr_t *, phys_addr_t *); +extern int ppc4xx_delete_dma_sgl_element(sgl_handle_t, phys_addr_t *, phys_addr_t *); +extern int ppc4xx_alloc_dma_handle(sgl_handle_t *, unsigned int, unsigned int); +extern void ppc4xx_free_dma_handle(sgl_handle_t); +extern int ppc4xx_get_dma_status(void); +extern void ppc4xx_set_src_addr(int dmanr, phys_addr_t src_addr); +extern void ppc4xx_set_dst_addr(int dmanr, phys_addr_t dst_addr); +extern void ppc4xx_enable_dma(unsigned int dmanr); +extern void ppc4xx_disable_dma(unsigned int dmanr); +extern void ppc4xx_set_dma_count(unsigned int dmanr, unsigned int count); +extern int ppc4xx_get_dma_residue(unsigned int dmanr); +extern void ppc4xx_set_dma_addr2(unsigned int dmanr, phys_addr_t src_dma_addr, + phys_addr_t dst_dma_addr); +extern int ppc4xx_enable_dma_interrupt(unsigned int dmanr); +extern int ppc4xx_disable_dma_interrupt(unsigned int dmanr); +extern int ppc4xx_clr_dma_status(unsigned int dmanr); +extern int ppc4xx_map_dma_port(unsigned int dmanr, unsigned int ocp_dma,short dma_chan); +extern int ppc4xx_disable_dma_port(unsigned int dmanr, unsigned int ocp_dma,short dma_chan); +extern int ppc4xx_set_dma_mode(unsigned int dmanr, unsigned int mode); + +/* These are in kernel/dma.c: */ + +/* reserve a DMA channel */ +extern int request_dma(unsigned int dmanr, const char *device_id); +/* release it again */ +extern void free_dma(unsigned int dmanr); +#endif +#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/irq.h b/include/asm-ppc64/irq.h index 6544827f7f4d..9c491814dbb5 100644 --- a/include/asm-ppc64/irq.h +++ b/include/asm-ppc64/irq.h @@ -9,8 +9,8 @@ * 2 of the License, or (at your option) any later version. */ +#include <linux/config.h> #include <linux/threads.h> -#include <asm/atomic.h> /* * Maximum number of interrupt sources that we can handle. @@ -46,6 +46,8 @@ static inline unsigned int virt_irq_to_real(unsigned int virt_irq) return virt_irq_to_real_map[virt_irq]; } +extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); + /* * Because many systems have two overlapping names spaces for * interrupts (ISA and XICS for example), and the ISA interrupts diff --git a/include/linux/coda_proc.h b/include/linux/coda_proc.h index 5bf752163790..c061a22ed86d 100644 --- a/include/linux/coda_proc.h +++ b/include/linux/coda_proc.h @@ -82,10 +82,10 @@ void reset_coda_cache_inv_stats( void ); * data structure for /proc/sys/... files */ int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, - void __user * buffer, size_t * lenp ); + void __user * buffer, size_t * lenp, loff_t * ppos ); int do_reset_coda_cache_inv_stats( ctl_table * table, int write, struct file * filp, void __user * buffer, - size_t * lenp ); + size_t * lenp, loff_t * ppos ); /* these functions are called to form the content of /proc/fs/coda/... files */ int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset, diff --git a/include/linux/dvb/osd.h b/include/linux/dvb/osd.h index 5ccf27457e1b..cdaff25eccc3 100644 --- a/include/linux/dvb/osd.h +++ b/include/linux/dvb/osd.h @@ -24,6 +24,8 @@ #ifndef _DVBOSD_H_ #define _DVBOSD_H_ +#include <linux/compiler.h> + typedef enum { // All functions return -2 on "not open" OSD_Close=1, // () diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h index 8fb2eb336336..2ed5d7bc4cbc 100644 --- a/include/linux/dvb/video.h +++ b/include/linux/dvb/video.h @@ -24,6 +24,8 @@ #ifndef _DVBVIDEO_H_ #define _DVBVIDEO_H_ +#include <linux/compiler.h> + #ifdef __KERNEL__ #include <linux/types.h> #else diff --git a/include/linux/fs.h b/include/linux/fs.h index 22dd6acdf9f1..e6f97b00fe34 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -75,6 +75,11 @@ extern int leases_enable, dir_notify_enable, lease_break_time; #define FMODE_READ 1 #define FMODE_WRITE 2 +/* Internal kernel extensions */ +#define FMODE_LSEEK 4 +#define FMODE_PREAD 8 +#define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */ + #define RW_MASK 1 #define RWA_MASK 2 #define READ 0 @@ -1430,6 +1435,7 @@ extern loff_t no_llseek(struct file *file, loff_t offset, int origin); extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); extern loff_t remote_llseek(struct file *file, loff_t offset, int origin); extern int generic_file_open(struct inode * inode, struct file * filp); +extern int nonseekable_open(struct inode * inode, struct file * filp); static inline void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 5e578c036157..954af9d82768 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -12,7 +12,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) return vma->vm_flags & VM_HUGETLB; } -int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *); +int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *); int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int); void zap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 8958b0e6af06..8a23709fe18a 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -374,9 +374,9 @@ static inline int is_normal(struct zone *zone) struct ctl_table; struct file; int min_free_kbytes_sysctl_handler(struct ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); int lower_zone_protection_sysctl_handler(struct ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); #include <linux/topology.h> /* Returns the number of the current Node. */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 53c73157ed74..5edb93f163c1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -362,8 +362,8 @@ struct net_device struct Qdisc *qdisc; struct Qdisc *qdisc_sleeping; - struct Qdisc *qdisc_list; struct Qdisc *qdisc_ingress; + struct list_head qdisc_list; unsigned long tx_queue_len; /* Max frames per queue allowed */ /* ingress path synchronizer */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 11f514844817..724d6841d0ae 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1108,6 +1108,22 @@ extern void skb_split(struct sk_buff *skb, extern void skb_init(void); extern void skb_add_mtu(int mtu); +struct skb_iter { + /* Iteration functions set these */ + unsigned char *data; + unsigned int len; + + /* Private to iteration */ + unsigned int nextfrag; + struct sk_buff *fraglist; +}; + +/* Keep iterating until skb_iter_next returns false. */ +extern void skb_iter_first(const struct sk_buff *skb, struct skb_iter *i); +extern int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i); +/* Call this if aborting loop before !skb_iter_next */ +extern void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i); + #ifdef CONFIG_NETFILTER static inline void nf_conntrack_put(struct nf_ct_info *nfct) { diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 38acd5d4b691..70ac59e6a41f 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -762,24 +762,24 @@ typedef int ctl_handler (ctl_table *table, int __user *name, int nlen, void **context); typedef int proc_handler (ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp); + void __user *buffer, size_t *lenp, loff_t *ppos); extern int proc_dostring(ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); extern int proc_dointvec(ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); extern int proc_dointvec_bset(ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); extern int proc_dointvec_minmax(ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); extern int proc_dointvec_jiffies(ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); extern int proc_dointvec_userhz_jiffies(ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); extern int proc_doulongvec_minmax(ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int, - struct file *, void __user *, size_t *); + struct file *, void __user *, size_t *, loff_t *); extern int do_sysctl (int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, diff --git a/include/linux/writeback.h b/include/linux/writeback.h index f557b55e8b0a..e4450070ac78 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -86,7 +86,7 @@ extern int laptop_mode; struct ctl_table; struct file; int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); void page_writeback_init(void); void balance_dirty_pages_ratelimited(struct address_space *mapping); diff --git a/include/net/ip.h b/include/net/ip.h index 70bb6f887988..bacccde1c078 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -301,7 +301,7 @@ extern int ipv4_proc_init(void); */ int ipv4_doint_and_flush(ctl_table *ctl, int write, struct file* filp, void __user *buffer, - size_t *lenp); + size_t *lenp, loff_t *ppos); int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen, diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 95684d3363c1..61d7033bca7f 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -103,7 +103,8 @@ extern int ndisc_ifinfo_sysctl_change(ctl_table *ctl, int write, struct file * filp, void __user *buffer, - size_t *lenp); + size_t *lenp, + loff_t *ppos); #endif extern void inet6_ifinfo_notify(int event, diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 159f8ebf4bb5..bce3aaf91235 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -77,12 +77,13 @@ struct Qdisc #define TCQ_F_BUILTIN 1 #define TCQ_F_THROTTLED 2 #define TCQ_F_INGRES 4 + int padded; struct Qdisc_ops *ops; - struct Qdisc *next; u32 handle; atomic_t refcnt; struct sk_buff_head q; struct net_device *dev; + struct list_head list; struct tc_stats stats; spinlock_t *stats_lock; @@ -93,10 +94,17 @@ struct Qdisc * and it will live until better solution will be invented. */ struct Qdisc *__parent; - - char data[0]; }; +#define QDISC_ALIGN 32 +#define QDISC_ALIGN_CONST (QDISC_ALIGN - 1) + +static inline void *qdisc_priv(struct Qdisc *q) +{ + return (char *)q + ((sizeof(struct Qdisc) + QDISC_ALIGN_CONST) + & ~QDISC_ALIGN_CONST); +} + struct qdisc_rate_table { struct tc_ratespec rate; diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index ef5ef24cda16..1c6d293846f0 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -214,25 +214,25 @@ static inline int scsi_status_is_good(int status) */ struct ccs_modesel_head { - u8 _r1; /* reserved */ - u8 medium; /* device-specific medium type */ - u8 _r2; /* reserved */ - u8 block_desc_length; /* block descriptor length */ - u8 density; /* device-specific density code */ - u8 number_blocks_hi; /* number of blocks in this block desc */ - u8 number_blocks_med; - u8 number_blocks_lo; - u8 _r3; - u8 block_length_hi; /* block length for blocks in this desc */ - u8 block_length_med; - u8 block_length_lo; + __u8 _r1; /* reserved */ + __u8 medium; /* device-specific medium type */ + __u8 _r2; /* reserved */ + __u8 block_desc_length; /* block descriptor length */ + __u8 density; /* device-specific density code */ + __u8 number_blocks_hi; /* number of blocks in this block desc */ + __u8 number_blocks_med; + __u8 number_blocks_lo; + __u8 _r3; + __u8 block_length_hi; /* block length for blocks in this desc */ + __u8 block_length_med; + __u8 block_length_lo; }; /* * ScsiLun: 8 byte LUN. */ struct scsi_lun { - u8 scsi_lun[8]; + __u8 scsi_lun[8]; }; /* diff --git a/include/scsi/sg.h b/include/scsi/sg.h index c8985dd1d4b2..0a487fe26d4f 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -1,6 +1,8 @@ #ifndef _SCSI_GENERIC_H #define _SCSI_GENERIC_H +#include <linux/compiler.h> + /* History: Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user diff --git a/include/sound/info.h b/include/sound/info.h index 9e33b58b8cce..29a6b83d1aeb 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -54,9 +54,11 @@ struct snd_info_entry_ops { int (*release) (snd_info_entry_t * entry, unsigned short mode, void *file_private_data); long (*read) (snd_info_entry_t *entry, void *file_private_data, - struct file * file, char __user *buf, long count); + struct file * file, char __user *buf, + unsigned long count, unsigned long pos); long (*write) (snd_info_entry_t *entry, void *file_private_data, - struct file * file, const char __user *buf, long count); + struct file * file, const char __user *buf, + unsigned long count, unsigned long pos); long long (*llseek) (snd_info_entry_t *entry, void *file_private_data, struct file * file, long long offset, int orig); unsigned int (*poll) (snd_info_entry_t *entry, void *file_private_data, diff --git a/kernel/sysctl.c b/kernel/sysctl.c index e7435ba0f35b..2a643c00e9ad 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -123,7 +123,7 @@ extern int acct_parm[]; static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t, ctl_table *, void **); static int proc_doutsstring(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp); + void __user *buffer, size_t *lenp, loff_t *ppos); static ctl_table root_table[]; static struct ctl_table_header root_table_header = @@ -1287,11 +1287,7 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf, res = count; - /* - * FIXME: we need to pass on ppos to the handler. - */ - - error = (*table->proc_handler) (table, write, file, buf, &res); + error = (*table->proc_handler) (table, write, file, buf, &res, ppos); if (error) return error; return res; @@ -1341,14 +1337,14 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf, * Returns 0 on success. */ int proc_dostring(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { size_t len; char __user *p; char c; if (!table->data || !table->maxlen || !*lenp || - (filp->f_pos && !write)) { + (*ppos && !write)) { *lenp = 0; return 0; } @@ -1368,7 +1364,7 @@ int proc_dostring(ctl_table *table, int write, struct file *filp, if(copy_from_user(table->data, buffer, len)) return -EFAULT; ((char *) table->data)[len] = 0; - filp->f_pos += *lenp; + *ppos += *lenp; } else { len = strlen(table->data); if (len > table->maxlen) @@ -1384,7 +1380,7 @@ int proc_dostring(ctl_table *table, int write, struct file *filp, len++; } *lenp = len; - filp->f_pos += len; + *ppos += len; } return 0; } @@ -1395,17 +1391,17 @@ int proc_dostring(ctl_table *table, int write, struct file *filp, */ static int proc_doutsstring(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int r; if (!write) { down_read(&uts_sem); - r=proc_dostring(table,0,filp,buffer,lenp); + r=proc_dostring(table,0,filp,buffer,lenp, ppos); up_read(&uts_sem); } else { down_write(&uts_sem); - r=proc_dostring(table,1,filp,buffer,lenp); + r=proc_dostring(table,1,filp,buffer,lenp, ppos); up_write(&uts_sem); } return r; @@ -1431,7 +1427,7 @@ static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp, } static int do_proc_dointvec(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp, + void __user *buffer, size_t *lenp, loff_t *ppos, int (*conv)(int *negp, unsigned long *lvalp, int *valp, int write, void *data), void *data) @@ -1445,7 +1441,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp, char __user *s = buffer; if (!table->data || !table->maxlen || !*lenp || - (filp->f_pos && !write)) { + (*ppos && !write)) { *lenp = 0; return 0; } @@ -1534,7 +1530,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp, if (write && first) return -EINVAL; *lenp -= left; - filp->f_pos += *lenp; + *ppos += *lenp; return 0; #undef TMPBUFLEN } @@ -1553,9 +1549,9 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp, * Returns 0 on success. */ int proc_dointvec(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { - return do_proc_dointvec(table,write,filp,buffer,lenp, + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, NULL,NULL); } @@ -1601,7 +1597,7 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp, */ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int op; @@ -1610,7 +1606,7 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, } op = (current->pid == 1) ? OP_SET : OP_AND; - return do_proc_dointvec(table,write,filp,buffer,lenp, + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, do_proc_dointvec_bset_conv,&op); } @@ -1660,19 +1656,20 @@ static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp, * Returns 0 on success. */ int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { struct do_proc_dointvec_minmax_conv_param param = { .min = (int *) table->extra1, .max = (int *) table->extra2, }; - return do_proc_dointvec(table, write, filp, buffer, lenp, + return do_proc_dointvec(table, write, filp, buffer, lenp, ppos, do_proc_dointvec_minmax_conv, ¶m); } static int do_proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp, + void __user *buffer, + size_t *lenp, loff_t *ppos, unsigned long convmul, unsigned long convdiv) { @@ -1684,7 +1681,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write, char __user *s = buffer; if (!table->data || !table->maxlen || !*lenp || - (filp->f_pos && !write)) { + (*ppos && !write)) { *lenp = 0; return 0; } @@ -1769,7 +1766,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write, if (write && first) return -EINVAL; *lenp -= left; - filp->f_pos += *lenp; + *ppos += *lenp; return 0; #undef TMPBUFLEN } @@ -1791,9 +1788,9 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write, * Returns 0 on success. */ int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { - return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, 1l, 1l); + return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l); } /** @@ -1815,10 +1812,11 @@ int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, */ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, + size_t *lenp, loff_t *ppos) { return do_proc_doulongvec_minmax(table, write, filp, buffer, - lenp, HZ, 1000l); + lenp, ppos, HZ, 1000l); } @@ -1880,9 +1878,9 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp, * Returns 0 on success. */ int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { - return do_proc_dointvec(table,write,filp,buffer,lenp, + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, do_proc_dointvec_jiffies_conv,NULL); } @@ -1902,65 +1900,66 @@ int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, * Returns 0 on success. */ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { - return do_proc_dointvec(table,write,filp,buffer,lenp, + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, do_proc_dointvec_userhz_jiffies_conv,NULL); } #else /* CONFIG_PROC_FS */ int proc_dostring(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } static int proc_doutsstring(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, + size_t *lenp, loff_t *ppos) { return -ENOSYS; } @@ -2111,50 +2110,51 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen, } int proc_dostring(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; } int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, + size_t *lenp, loff_t *ppos) { return -ENOSYS; } diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b1f5c9deede5..0b0935915066 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -668,8 +668,16 @@ int vsscanf(const char * buf, const char * fmt, va_list args) qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z' || *fmt == 'z') { - qualifier = *fmt; - fmt++; + qualifier = *fmt++; + if (unlikely(qualifier == *fmt)) { + if (qualifier == 'h') { + qualifier = 'H'; + fmt++; + } else if (qualifier == 'l') { + qualifier = 'L'; + fmt++; + } + } } base = 10; is_sign = 0; @@ -754,6 +762,15 @@ int vsscanf(const char * buf, const char * fmt, va_list args) break; switch(qualifier) { + case 'H': /* that's 'hh' in format */ + if (is_sign) { + signed char *s = (signed char *) va_arg(args,signed char *); + *s = (signed char) simple_strtol(str,&next,base); + } else { + unsigned char *s = (unsigned char *) va_arg(args, unsigned char *); + *s = (unsigned char) simple_strtoul(str, &next, base); + } + break; case 'h': if (is_sign) { short *s = (short *) va_arg(args,short *); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 1c1cf7daceac..6c522e127033 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -191,9 +191,9 @@ static unsigned long set_max_huge_pages(unsigned long count) #ifdef CONFIG_SYSCTL int hugetlb_sysctl_handler(struct ctl_table *table, int write, struct file *file, void __user *buffer, - size_t *length) + size_t *length, loff_t *ppos) { - proc_doulongvec_minmax(table, write, file, buffer, length); + proc_doulongvec_minmax(table, write, file, buffer, length, ppos); max_huge_pages = set_max_huge_pages(max_huge_pages); return 0; } diff --git a/mm/page-writeback.c b/mm/page-writeback.c index a2aa511adf9a..343998d46bb0 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -399,9 +399,9 @@ static void wb_kupdate(unsigned long arg) * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs */ int dirty_writeback_centisecs_handler(ctl_table *table, int write, - struct file *file, void __user *buffer, size_t *length) + struct file *file, void __user *buffer, size_t *length, loff_t *ppos) { - proc_dointvec(table, write, file, buffer, length); + proc_dointvec(table, write, file, buffer, length, ppos); if (dirty_writeback_centisecs) { mod_timer(&wb_timer, jiffies + (dirty_writeback_centisecs * HZ) / 100); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 60522982ad3f..6708f4f80b43 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1955,9 +1955,9 @@ module_init(init_per_zone_pages_min) * changes. */ int min_free_kbytes_sysctl_handler(ctl_table *table, int write, - struct file *file, void __user *buffer, size_t *length) + struct file *file, void __user *buffer, size_t *length, loff_t *ppos) { - proc_dointvec(table, write, file, buffer, length); + proc_dointvec(table, write, file, buffer, length, ppos); setup_per_zone_pages_min(); setup_per_zone_protection(); return 0; @@ -1969,9 +1969,9 @@ int min_free_kbytes_sysctl_handler(ctl_table *table, int write, * whenever sysctl_lower_zone_protection changes. */ int lower_zone_protection_sysctl_handler(ctl_table *table, int write, - struct file *file, void __user *buffer, size_t *length) + struct file *file, void __user *buffer, size_t *length, loff_t *ppos) { - proc_dointvec_minmax(table, write, file, buffer, length); + proc_dointvec_minmax(table, write, file, buffer, length, ppos); setup_per_zone_protection(); return 0; } diff --git a/net/atm/mpc.c b/net/atm/mpc.c index e629e89d4df4..ba4a1569dd60 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -3,6 +3,7 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/bitops.h> +#include <linux/seq_file.h> /* We are an ethernet device */ #include <linux/if_ether.h> @@ -224,29 +225,27 @@ int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry) return 0; } -void atm_mpoa_disp_qos(char *page, ssize_t *len) +/* this is buggered - we need locking for qos_head */ +void atm_mpoa_disp_qos(struct seq_file *m) { - unsigned char *ip; char ipaddr[16]; struct atm_mpoa_qos *qos; qos = qos_head; - *len += sprintf(page + *len, "QoS entries for shortcuts:\n"); - *len += sprintf(page + *len, "IP address\n TX:max_pcr pcr min_pcr max_cdv max_sdu\n RX:max_pcr pcr min_pcr max_cdv max_sdu\n"); + seq_printf(m, "QoS entries for shortcuts:\n"); + seq_printf(m, "IP address\n TX:max_pcr pcr min_pcr max_cdv max_sdu\n RX:max_pcr pcr min_pcr max_cdv max_sdu\n"); ipaddr[sizeof(ipaddr)-1] = '\0'; while (qos != NULL) { ip = (unsigned char *)&qos->ipaddr; sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip)); - *len += sprintf(page + *len, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n", + seq_printf(m, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n", NIPQUAD(ipaddr), qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu, qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu); qos = qos->next; } - - return; } static struct net_device *find_lec_by_itfnum(int itf) diff --git a/net/atm/mpc.h b/net/atm/mpc.h index c7b1108d01e4..cb6cbdd2294b 100644 --- a/net/atm/mpc.h +++ b/net/atm/mpc.h @@ -51,6 +51,7 @@ struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip); int atm_mpoa_delete_qos(struct atm_mpoa_qos *qos); /* Display QoS entries. This is for the procfs */ -void atm_mpoa_disp_qos(char *page, ssize_t *len); +struct seq_file; +void atm_mpoa_disp_qos(struct seq_file *m); #endif /* _MPC_H_ */ diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 714fe71aeda9..4f1849f9ab29 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -8,6 +8,7 @@ #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/time.h> +#include <linux/seq_file.h> #include <asm/uaccess.h> #include <linux/atmmpc.h> #include <linux/atm.h> @@ -30,31 +31,24 @@ extern struct mpoa_client *mpcs; extern struct proc_dir_entry *atm_proc_root; /* from proc.c. */ -static ssize_t proc_mpc_read(struct file *file, char __user *buff, - size_t count, loff_t *pos); - +static int proc_mpc_open(struct inode *inode, struct file *file); static ssize_t proc_mpc_write(struct file *file, const char __user *buff, size_t nbytes, loff_t *ppos); -static int parse_qos(const char *buff, int len); +static int parse_qos(const char *buff); /* * Define allowed FILE OPERATIONS */ static struct file_operations mpc_file_operations = { .owner = THIS_MODULE, - .read = proc_mpc_read, + .open = proc_mpc_open, + .read = seq_read, + .llseek = seq_lseek, .write = proc_mpc_write, + .release = seq_release, }; -static int print_header(char *buff,struct mpoa_client *mpc){ - if(mpc != NULL){ - return sprintf(buff,"\nInterface %d:\n\n",mpc->dev_num); - - } - return 0; -} - /* * Returns the state of an ingress cache entry as a string */ @@ -97,210 +91,173 @@ static const char *egress_state_string(int state){ } /* + * FIXME: mpcs (and per-mpc lists) have no locking whatsoever. + */ + +static void *mpc_start(struct seq_file *m, loff_t *pos) +{ + loff_t l = *pos; + struct mpoa_client *mpc; + + if (!l--) + return SEQ_START_TOKEN; + for (mpc = mpcs; mpc; mpc = mpc->next) + if (!l--) + return mpc; + return NULL; +} + +static void *mpc_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct mpoa_client *p = v; + (*pos)++; + return v == SEQ_START_TOKEN ? mpcs : p->next; +} + +static void mpc_stop(struct seq_file *m, void *v) +{ +} + +/* * READING function - called when the /proc/atm/mpoa file is read from. */ -static ssize_t proc_mpc_read(struct file *file, char __user *buff, - size_t count, loff_t *pos){ - unsigned long page = 0; +static ssize_t mpc_show(struct seq_file *m, void *v) +{ + struct mpoa_client *mpc = v; unsigned char *temp; - ssize_t length = 0; - int i = 0; - struct mpoa_client *mpc = mpcs; + int i; in_cache_entry *in_entry; eg_cache_entry *eg_entry; struct timeval now; unsigned char ip_string[16]; - if(count == 0) - return 0; - page = get_zeroed_page(GFP_KERNEL); - if(!page) - return -ENOMEM; - atm_mpoa_disp_qos((char *)page, &length); - while(mpc != NULL){ - length += print_header((char *)page + length, mpc); - length += sprintf((char *)page + length,"Ingress Entries:\nIP address State Holding time Packets fwded VPI VCI\n"); - in_entry = mpc->in_cache; - do_gettimeofday(&now); - while(in_entry != NULL){ - temp = (unsigned char *)&in_entry->ctrl_info.in_dst_ip; sprintf(ip_string,"%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]); - length += sprintf((char *)page + length,"%-16s%s%-14lu%-12u", ip_string, ingress_state_string(in_entry->entry_state), (in_entry->ctrl_info.holding_time-(now.tv_sec-in_entry->tv.tv_sec)), in_entry->packets_fwded); - if(in_entry->shortcut) - length += sprintf((char *)page + length," %-3d %-3d",in_entry->shortcut->vpi,in_entry->shortcut->vci); - length += sprintf((char *)page + length,"\n"); - in_entry = in_entry->next; - } - length += sprintf((char *)page + length,"\n"); - eg_entry = mpc->eg_cache; - length += sprintf((char *)page + length,"Egress Entries:\nIngress MPC ATM addr\nCache-id State Holding time Packets recvd Latest IP addr VPI VCI\n"); - while(eg_entry != NULL){ - for(i=0;i<ATM_ESA_LEN;i++){ - length += sprintf((char *)page + length,"%02x",eg_entry->ctrl_info.in_MPC_data_ATM_addr[i]);} - length += sprintf((char *)page + length,"\n%-16lu%s%-14lu%-15u",(unsigned long) ntohl(eg_entry->ctrl_info.cache_id), egress_state_string(eg_entry->entry_state), (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)), eg_entry->packets_rcvd); - - /* latest IP address */ - temp = (unsigned char *)&eg_entry->latest_ip_addr; - sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]); - length += sprintf((char *)page + length, "%-16s", ip_string); - - if(eg_entry->shortcut) - length += sprintf((char *)page + length," %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci); - length += sprintf((char *)page + length,"\n"); - eg_entry = eg_entry->next; - } - length += sprintf((char *)page + length,"\n"); - mpc = mpc->next; + + if (v == SEQ_START_TOKEN) { + atm_mpoa_disp_qos(m); + return 0; } - if (*pos >= length) length = 0; - else { - if ((count + *pos) > length) count = length - *pos; - if (copy_to_user(buff, (char *)page , count)) { - free_page(page); - return -EFAULT; - } - *pos += count; + seq_printf(m, "\nInterface %d:\n\n", mpc->dev_num); + seq_printf(m, "Ingress Entries:\nIP address State Holding time Packets fwded VPI VCI\n"); + do_gettimeofday(&now); + + for (in_entry = mpc->in_cache; in_entry; in_entry = in_entry->next) { + temp = (unsigned char *)&in_entry->ctrl_info.in_dst_ip; + sprintf(ip_string,"%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]); + seq_printf(m, "%-16s%s%-14lu%-12u", + ip_string, + ingress_state_string(in_entry->entry_state), + in_entry->ctrl_info.holding_time-(now.tv_sec-in_entry->tv.tv_sec), + in_entry->packets_fwded); + if (in_entry->shortcut) + seq_printf(m, " %-3d %-3d",in_entry->shortcut->vpi,in_entry->shortcut->vci); + seq_printf(m, "\n"); } - free_page(page); - return length; + seq_printf(m, "\n"); + seq_printf(m, "Egress Entries:\nIngress MPC ATM addr\nCache-id State Holding time Packets recvd Latest IP addr VPI VCI\n"); + for (eg_entry = mpc->eg_cache; eg_entry; eg_entry = eg_entry->next) { + unsigned char *p = eg_entry->ctrl_info.in_MPC_data_ATM_addr; + for(i = 0; i < ATM_ESA_LEN; i++) + seq_printf(m, "%02x", p[i]); + seq_printf(m, "\n%-16lu%s%-14lu%-15u", + (unsigned long)ntohl(eg_entry->ctrl_info.cache_id), + egress_state_string(eg_entry->entry_state), + (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)), + eg_entry->packets_rcvd); + + /* latest IP address */ + temp = (unsigned char *)&eg_entry->latest_ip_addr; + sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]); + seq_printf(m, "%-16s", ip_string); + + if (eg_entry->shortcut) + seq_printf(m, " %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci); + seq_printf(m, "\n"); + } + seq_printf(m, "\n"); + return 0; +} + +static struct seq_operations mpc_op = { + .start = mpc_start, + .next = mpc_next, + .stop = mpc_stop, + .show = mpc_show +}; + +static int proc_mpc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &mpc_op); } static ssize_t proc_mpc_write(struct file *file, const char __user *buff, size_t nbytes, loff_t *ppos) { - int incoming, error, retval; - char *page, c; - const char __user *tmp; + char *page, *p; + unsigned len; - if (nbytes == 0) return 0; - if (nbytes >= PAGE_SIZE) nbytes = PAGE_SIZE-1; + if (nbytes == 0) + return 0; - error = verify_area(VERIFY_READ, buff, nbytes); - if (error) return error; + if (nbytes >= PAGE_SIZE) + nbytes = PAGE_SIZE-1; page = (char *)__get_free_page(GFP_KERNEL); - if (page == NULL) return -ENOMEM; - - incoming = 0; - tmp = buff; - while(incoming < nbytes){ - if (get_user(c, tmp++)) return -EFAULT; - incoming++; - if (c == '\0' || c == '\n') - break; - } + if (!page) + return -ENOMEM; - retval = copy_from_user(page, buff, incoming); - if (retval != 0) { - printk("mpoa: proc_mpc_write: copy_from_user() failed\n"); - return -EFAULT; + for (p = page, len = 0; len < nbytes; p++, len++) { + if (get_user(*p, buff++)) { + free_page((unsigned long)page); + return -EFAULT; + } + if (*p == '\0' || *p == '\n') + break; } - *ppos += incoming; + *p = '\0'; - page[incoming] = '\0'; - retval = parse_qos(page, incoming); - if (retval == 0) + if (!parse_qos(page)) printk("mpoa: proc_mpc_write: could not parse '%s'\n", page); free_page((unsigned long)page); - return nbytes; + return len; } -static int parse_qos(const char *buff, int len) +static int parse_qos(const char *buff) { /* possible lines look like this * add 130.230.54.142 tx=max_pcr,max_sdu rx=max_pcr,max_sdu */ - - int pos, i; - uint32_t ipaddr; unsigned char ip[4]; - char cmd[4], temp[256]; - const char *tmp, *prev; + int tx_pcr, tx_sdu, rx_pcr, rx_sdu; + uint32_t ipaddr; struct atm_qos qos; - int value[5]; memset(&qos, 0, sizeof(struct atm_qos)); - strlcpy(cmd, buff, sizeof(cmd)); - if( strncmp(cmd,"add", 3) && strncmp(cmd,"del", 3)) - return 0; /* not add or del */ - - pos = 4; - /* next parse ip */ - prev = buff + pos; - for (i = 0; i < 3; i++) { - tmp = strchr(prev, '.'); - if (tmp == NULL) return 0; - memset(temp, '\0', 256); - memcpy(temp, prev, tmp-prev); - ip[i] = (char)simple_strtoul(temp, NULL, 0); - tmp ++; - prev = tmp; - } - tmp = strchr(prev, ' '); - if (tmp == NULL) return 0; - memset(temp, '\0', 256); - memcpy(temp, prev, tmp-prev); - ip[i] = (char)simple_strtoul(temp, NULL, 0); - ipaddr = *(uint32_t *)ip; - - if(!strncmp(cmd, "del", 3)) - return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr)); - - /* next transmit values */ - tmp = strstr(buff, "tx="); - if(tmp == NULL) return 0; - tmp += 3; - prev = tmp; - for( i = 0; i < 1; i++){ - tmp = strchr(prev, ','); - if (tmp == NULL) return 0; - memset(temp, '\0', 256); - memcpy(temp, prev, tmp-prev); - value[i] = (int)simple_strtoul(temp, NULL, 0); - tmp ++; - prev = tmp; + + if (sscanf(buff, "del %hhu.%hhu.%hhu.%hhu", + ip, ip+1, ip+2, ip+3) == 4) { + ipaddr = *(uint32_t *)ip; + return atm_mpoa_delete_qos(atm_mpoa_search_qos(ipaddr)); } - tmp = strchr(prev, ' '); - if (tmp == NULL) return 0; - memset(temp, '\0', 256); - memcpy(temp, prev, tmp-prev); - value[i] = (int)simple_strtoul(temp, NULL, 0); + + if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=tx", + ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu) == 6) { + rx_pcr = tx_pcr; + rx_sdu = tx_sdu; + } else if (sscanf(buff, "add %hhu.%hhu.%hhu.%hhu tx=%d,%d rx=%d,%d", + ip, ip+1, ip+2, ip+3, &tx_pcr, &tx_sdu, &rx_pcr, &rx_sdu) != 8) + return 0; + + ipaddr = *(uint32_t *)ip; qos.txtp.traffic_class = ATM_CBR; - qos.txtp.max_pcr = value[0]; - qos.txtp.max_sdu = value[1]; - - /* next receive values */ - tmp = strstr(buff, "rx="); - if(tmp == NULL) return 0; - if (strstr(buff, "rx=tx")) { /* rx == tx */ - qos.rxtp.traffic_class = qos.txtp.traffic_class; - qos.rxtp.max_pcr = qos.txtp.max_pcr; - qos.rxtp.max_cdv = qos.txtp.max_cdv; - qos.rxtp.max_sdu = qos.txtp.max_sdu; - } else { - tmp += 3; - prev = tmp; - for( i = 0; i < 1; i++){ - tmp = strchr(prev, ','); - if (tmp == NULL) return 0; - memset(temp, '\0', 256); - memcpy(temp, prev, tmp-prev); - value[i] = (int)simple_strtoul(temp, NULL, 0); - tmp ++; - prev = tmp; - } - tmp = strchr(prev, '\0'); - if (tmp == NULL) return 0; - memset(temp, '\0', 256); - memcpy(temp, prev, tmp-prev); - value[i] = (int)simple_strtoul(temp, NULL, 0); - qos.rxtp.traffic_class = ATM_CBR; - qos.rxtp.max_pcr = value[0]; - qos.rxtp.max_sdu = value[1]; - } + qos.txtp.max_pcr = tx_pcr; + qos.txtp.max_sdu = tx_sdu; + qos.rxtp.traffic_class = ATM_CBR; + qos.rxtp.max_pcr = rx_pcr; + qos.rxtp.max_sdu = rx_sdu; qos.aal = ATM_AAL5; dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n", qos.txtp.max_pcr, diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 7313d06c9328..404dda32b2f9 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -800,11 +800,11 @@ static struct nf_hook_ops br_nf_ops[] = { #ifdef CONFIG_SYSCTL static int brnf_sysctl_call_tables(ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int ret; - ret = proc_dointvec(ctl, write, filp, buffer, lenp); + ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && *(int *)(ctl->data)) *(int *)(ctl->data) = 1; diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 70dc21f0c5ec..d0702fbcb21d 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -23,32 +23,39 @@ struct notifier_block br_device_notifier = { .notifier_call = br_device_event }; +/* + * Handle changes in state of network devices enslaved to a bridge. + * + * Note: don't care about up/down if bridge itself is down, because + * port state is checked when bridge is brought up. + */ static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = ptr; struct net_bridge_port *p = dev->br_port; struct net_bridge *br; + /* not a port of a bridge */ if (p == NULL) return NOTIFY_DONE; br = p->br; - if ( !(br->dev->flags & IFF_UP)) - return NOTIFY_DONE; - - if (event == NETDEV_CHANGEMTU) { - dev_set_mtu(br->dev, br_min_mtu(br)); - return NOTIFY_DONE; - } spin_lock_bh(&br->lock); switch (event) { + case NETDEV_CHANGEMTU: + dev_set_mtu(br->dev, br_min_mtu(br)); + break; + case NETDEV_CHANGEADDR: br_fdb_changeaddr(p, dev->dev_addr); br_stp_recalculate_bridge_id(br); break; case NETDEV_CHANGE: /* device is up but carrier changed */ + if (!(br->dev->flags & IFF_UP)) + break; + if (netif_carrier_ok(dev)) { if (p->state == BR_STATE_DISABLED) br_stp_enable_port(p); @@ -59,11 +66,12 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v break; case NETDEV_DOWN: - br_stp_disable_port(p); + if (br->dev->flags & IFF_UP) + br_stp_disable_port(p); break; case NETDEV_UP: - if (netif_carrier_ok(dev)) + if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) br_stp_enable_port(p); break; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0b44c0e25dcf..c34a3a9db712 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -929,6 +929,70 @@ fault: return -EFAULT; } +/* Keep iterating until skb_iter_next returns false. */ +void skb_iter_first(const struct sk_buff *skb, struct skb_iter *i) +{ + i->len = skb_headlen(skb); + i->data = (unsigned char *)skb->data; + i->nextfrag = 0; + i->fraglist = NULL; +} + +int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i) +{ + /* Unmap previous, if not head fragment. */ + if (i->nextfrag) + kunmap_skb_frag(i->data); + + if (i->fraglist) { + fraglist: + /* We're iterating through fraglist. */ + if (i->nextfrag < skb_shinfo(i->fraglist)->nr_frags) { + i->data = kmap_skb_frag(&skb_shinfo(i->fraglist) + ->frags[i->nextfrag]); + i->len = skb_shinfo(i->fraglist)->frags[i->nextfrag] + .size; + i->nextfrag++; + return 1; + } + /* Fragments with fragments? Too hard! */ + BUG_ON(skb_shinfo(i->fraglist)->frag_list); + i->fraglist = i->fraglist->next; + if (!i->fraglist) + goto end; + + i->len = skb_headlen(i->fraglist); + i->data = i->fraglist->data; + i->nextfrag = 0; + return 1; + } + + if (i->nextfrag < skb_shinfo(skb)->nr_frags) { + i->data = kmap_skb_frag(&skb_shinfo(skb)->frags[i->nextfrag]); + i->len = skb_shinfo(skb)->frags[i->nextfrag].size; + i->nextfrag++; + return 1; + } + + i->fraglist = skb_shinfo(skb)->frag_list; + if (i->fraglist) + goto fraglist; + +end: + /* Bug trap for callers */ + i->data = NULL; + return 0; +} + +void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i) +{ + /* Unmap previous, if not head fragment. */ + if (i->data && i->nextfrag) + kunmap_skb_frag(i->data); + /* Bug trap for callers */ + i->data = NULL; +} + /* Checksum skb data. */ unsigned int skb_checksum(const struct sk_buff *skb, int offset, @@ -1399,3 +1463,6 @@ EXPORT_SYMBOL(skb_queue_tail); EXPORT_SYMBOL(skb_unlink); EXPORT_SYMBOL(skb_append); EXPORT_SYMBOL(skb_split); +EXPORT_SYMBOL(skb_iter_first); +EXPORT_SYMBOL(skb_iter_next); +EXPORT_SYMBOL(skb_iter_abort); diff --git a/net/core/sock.c b/net/core/sock.c index f8688edc7201..9146be7067cc 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -652,14 +652,6 @@ void sk_free(struct sock *sk) printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n", __FUNCTION__, atomic_read(&sk->sk_omem_alloc)); - /* - * If sendmsg cached page exists, toss it. - */ - if (sk->sk_sndmsg_page) { - __free_page(sk->sk_sndmsg_page); - sk->sk_sndmsg_page = NULL; - } - security_sk_free(sk); kmem_cache_free(sk->sk_slab, sk); module_put(owner); diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 6b6e49a9eb23..11b0f0c6d45c 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -161,7 +161,7 @@ static int min_priority[1]; static int max_priority[] = { 127 }; /* From DECnet spec */ static int dn_forwarding_proc(ctl_table *, int, struct file *, - void __user *, size_t *); + void __user *, size_t *, loff_t *); static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen, @@ -362,7 +362,8 @@ static void dn_dev_check_default(struct net_device *dev) static int dn_forwarding_proc(ctl_table *table, int write, struct file *filep, - void __user *buffer, size_t *lenp) + void __user *buffer, + size_t *lenp, loff_t *ppos) { #ifdef CONFIG_DECNET_ROUTER struct net_device *dev = table->extra1; @@ -376,7 +377,7 @@ static int dn_forwarding_proc(ctl_table *table, int write, dn_db = dev->dn_ptr; old = dn_db->parms.forwarding; - err = proc_dointvec(table, write, filep, buffer, lenp); + err = proc_dointvec(table, write, filep, buffer, lenp, ppos); if ((err >= 0) && write) { if (dn_db->parms.forwarding < 0) diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c index 65ce3bb9563b..02bca49cb508 100644 --- a/net/decnet/sysctl_net_decnet.c +++ b/net/decnet/sysctl_net_decnet.c @@ -162,13 +162,14 @@ static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen static int dn_node_address_handler(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, + size_t *lenp, loff_t *ppos) { char addr[DN_ASCBUF_LEN]; size_t len; dn_address dnaddr; - if (!*lenp || (filp->f_pos && !write)) { + if (!*lenp || (*ppos && !write)) { *lenp = 0; return 0; } @@ -191,7 +192,7 @@ static int dn_node_address_handler(ctl_table *table, int write, dn_dev_devices_on(); - filp->f_pos += len; + *ppos += len; return 0; } @@ -206,7 +207,7 @@ static int dn_node_address_handler(ctl_table *table, int write, return -EFAULT; *lenp = len; - filp->f_pos += len; + *ppos += len; return 0; } @@ -273,13 +274,14 @@ static int dn_def_dev_strategy(ctl_table *table, int __user *name, int nlen, static int dn_def_dev_handler(ctl_table *table, int write, struct file * filp, - void __user *buffer, size_t *lenp) + void __user *buffer, + size_t *lenp, loff_t *ppos) { size_t len; struct net_device *dev; char devname[17]; - if (!*lenp || (filp->f_pos && !write)) { + if (!*lenp || (*ppos && !write)) { *lenp = 0; return 0; } @@ -307,7 +309,7 @@ static int dn_def_dev_handler(ctl_table *table, int write, dev_put(dev); return -ENODEV; } - filp->f_pos += *lenp; + *ppos += *lenp; return 0; } @@ -329,7 +331,7 @@ static int dn_def_dev_handler(ctl_table *table, int write, return -EFAULT; *lenp = len; - filp->f_pos += len; + *ppos += len; return 0; } diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 2dc4e7a8ade8..4781dea42dfe 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1151,11 +1151,11 @@ void inet_forward_change(void) static int devinet_sysctl_forward(ctl_table *ctl, int write, struct file* filp, void __user *buffer, - size_t *lenp) + size_t *lenp, loff_t *ppos) { int *valp = ctl->data; int val = *valp; - int ret = proc_dointvec(ctl, write, filp, buffer, lenp); + int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && *valp != val) { if (valp == &ipv4_devconf.forwarding) @@ -1169,11 +1169,11 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write, int ipv4_doint_and_flush(ctl_table *ctl, int write, struct file* filp, void __user *buffer, - size_t *lenp) + size_t *lenp, loff_t *ppos) { int *valp = ctl->data; int val = *valp; - int ret = proc_dointvec(ctl, write, filp, buffer, lenp); + int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && *valp != val) rt_cache_flush(0); diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 5df55ca9eef0..d90a7935623f 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -1347,13 +1347,13 @@ static int ip_vs_zero_all(void) static int proc_do_defense_mode(ctl_table *table, int write, struct file * filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = table->data; int val = *valp; int rc; - rc = proc_dointvec(table, write, filp, buffer, lenp); + rc = proc_dointvec(table, write, filp, buffer, lenp, ppos); if (write && (*valp != val)) { if ((*valp < 0) || (*valp > 3)) { /* Restore the correct value */ @@ -1370,7 +1370,7 @@ proc_do_defense_mode(ctl_table *table, int write, struct file * filp, static int proc_do_sync_threshold(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = table->data; int val[2]; @@ -1379,7 +1379,7 @@ proc_do_sync_threshold(ctl_table *table, int write, struct file *filp, /* backup the value first */ memcpy(val, valp, sizeof(val)); - rc = proc_dointvec(table, write, filp, buffer, lenp); + rc = proc_dointvec(table, write, filp, buffer, lenp, ppos); if (write && (valp[0] < 0 || valp[1] < 0 || valp[0] >= valp[1])) { /* Restore the correct value */ memcpy(valp, val, sizeof(val)); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 37c9d31c3880..15d9eca5384e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2498,10 +2498,10 @@ static int flush_delay; static int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file *filp, void __user *buffer, - size_t *lenp) + size_t *lenp, loff_t *ppos) { if (write) { - proc_dointvec(ctl, write, filp, buffer, lenp); + proc_dointvec(ctl, write, filp, buffer, lenp, ppos); rt_cache_flush(flush_delay); return 0; } diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 6b0b74430e28..55cc269224db 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -62,12 +62,12 @@ extern ctl_table ipv4_route_table[]; static int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int val = ipv4_devconf.forwarding; int ret; - ret = proc_dointvec(ctl, write, filp, buffer, lenp); + ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && ipv4_devconf.forwarding != val) inet_forward_change(); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e193507ea3f9..2cfd74fbf566 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2113,6 +2113,14 @@ int tcp_v4_destroy_sock(struct sock *sk) if (tp->bind_hash) tcp_put_port(sk); + /* + * If sendmsg cached page exists, toss it. + */ + if (sk->sk_sndmsg_page) { + __free_page(sk->sk_sndmsg_page); + sk->sk_sndmsg_page = NULL; + } + atomic_dec(&tcp_sockets_allocated); return 0; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1305cf851707..40ad73c5cbb7 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3003,13 +3003,13 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) static int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = ctl->data; int val = *valp; int ret; - ret = proc_dointvec(ctl, write, filp, buffer, lenp); + ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && *valp != val && valp != &ipv6_devconf_dflt.forwarding) { struct inet6_dev *idev = NULL; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3e8767628a95..b278e5a04ca8 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1423,7 +1423,7 @@ static struct notifier_block ndisc_netdev_notifier = { }; #ifdef CONFIG_SYSCTL -int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp) +int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos) { struct net_device *dev = ctl->extra1; struct inet6_dev *idev; @@ -1433,7 +1433,7 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f inet6_ifinfo_notify(RTM_NEWLINK, idev); in6_dev_put(idev); } - return proc_dointvec(ctl, write, filp, buffer, lenp); + return proc_dointvec(ctl, write, filp, buffer, lenp, ppos); } #endif diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 143543f262a6..2017c69dc9f3 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1924,10 +1924,10 @@ static int flush_delay; static int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { if (write) { - proc_dointvec(ctl, write, filp, buffer, lenp); + proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (flush_delay < 0) flush_delay = 0; fib6_run_gc((unsigned long)flush_delay); diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c index 995f4e15cce5..cdcb320b56d1 100644 --- a/net/irda/irsysctl.c +++ b/net/irda/irsysctl.c @@ -78,11 +78,11 @@ static int min_lap_keepalive_time = 100; /* 100us */ * us on that - Jean II */ static int do_devname(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { int ret; - ret = proc_dostring(table, write, filp, buffer, lenp); + ret = proc_dostring(table, write, filp, buffer, lenp, ppos); if (ret == 0 && write) { struct ias_value *val; diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 6498c34c5494..1f9bf9d0834c 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -34,6 +34,7 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/kmod.h> +#include <linux/list.h> #include <net/sock.h> #include <net/pkt_sched.h> @@ -195,7 +196,7 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) { struct Qdisc *q; - for (q = dev->qdisc_list; q; q = q->next) { + list_for_each_entry(q, &dev->qdisc_list, list) { if (q->handle == handle) return q; } @@ -421,6 +422,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) memset(sch, 0, size); + INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); if (handle == TC_H_INGRESS) @@ -430,6 +432,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) sch->enqueue = ops->enqueue; sch->dequeue = ops->dequeue; sch->dev = dev; + dev_hold(dev); atomic_set(&sch->refcnt, 1); sch->stats_lock = &dev->queue_lock; if (handle == 0) { @@ -453,8 +456,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) smp_wmb(); if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { qdisc_lock_tree(dev); - sch->next = dev->qdisc_list; - dev->qdisc_list = sch; + list_add_tail(&sch->list, &dev->qdisc_list); qdisc_unlock_tree(dev); #ifdef CONFIG_NET_ESTIMATOR @@ -751,7 +753,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, nlh->nlmsg_flags = flags; tcm = NLMSG_DATA(nlh); tcm->tcm_family = AF_UNSPEC; - tcm->tcm_ifindex = q->dev ? q->dev->ifindex : 0; + tcm->tcm_ifindex = q->dev->ifindex; tcm->tcm_parent = clid; tcm->tcm_handle = q->handle; tcm->tcm_info = atomic_read(&q->refcnt); @@ -812,18 +814,21 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) continue; if (idx > s_idx) s_q_idx = 0; - read_lock(&qdisc_tree_lock); - for (q = dev->qdisc_list, q_idx = 0; q; - q = q->next, q_idx++) { - if (q_idx < s_q_idx) + read_lock_bh(&qdisc_tree_lock); + q_idx = 0; + list_for_each_entry(q, &dev->qdisc_list, list) { + if (q_idx < s_q_idx) { + q_idx++; continue; + } if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) { - read_unlock(&qdisc_tree_lock); + read_unlock_bh(&qdisc_tree_lock); goto done; } + q_idx++; } - read_unlock(&qdisc_tree_lock); + read_unlock_bh(&qdisc_tree_lock); } done: @@ -968,7 +973,7 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, nlh->nlmsg_flags = flags; tcm = NLMSG_DATA(nlh); tcm->tcm_family = AF_UNSPEC; - tcm->tcm_ifindex = q->dev ? q->dev->ifindex : 0; + tcm->tcm_ifindex = q->dev->ifindex; tcm->tcm_parent = q->handle; tcm->tcm_handle = q->handle; tcm->tcm_info = 0; @@ -1032,13 +1037,16 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) return 0; s_t = cb->args[0]; - - read_lock(&qdisc_tree_lock); - for (q=dev->qdisc_list, t=0; q; q = q->next, t++) { - if (t < s_t) continue; - if (!q->ops->cl_ops) continue; - if (tcm->tcm_parent && TC_H_MAJ(tcm->tcm_parent) != q->handle) + t = 0; + + read_lock_bh(&qdisc_tree_lock); + list_for_each_entry(q, &dev->qdisc_list, list) { + if (t < s_t || !q->ops->cl_ops || + (tcm->tcm_parent && + TC_H_MAJ(tcm->tcm_parent) != q->handle)) { + t++; continue; + } if (t > s_t) memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0])); arg.w.fn = qdisc_class_dump; @@ -1051,8 +1059,9 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) cb->args[1] = arg.w.count; if (arg.w.stop) break; + t++; } - read_unlock(&qdisc_tree_lock); + read_unlock_bh(&qdisc_tree_lock); cb->args[0] = t; diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index c43a6e014656..ca08449e7b03 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -56,7 +56,7 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ */ -#define PRIV(sch) ((struct atm_qdisc_data *) (sch)->data) +#define PRIV(sch) qdisc_priv(sch) #define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back)) @@ -104,9 +104,10 @@ static int find_flow(struct atm_qdisc_data *qdisc,struct atm_flow_data *flow) static __inline__ struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid) { + struct atm_qdisc_data *p = PRIV(sch); struct atm_flow_data *flow; - for (flow = PRIV(sch)->flows; flow; flow = flow->next) + for (flow = p->flows; flow; flow = flow->next) if (flow->classid == classid) break; return flow; } diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 2d484883465f..01dfcb1ab832 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -241,7 +241,7 @@ cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) static struct cbq_class * cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres) { - struct cbq_sched_data *q = (struct cbq_sched_data*)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *head = &q->link; struct cbq_class **defmap; struct cbq_class *cl = NULL; @@ -344,7 +344,7 @@ fallback: static __inline__ void cbq_activate_class(struct cbq_class *cl) { - struct cbq_sched_data *q = (struct cbq_sched_data*)cl->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(cl->qdisc); int prio = cl->cpriority; struct cbq_class *cl_tail; @@ -368,7 +368,7 @@ static __inline__ void cbq_activate_class(struct cbq_class *cl) static void cbq_deactivate_class(struct cbq_class *this) { - struct cbq_sched_data *q = (struct cbq_sched_data*)this->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(this->qdisc); int prio = this->cpriority; struct cbq_class *cl; struct cbq_class *cl_prev = q->active[prio]; @@ -419,7 +419,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl) static int cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); int len = skb->len; int ret = NET_XMIT_SUCCESS; struct cbq_class *cl = cbq_classify(skb, sch,&ret); @@ -466,7 +466,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) static int cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl; int ret; @@ -500,7 +500,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) static void cbq_ovl_classic(struct cbq_class *cl) { - struct cbq_sched_data *q = (struct cbq_sched_data *)cl->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(cl->qdisc); psched_tdiff_t delay = PSCHED_TDIFF(cl->undertime, q->now); if (!cl->delayed) { @@ -554,7 +554,7 @@ static void cbq_ovl_classic(struct cbq_class *cl) static void cbq_ovl_rclassic(struct cbq_class *cl) { - struct cbq_sched_data *q = (struct cbq_sched_data *)cl->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(cl->qdisc); struct cbq_class *this = cl; do { @@ -573,7 +573,7 @@ static void cbq_ovl_rclassic(struct cbq_class *cl) static void cbq_ovl_delay(struct cbq_class *cl) { - struct cbq_sched_data *q = (struct cbq_sched_data *)cl->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(cl->qdisc); psched_tdiff_t delay = PSCHED_TDIFF(cl->undertime, q->now); if (!cl->delayed) { @@ -609,7 +609,7 @@ static void cbq_ovl_delay(struct cbq_class *cl) static void cbq_ovl_lowprio(struct cbq_class *cl) { - struct cbq_sched_data *q = (struct cbq_sched_data*)cl->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(cl->qdisc); cl->penalized = jiffies + cl->penalty; @@ -678,7 +678,7 @@ static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio) static void cbq_undelay(unsigned long arg) { struct Qdisc *sch = (struct Qdisc*)arg; - struct cbq_sched_data *q = (struct cbq_sched_data*)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); long delay = 0; unsigned pmask; @@ -715,7 +715,7 @@ static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) { int len = skb->len; struct Qdisc *sch = child->__parent; - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl = q->rx_class; q->rx_class = NULL; @@ -863,7 +863,7 @@ cbq_update(struct cbq_sched_data *q) static __inline__ struct cbq_class * cbq_under_limit(struct cbq_class *cl) { - struct cbq_sched_data *q = (struct cbq_sched_data*)cl->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(cl->qdisc); struct cbq_class *this_cl = cl; if (cl->tparent == NULL) @@ -903,7 +903,7 @@ cbq_under_limit(struct cbq_class *cl) static __inline__ struct sk_buff * cbq_dequeue_prio(struct Qdisc *sch, int prio) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl_tail, *cl_prev, *cl; struct sk_buff *skb; int deficit; @@ -1006,7 +1006,7 @@ next_class: static __inline__ struct sk_buff * cbq_dequeue_1(struct Qdisc *sch) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; unsigned activemask; @@ -1025,7 +1025,7 @@ static struct sk_buff * cbq_dequeue(struct Qdisc *sch) { struct sk_buff *skb; - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); psched_time_t now; psched_tdiff_t incr; @@ -1150,7 +1150,7 @@ static void cbq_normalize_quanta(struct cbq_sched_data *q, int prio) static void cbq_sync_defmap(struct cbq_class *cl) { - struct cbq_sched_data *q = (struct cbq_sched_data*)cl->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(cl->qdisc); struct cbq_class *split = cl->split; unsigned h; int i; @@ -1216,7 +1216,7 @@ static void cbq_change_defmap(struct cbq_class *cl, u32 splitid, u32 def, u32 ma static void cbq_unlink_class(struct cbq_class *this) { struct cbq_class *cl, **clp; - struct cbq_sched_data *q = (struct cbq_sched_data*)this->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(this->qdisc); for (clp = &q->classes[cbq_hash(this->classid)]; (cl = *clp) != NULL; clp = &cl->next) { if (cl == this) { @@ -1249,7 +1249,7 @@ static void cbq_unlink_class(struct cbq_class *this) static void cbq_link_class(struct cbq_class *this) { - struct cbq_sched_data *q = (struct cbq_sched_data*)this->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(this->qdisc); unsigned h = cbq_hash(this->classid); struct cbq_class *parent = this->tparent; @@ -1270,7 +1270,7 @@ static void cbq_link_class(struct cbq_class *this) static unsigned int cbq_drop(struct Qdisc* sch) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl, *cl_head; int prio; unsigned int len; @@ -1293,7 +1293,7 @@ static unsigned int cbq_drop(struct Qdisc* sch) static void cbq_reset(struct Qdisc* sch) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl; int prio; unsigned h; @@ -1363,7 +1363,7 @@ static void cbq_addprio(struct cbq_sched_data *q, struct cbq_class *cl) static int cbq_set_wrr(struct cbq_class *cl, struct tc_cbq_wrropt *wrr) { - struct cbq_sched_data *q = (struct cbq_sched_data *)cl->qdisc->data; + struct cbq_sched_data *q = qdisc_priv(cl->qdisc); if (wrr->allot) cl->allot = wrr->allot; @@ -1432,7 +1432,7 @@ static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt) static int cbq_init(struct Qdisc *sch, struct rtattr *opt) { - struct cbq_sched_data *q = (struct cbq_sched_data*)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct rtattr *tb[TCA_CBQ_MAX]; struct tc_ratespec *r; @@ -1623,7 +1623,7 @@ rtattr_failure: static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct cbq_sched_data *q = (struct cbq_sched_data*)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct rtattr *rta; @@ -1650,7 +1650,7 @@ static int cbq_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, struct tcmsg *tcm) { - struct cbq_sched_data *q = (struct cbq_sched_data*)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl = (struct cbq_class*)arg; unsigned char *b = skb->tail; struct rtattr *rta; @@ -1726,7 +1726,7 @@ cbq_leaf(struct Qdisc *sch, unsigned long arg) static unsigned long cbq_get(struct Qdisc *sch, u32 classid) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl = cbq_class_lookup(q, classid); if (cl) { @@ -1760,7 +1760,7 @@ static void cbq_destroy_class(struct cbq_class *cl) static void cbq_destroy(struct Qdisc* sch) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl; unsigned h; @@ -1791,7 +1791,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg) if (--cl->refcnt == 0) { #ifdef CONFIG_NET_CLS_POLICE - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); spin_lock_bh(&sch->dev->queue_lock); if (q->rx_class == cl) @@ -1808,7 +1808,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t unsigned long *arg) { int err; - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl = (struct cbq_class*)*arg; struct rtattr *opt = tca[TCA_OPTIONS-1]; struct rtattr *tb[TCA_CBQ_MAX]; @@ -2004,7 +2004,7 @@ failure: static int cbq_delete(struct Qdisc *sch, unsigned long arg) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl = (struct cbq_class*)arg; if (cl->filters || cl->children || cl == &q->link) @@ -2042,7 +2042,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg) static struct tcf_proto **cbq_find_tcf(struct Qdisc *sch, unsigned long arg) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *cl = (struct cbq_class *)arg; if (cl == NULL) @@ -2054,7 +2054,7 @@ static struct tcf_proto **cbq_find_tcf(struct Qdisc *sch, unsigned long arg) static unsigned long cbq_bind_filter(struct Qdisc *sch, unsigned long parent, u32 classid) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); struct cbq_class *p = (struct cbq_class*)parent; struct cbq_class *cl = cbq_class_lookup(q, classid); @@ -2076,7 +2076,7 @@ static void cbq_unbind_filter(struct Qdisc *sch, unsigned long arg) static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg) { - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + struct cbq_sched_data *q = qdisc_priv(sch); unsigned h; if (arg->stop) diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 92e9f335b70d..e0831a4a4457 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -30,7 +30,7 @@ #endif -#define PRIV(sch) ((struct dsmark_qdisc_data *) (sch)->data) +#define PRIV(sch) qdisc_priv(sch) /* @@ -383,7 +383,6 @@ static void dsmark_destroy(struct Qdisc *sch) tcf_destroy(tp); } qdisc_destroy(p->q); - p->q = &noop_qdisc; kfree(p->mask); } diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 132a5bc94294..b089924177f8 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -45,7 +45,7 @@ struct fifo_sched_data static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) { - struct fifo_sched_data *q = (struct fifo_sched_data *)sch->data; + struct fifo_sched_data *q = qdisc_priv(sch); if (sch->stats.backlog + skb->len <= q->limit) { __skb_queue_tail(&sch->q, skb); @@ -106,7 +106,7 @@ fifo_reset(struct Qdisc* sch) static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) { - struct fifo_sched_data *q = (struct fifo_sched_data *)sch->data; + struct fifo_sched_data *q = qdisc_priv(sch); if (sch->q.qlen < q->limit) { __skb_queue_tail(&sch->q, skb); @@ -138,7 +138,7 @@ pfifo_dequeue(struct Qdisc* sch) static int fifo_init(struct Qdisc *sch, struct rtattr *opt) { - struct fifo_sched_data *q = (void*)sch->data; + struct fifo_sched_data *q = qdisc_priv(sch); if (opt == NULL) { unsigned int limit = sch->dev->tx_queue_len ? : 1; @@ -158,7 +158,7 @@ static int fifo_init(struct Qdisc *sch, struct rtattr *opt) static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct fifo_sched_data *q = (void*)sch->data; + struct fifo_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct tc_fifo_qopt opt; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index ece985b6dc25..82117f9ba7d1 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -31,6 +31,7 @@ #include <linux/rtnetlink.h> #include <linux/init.h> #include <linux/rcupdate.h> +#include <linux/list.h> #include <net/sock.h> #include <net/pkt_sched.h> @@ -45,10 +46,11 @@ The idea is the following: - enqueue, dequeue are serialized via top level device spinlock dev->queue_lock. - - tree walking is protected by read_lock(qdisc_tree_lock) + - tree walking is protected by read_lock_bh(qdisc_tree_lock) and this lock is used only in process context. - - updates to tree are made only under rtnl semaphore, - hence this lock may be made without local bh disabling. + - updates to tree are made under rtnl semaphore or + from softirq context (__qdisc_destroy rcu-callback) + hence this lock needs local bh disabling. qdisc_tree_lock must be grabbed BEFORE dev->queue_lock! */ @@ -56,14 +58,14 @@ rwlock_t qdisc_tree_lock = RW_LOCK_UNLOCKED; void qdisc_lock_tree(struct net_device *dev) { - write_lock(&qdisc_tree_lock); + write_lock_bh(&qdisc_tree_lock); spin_lock_bh(&dev->queue_lock); } void qdisc_unlock_tree(struct net_device *dev) { spin_unlock_bh(&dev->queue_lock); - write_unlock(&qdisc_tree_lock); + write_unlock_bh(&qdisc_tree_lock); } /* @@ -283,10 +285,9 @@ static const u8 prio2band[TC_PRIO_MAX+1] = static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) { - struct sk_buff_head *list; + struct sk_buff_head *list = qdisc_priv(qdisc); - list = ((struct sk_buff_head*)qdisc->data) + - prio2band[skb->priority&TC_PRIO_MAX]; + list += prio2band[skb->priority&TC_PRIO_MAX]; if (list->qlen < qdisc->dev->tx_queue_len) { __skb_queue_tail(list, skb); @@ -304,7 +305,7 @@ static struct sk_buff * pfifo_fast_dequeue(struct Qdisc* qdisc) { int prio; - struct sk_buff_head *list = ((struct sk_buff_head*)qdisc->data); + struct sk_buff_head *list = qdisc_priv(qdisc); struct sk_buff *skb; for (prio = 0; prio < 3; prio++, list++) { @@ -320,10 +321,9 @@ pfifo_fast_dequeue(struct Qdisc* qdisc) static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc) { - struct sk_buff_head *list; + struct sk_buff_head *list = qdisc_priv(qdisc); - list = ((struct sk_buff_head*)qdisc->data) + - prio2band[skb->priority&TC_PRIO_MAX]; + list += prio2band[skb->priority&TC_PRIO_MAX]; __skb_queue_head(list, skb); qdisc->q.qlen++; @@ -334,7 +334,7 @@ static void pfifo_fast_reset(struct Qdisc* qdisc) { int prio; - struct sk_buff_head *list = ((struct sk_buff_head*)qdisc->data); + struct sk_buff_head *list = qdisc_priv(qdisc); for (prio=0; prio < 3; prio++) skb_queue_purge(list+prio); @@ -359,9 +359,7 @@ rtattr_failure: static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt) { int i; - struct sk_buff_head *list; - - list = ((struct sk_buff_head*)qdisc->data); + struct sk_buff_head *list = qdisc_priv(qdisc); for (i=0; i<3; i++) skb_queue_head_init(list+i); @@ -385,19 +383,30 @@ static struct Qdisc_ops pfifo_fast_ops = { struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) { + void *p; struct Qdisc *sch; - int size = sizeof(*sch) + ops->priv_size; + int size; - sch = kmalloc(size, GFP_KERNEL); - if (!sch) + /* ensure that the Qdisc and the private data are 32-byte aligned */ + size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST); + size += ops->priv_size + QDISC_ALIGN_CONST; + + p = kmalloc(size, GFP_KERNEL); + if (!p) return NULL; - memset(sch, 0, size); + memset(p, 0, size); + + sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST) + & ~QDISC_ALIGN_CONST); + sch->padded = (char *)sch - (char *)p; + INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); sch->ops = ops; sch->enqueue = ops->enqueue; sch->dequeue = ops->dequeue; sch->dev = dev; + dev_hold(dev); sch->stats_lock = &dev->queue_lock; atomic_set(&sch->refcnt, 1); /* enqueue is accessed locklessly - make sure it's visible @@ -406,7 +415,7 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) if (!ops->init || ops->init(sch, NULL) == 0) return sch; - kfree(sch); + kfree(p); return NULL; } @@ -431,40 +440,29 @@ static void __qdisc_destroy(struct rcu_head *head) #ifdef CONFIG_NET_ESTIMATOR qdisc_kill_estimator(&qdisc->stats); #endif + write_lock(&qdisc_tree_lock); if (ops->reset) ops->reset(qdisc); if (ops->destroy) ops->destroy(qdisc); + write_unlock(&qdisc_tree_lock); module_put(ops->owner); + dev_put(qdisc->dev); if (!(qdisc->flags&TCQ_F_BUILTIN)) - kfree(qdisc); + kfree((char *) qdisc - qdisc->padded); } /* Under dev->queue_lock and BH! */ void qdisc_destroy(struct Qdisc *qdisc) { - struct net_device *dev = qdisc->dev; - if (!atomic_dec_and_test(&qdisc->refcnt)) return; - - if (dev) { - struct Qdisc *q, **qp; - for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) { - if (q == qdisc) { - *qp = q->next; - break; - } - } - } - + list_del(&qdisc->list); call_rcu(&qdisc->q_rcu, __qdisc_destroy); - } - void dev_activate(struct net_device *dev) { /* No queueing discipline is attached to device; @@ -481,18 +479,15 @@ void dev_activate(struct net_device *dev) printk(KERN_INFO "%s: activation failed\n", dev->name); return; } - - write_lock(&qdisc_tree_lock); - qdisc->next = dev->qdisc_list; - dev->qdisc_list = qdisc; - write_unlock(&qdisc_tree_lock); - + write_lock_bh(&qdisc_tree_lock); + list_add_tail(&qdisc->list, &dev->qdisc_list); + write_unlock_bh(&qdisc_tree_lock); } else { qdisc = &noqueue_qdisc; } - write_lock(&qdisc_tree_lock); + write_lock_bh(&qdisc_tree_lock); dev->qdisc_sleeping = qdisc; - write_unlock(&qdisc_tree_lock); + write_unlock_bh(&qdisc_tree_lock); } spin_lock_bh(&dev->queue_lock); @@ -528,7 +523,7 @@ void dev_init_scheduler(struct net_device *dev) qdisc_lock_tree(dev); dev->qdisc = &noop_qdisc; dev->qdisc_sleeping = &noop_qdisc; - dev->qdisc_list = NULL; + INIT_LIST_HEAD(&dev->qdisc_list); qdisc_unlock_tree(dev); dev_watchdog_init(dev); @@ -549,9 +544,7 @@ void dev_shutdown(struct net_device *dev) qdisc_destroy(qdisc); } #endif - BUG_TRAP(dev->qdisc_list == NULL); BUG_TRAP(!timer_pending(&dev->watchdog_timer)); - dev->qdisc_list = NULL; qdisc_unlock_tree(dev); } diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 1861ab10bdb1..375c6c2fb996 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -106,7 +106,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { psched_time_t now; struct gred_sched_data *q=NULL; - struct gred_sched *t= (struct gred_sched *)sch->data; + struct gred_sched *t= qdisc_priv(sch); unsigned long qave=0; int i=0; @@ -215,7 +215,7 @@ static int gred_requeue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q; - struct gred_sched *t= (struct gred_sched *)sch->data; + struct gred_sched *t= qdisc_priv(sch); q= t->tab[(skb->tc_index&0xf)]; /* error checking here -- probably unnecessary */ PSCHED_SET_PASTPERFECT(q->qidlestart); @@ -231,7 +231,7 @@ gred_dequeue(struct Qdisc* sch) { struct sk_buff *skb; struct gred_sched_data *q; - struct gred_sched *t= (struct gred_sched *)sch->data; + struct gred_sched *t= qdisc_priv(sch); skb = __skb_dequeue(&sch->q); if (skb) { @@ -264,7 +264,7 @@ static unsigned int gred_drop(struct Qdisc* sch) struct sk_buff *skb; struct gred_sched_data *q; - struct gred_sched *t= (struct gred_sched *)sch->data; + struct gred_sched *t= qdisc_priv(sch); skb = __skb_dequeue_tail(&sch->q); if (skb) { @@ -300,7 +300,7 @@ static void gred_reset(struct Qdisc* sch) { int i; struct gred_sched_data *q; - struct gred_sched *t= (struct gred_sched *)sch->data; + struct gred_sched *t= qdisc_priv(sch); __skb_queue_purge(&sch->q); @@ -323,7 +323,7 @@ static void gred_reset(struct Qdisc* sch) static int gred_change(struct Qdisc *sch, struct rtattr *opt) { - struct gred_sched *table = (struct gred_sched *)sch->data; + struct gred_sched *table = qdisc_priv(sch); struct gred_sched_data *q; struct tc_gred_qopt *ctl; struct tc_gred_sopt *sopt; @@ -469,7 +469,7 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) static int gred_init(struct Qdisc *sch, struct rtattr *opt) { - struct gred_sched *table = (struct gred_sched *)sch->data; + struct gred_sched *table = qdisc_priv(sch); struct tc_gred_sopt *sopt; struct rtattr *tb[TCA_GRED_STAB]; struct rtattr *tb2[TCA_GRED_DPS]; @@ -502,7 +502,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) struct rtattr *rta; struct tc_gred_qopt *opt = NULL ; struct tc_gred_qopt *dst; - struct gred_sched *table = (struct gred_sched *)sch->data; + struct gred_sched *table = qdisc_priv(sch); struct gred_sched_data *q; int i; unsigned char *b = skb->tail; @@ -593,7 +593,7 @@ rtattr_failure: static void gred_destroy(struct Qdisc *sch) { - struct gred_sched *table = (struct gred_sched *)sch->data; + struct gred_sched *table = qdisc_priv(sch); int i; for (i = 0;i < table->DPs; i++) { diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index a6e559c1670d..84ef3ab6a843 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1016,7 +1016,7 @@ hfsc_hash(u32 h) static inline struct hfsc_class * hfsc_find_class(u32 classid, struct Qdisc *sch) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl; list_for_each_entry(cl, &q->clhash[hfsc_hash(classid)], hlist) { @@ -1061,7 +1061,7 @@ static int hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **tca, unsigned long *arg) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl = (struct hfsc_class *)*arg; struct hfsc_class *parent = NULL; struct rtattr *opt = tca[TCA_OPTIONS-1]; @@ -1204,7 +1204,7 @@ hfsc_destroy_filters(struct tcf_proto **fl) static void hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); hfsc_destroy_filters(&cl->filter_list); qdisc_destroy(cl->qdisc); @@ -1218,7 +1218,7 @@ hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl) static int hfsc_delete_class(struct Qdisc *sch, unsigned long arg) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl = (struct hfsc_class *)arg; if (cl->level > 0 || cl->filter_cnt > 0 || cl == &q->root) @@ -1240,7 +1240,7 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg) static struct hfsc_class * hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl; struct tcf_result res; struct tcf_proto *tcf; @@ -1381,7 +1381,7 @@ hfsc_unbind_tcf(struct Qdisc *sch, unsigned long arg) static struct tcf_proto ** hfsc_tcf_chain(struct Qdisc *sch, unsigned long arg) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl = (struct hfsc_class *)arg; if (cl == NULL) @@ -1489,7 +1489,7 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, static void hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl; unsigned int i; @@ -1523,7 +1523,7 @@ hfsc_watchdog(unsigned long arg) static void hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl; u64 next_time = 0; long delay; @@ -1545,7 +1545,7 @@ hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time) static int hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct tc_hfsc_qopt *qopt; unsigned int i; @@ -1585,7 +1585,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) static int hfsc_change_qdisc(struct Qdisc *sch, struct rtattr *opt) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct tc_hfsc_qopt *qopt; if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt)) @@ -1632,7 +1632,7 @@ hfsc_reset_class(struct hfsc_class *cl) static void hfsc_reset_qdisc(struct Qdisc *sch) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl; unsigned int i; @@ -1651,7 +1651,7 @@ hfsc_reset_qdisc(struct Qdisc *sch) static void hfsc_destroy_qdisc(struct Qdisc *sch) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl, *next; unsigned int i; @@ -1666,7 +1666,7 @@ hfsc_destroy_qdisc(struct Qdisc *sch) static int hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct tc_hfsc_qopt qopt; @@ -1730,7 +1730,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch) static struct sk_buff * hfsc_dequeue(struct Qdisc *sch) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl; struct sk_buff *skb; u64 cur_time; @@ -1799,7 +1799,7 @@ hfsc_dequeue(struct Qdisc *sch) static int hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); __skb_queue_head(&q->requeue, skb); sch->q.qlen++; @@ -1809,7 +1809,7 @@ hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch) static unsigned int hfsc_drop(struct Qdisc *sch) { - struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_sched *q = qdisc_priv(sch); struct hfsc_class *cl; unsigned int len; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 415369672f44..6eccda6df458 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -267,7 +267,7 @@ static __inline__ int htb_hash(u32 h) /* find class in global hash table using given handle */ static __inline__ struct htb_class *htb_find(u32 handle, struct Qdisc *sch) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct list_head *p; if (TC_H_MAJ(handle) != sch->handle) return NULL; @@ -300,7 +300,7 @@ static inline u32 htb_classid(struct htb_class *cl) static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl; struct tcf_result res; struct tcf_proto *tcf; @@ -712,7 +712,7 @@ htb_deactivate(struct htb_sched *q,struct htb_class *cl) static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) { int ret = NET_XMIT_SUCCESS; - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = htb_classify(skb,sch,&ret); @@ -759,7 +759,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* TODO: requeuing packet charges it to policers again !! */ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); int ret = NET_XMIT_SUCCESS; struct htb_class *cl = htb_classify(skb,sch, &ret); struct sk_buff *tskb; @@ -800,7 +800,7 @@ static void htb_timer(unsigned long arg) static void htb_rate_timer(unsigned long arg) { struct Qdisc *sch = (struct Qdisc*)arg; - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct list_head *p; /* lock queue so that we can muck with it */ @@ -1060,7 +1060,7 @@ next: static void htb_delay_by(struct Qdisc *sch,long delay) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); if (delay <= 0) delay = 1; if (unlikely(delay > 5*HZ)) { if (net_ratelimit()) @@ -1077,7 +1077,7 @@ static void htb_delay_by(struct Qdisc *sch,long delay) static struct sk_buff *htb_dequeue(struct Qdisc *sch) { struct sk_buff *skb = NULL; - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); int level; long min_delay; #ifdef HTB_DEBUG @@ -1147,7 +1147,7 @@ fin: /* try to drop from each class (by prio) until one succeed */ static unsigned int htb_drop(struct Qdisc* sch) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); int prio; for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) { @@ -1172,7 +1172,7 @@ static unsigned int htb_drop(struct Qdisc* sch) /* always caled under BH & queue lock */ static void htb_reset(struct Qdisc* sch) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); int i; HTB_DBG(0,1,"htb_reset sch=%p, handle=%X\n",sch,sch->handle); @@ -1210,7 +1210,7 @@ static void htb_reset(struct Qdisc* sch) static int htb_init(struct Qdisc *sch, struct rtattr *opt) { - struct htb_sched *q = (struct htb_sched*)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct rtattr *tb[TCA_HTB_INIT]; struct tc_htb_glob *gopt; int i; @@ -1265,7 +1265,7 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt) static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct htb_sched *q = (struct htb_sched*)sch->data; + struct htb_sched *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct rtattr *rta; struct tc_htb_glob gopt; @@ -1300,7 +1300,7 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, struct tcmsg *tcm) { #ifdef HTB_DEBUG - struct htb_sched *q = (struct htb_sched*)sch->data; + struct htb_sched *q = qdisc_priv(sch); #endif struct htb_class *cl = (struct htb_class*)arg; unsigned char *b = skb->tail; @@ -1358,7 +1358,7 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, sch_tree_lock(sch); if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) { if (cl->prio_activity) - htb_deactivate ((struct htb_sched*)sch->data,cl); + htb_deactivate (qdisc_priv(sch),cl); /* TODO: is it correct ? Why CBQ doesn't do it ? */ sch->q.qlen -= (*old)->q.qlen; @@ -1379,7 +1379,7 @@ static struct Qdisc * htb_leaf(struct Qdisc *sch, unsigned long arg) static unsigned long htb_get(struct Qdisc *sch, u32 classid) { #ifdef HTB_DEBUG - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); #endif struct htb_class *cl = htb_find(classid,sch); HTB_DBG(0,1,"htb_get clid=%X q=%p cl=%p ref=%d\n",classid,q,cl,cl?cl->refcnt:0); @@ -1400,7 +1400,7 @@ static void htb_destroy_filters(struct tcf_proto **fl) static void htb_destroy_class(struct Qdisc* sch,struct htb_class *cl) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); HTB_DBG(0,1,"htb_destrycls clid=%X ref=%d\n", cl?cl->classid:0,cl?cl->refcnt:0); if (!cl->level) { BUG_TRAP(cl->un.leaf.q); @@ -1435,7 +1435,7 @@ static void htb_destroy_class(struct Qdisc* sch,struct htb_class *cl) /* always caled under BH & queue lock */ static void htb_destroy(struct Qdisc* sch) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); HTB_DBG(0,1,"htb_destroy q=%p\n",q); del_timer_sync (&q->timer); @@ -1457,7 +1457,7 @@ static void htb_destroy(struct Qdisc* sch) static int htb_delete(struct Qdisc *sch, unsigned long arg) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = (struct htb_class*)arg; HTB_DBG(0,1,"htb_delete q=%p cl=%X ref=%d\n",q,cl?cl->classid:0,cl?cl->refcnt:0); @@ -1484,7 +1484,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) static void htb_put(struct Qdisc *sch, unsigned long arg) { #ifdef HTB_DEBUG - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); #endif struct htb_class *cl = (struct htb_class*)arg; HTB_DBG(0,1,"htb_put q=%p cl=%X ref=%d\n",q,cl?cl->classid:0,cl?cl->refcnt:0); @@ -1497,7 +1497,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **tca, unsigned long *arg) { int err = -EINVAL; - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = (struct htb_class*)*arg,*parent; struct rtattr *opt = tca[TCA_OPTIONS-1]; struct qdisc_rate_table *rtab = NULL, *ctab = NULL; @@ -1623,7 +1623,7 @@ failure: static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = (struct htb_class *)arg; struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list; HTB_DBG(0,2,"htb_tcf q=%p clid=%X fref=%d fl=%p\n",q,cl?cl->classid:0,cl?cl->filter_cnt:q->filter_cnt,*fl); @@ -1633,7 +1633,7 @@ static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg) static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, u32 classid) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = htb_find (classid,sch); HTB_DBG(0,2,"htb_bind q=%p clid=%X cl=%p fref=%d\n",q,classid,cl,cl?cl->filter_cnt:q->filter_cnt); /*if (cl && !cl->level) return 0; @@ -1654,7 +1654,7 @@ static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = (struct htb_class *)arg; HTB_DBG(0,2,"htb_unbind q=%p cl=%p fref=%d\n",q,cl,cl?cl->filter_cnt:q->filter_cnt); if (cl) @@ -1665,7 +1665,7 @@ static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg) static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg) { - struct htb_sched *q = (struct htb_sched *)sch->data; + struct htb_sched *q = qdisc_priv(sch); int i; if (arg->stop) diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index 3ec741a3b44a..30f2176b992d 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c @@ -40,7 +40,7 @@ #endif -#define PRIV(sch) ((struct ingress_qdisc_data *) (sch)->data) +#define PRIV(sch) qdisc_priv(sch) /* Thanks to Doron Oz for this hack diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 12cc95eac339..4d91d697b334 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -603,7 +603,7 @@ static inline int tabledist(int mu, int sigma) */ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb; psched_time_t now; long delay; @@ -659,7 +659,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* Requeue packets but don't change time stamp */ static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); int ret; if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0) @@ -670,7 +670,7 @@ static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch) static unsigned int netem_drop(struct Qdisc* sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); unsigned int len; if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) { @@ -686,7 +686,7 @@ static unsigned int netem_drop(struct Qdisc* sch) */ static struct sk_buff *netem_dequeue(struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; psched_time_t now; @@ -726,7 +726,7 @@ static void netem_watchdog(unsigned long arg) static void netem_reset(struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); qdisc_reset(q->qdisc); skb_queue_purge(&q->delayed); @@ -754,7 +754,7 @@ static int set_fifo_limit(struct Qdisc *q, int limit) static int netem_change(struct Qdisc *sch, struct rtattr *opt) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); struct tc_netem_qopt *qopt = RTA_DATA(opt); struct Qdisc *child; int ret; @@ -791,7 +791,7 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt) static int netem_init(struct Qdisc *sch, struct rtattr *opt) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); if (!opt) return -EINVAL; @@ -809,23 +809,21 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt) static void netem_destroy(struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); del_timer_sync(&q->timer); - qdisc_destroy(q->qdisc); - q->qdisc = &noop_qdisc; } static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct tc_netem_qopt qopt; qopt.latency = q->latency; qopt.jitter = q->jitter; - qopt.limit = sch->dev->tx_queue_len; + qopt.limit = q->limit; qopt.loss = q->loss; qopt.gap = q->gap; @@ -841,7 +839,7 @@ rtattr_failure: static int netem_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, struct tcmsg *tcm) { - struct netem_sched_data *q = (struct netem_sched_data*)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); if (cl != 1) /* only one class */ return -ENOENT; @@ -855,7 +853,7 @@ static int netem_dump_class(struct Qdisc *sch, unsigned long cl, static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); if (new == NULL) new = &noop_qdisc; @@ -871,7 +869,7 @@ static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); return q->qdisc; } diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index a13d21994692..6961f081170f 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -49,7 +49,7 @@ struct prio_sched_data struct Qdisc *prio_classify(struct sk_buff *skb, struct Qdisc *sch,int *r) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); u32 band = skb->priority; struct tcf_result res; @@ -151,7 +151,7 @@ static struct sk_buff * prio_dequeue(struct Qdisc* sch) { struct sk_buff *skb; - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); int prio; struct Qdisc *qdisc; @@ -169,7 +169,7 @@ prio_dequeue(struct Qdisc* sch) static unsigned int prio_drop(struct Qdisc* sch) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); int prio; unsigned int len; struct Qdisc *qdisc; @@ -189,7 +189,7 @@ static void prio_reset(struct Qdisc* sch) { int prio; - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); for (prio=0; prio<q->bands; prio++) qdisc_reset(q->queues[prio]); @@ -200,7 +200,7 @@ static void prio_destroy(struct Qdisc* sch) { int prio; - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); struct tcf_proto *tp; while ((tp = q->filter_list) != NULL) { @@ -208,15 +208,13 @@ prio_destroy(struct Qdisc* sch) tcf_destroy(tp); } - for (prio=0; prio<q->bands; prio++) { + for (prio=0; prio<q->bands; prio++) qdisc_destroy(q->queues[prio]); - q->queues[prio] = &noop_qdisc; - } } static int prio_tune(struct Qdisc *sch, struct rtattr *opt) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); struct tc_prio_qopt *qopt = RTA_DATA(opt); int i; @@ -261,7 +259,7 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt) static int prio_init(struct Qdisc *sch, struct rtattr *opt) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); int i; for (i=0; i<TCQ_PRIO_BANDS; i++) @@ -280,7 +278,7 @@ static int prio_init(struct Qdisc *sch, struct rtattr *opt) static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct tc_prio_qopt opt; @@ -297,7 +295,7 @@ rtattr_failure: static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); unsigned long band = arg - 1; if (band >= q->bands) @@ -319,7 +317,7 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, static struct Qdisc * prio_leaf(struct Qdisc *sch, unsigned long arg) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); unsigned long band = arg - 1; if (band >= q->bands) @@ -330,7 +328,7 @@ prio_leaf(struct Qdisc *sch, unsigned long arg) static unsigned long prio_get(struct Qdisc *sch, u32 classid) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); unsigned long band = TC_H_MIN(classid); if (band - 1 >= q->bands) @@ -352,7 +350,7 @@ static void prio_put(struct Qdisc *q, unsigned long cl) static int prio_change(struct Qdisc *sch, u32 handle, u32 parent, struct rtattr **tca, unsigned long *arg) { unsigned long cl = *arg; - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); if (cl - 1 > q->bands) return -ENOENT; @@ -361,7 +359,7 @@ static int prio_change(struct Qdisc *sch, u32 handle, u32 parent, struct rtattr static int prio_delete(struct Qdisc *sch, unsigned long cl) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); if (cl - 1 > q->bands) return -ENOENT; return 0; @@ -371,7 +369,7 @@ static int prio_delete(struct Qdisc *sch, unsigned long cl) static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, struct tcmsg *tcm) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); if (cl - 1 > q->bands) return -ENOENT; @@ -383,7 +381,7 @@ static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff * static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); int prio; if (arg->stop) @@ -404,7 +402,7 @@ static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg) static struct tcf_proto ** prio_find_tcf(struct Qdisc *sch, unsigned long cl) { - struct prio_sched_data *q = (struct prio_sched_data *)sch->data; + struct prio_sched_data *q = qdisc_priv(sch); if (cl) return NULL; diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 9e6c85ceb2c4..5630abb209ad 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -180,7 +180,7 @@ static int red_ecn_mark(struct sk_buff *skb) static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) { - struct red_sched_data *q = (struct red_sched_data *)sch->data; + struct red_sched_data *q = qdisc_priv(sch); psched_time_t now; @@ -303,7 +303,7 @@ drop: static int red_requeue(struct sk_buff *skb, struct Qdisc* sch) { - struct red_sched_data *q = (struct red_sched_data *)sch->data; + struct red_sched_data *q = qdisc_priv(sch); PSCHED_SET_PASTPERFECT(q->qidlestart); @@ -316,7 +316,7 @@ static struct sk_buff * red_dequeue(struct Qdisc* sch) { struct sk_buff *skb; - struct red_sched_data *q = (struct red_sched_data *)sch->data; + struct red_sched_data *q = qdisc_priv(sch); skb = __skb_dequeue(&sch->q); if (skb) { @@ -330,7 +330,7 @@ red_dequeue(struct Qdisc* sch) static unsigned int red_drop(struct Qdisc* sch) { struct sk_buff *skb; - struct red_sched_data *q = (struct red_sched_data *)sch->data; + struct red_sched_data *q = qdisc_priv(sch); skb = __skb_dequeue_tail(&sch->q); if (skb) { @@ -347,7 +347,7 @@ static unsigned int red_drop(struct Qdisc* sch) static void red_reset(struct Qdisc* sch) { - struct red_sched_data *q = (struct red_sched_data *)sch->data; + struct red_sched_data *q = qdisc_priv(sch); __skb_queue_purge(&sch->q); sch->stats.backlog = 0; @@ -358,7 +358,7 @@ static void red_reset(struct Qdisc* sch) static int red_change(struct Qdisc *sch, struct rtattr *opt) { - struct red_sched_data *q = (struct red_sched_data *)sch->data; + struct red_sched_data *q = qdisc_priv(sch); struct rtattr *tb[TCA_RED_STAB]; struct tc_red_qopt *ctl; @@ -407,7 +407,7 @@ rtattr_failure: static int red_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct red_sched_data *q = (struct red_sched_data *)sch->data; + struct red_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct rtattr *rta; struct tc_red_qopt opt; @@ -434,10 +434,6 @@ rtattr_failure: return -1; } -static void red_destroy(struct Qdisc *sch) -{ -} - static struct Qdisc_ops red_qdisc_ops = { .next = NULL, .cl_ops = NULL, @@ -449,7 +445,6 @@ static struct Qdisc_ops red_qdisc_ops = { .drop = red_drop, .init = red_init, .reset = red_reset, - .destroy = red_destroy, .change = red_change, .dump = red_dump, .owner = THIS_MODULE, diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index acf2666ad748..f37d9cdd00fe 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -211,7 +211,7 @@ static inline void sfq_inc(struct sfq_sched_data *q, sfq_index x) static unsigned int sfq_drop(struct Qdisc *sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); sfq_index d = q->max_depth; struct sk_buff *skb; unsigned int len; @@ -253,7 +253,7 @@ static unsigned int sfq_drop(struct Qdisc *sch) static int sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); unsigned hash = sfq_hash(q, skb); sfq_index x; @@ -288,7 +288,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) static int sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); unsigned hash = sfq_hash(q, skb); sfq_index x; @@ -324,7 +324,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) static struct sk_buff * sfq_dequeue(struct Qdisc* sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; sfq_index a, old_a; @@ -369,7 +369,7 @@ sfq_reset(struct Qdisc* sch) static void sfq_perturbation(unsigned long arg) { struct Qdisc *sch = (struct Qdisc*)arg; - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); q->perturbation = net_random()&0x1F; q->perturb_timer.expires = jiffies + q->perturb_period; @@ -382,7 +382,7 @@ static void sfq_perturbation(unsigned long arg) static int sfq_change(struct Qdisc *sch, struct rtattr *opt) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); struct tc_sfq_qopt *ctl = RTA_DATA(opt); if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) @@ -408,7 +408,7 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) static int sfq_init(struct Qdisc *sch, struct rtattr *opt) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); int i; init_timer(&q->perturb_timer); @@ -440,13 +440,13 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt) static void sfq_destroy(struct Qdisc *sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); del_timer(&q->perturb_timer); } static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct tc_sfq_qopt opt; diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index e1eaf634baf8..a1df30471451 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -137,7 +137,7 @@ struct tbf_sched_data static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); int ret; if (skb->len > q->max_size) { @@ -163,7 +163,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) static int tbf_requeue(struct sk_buff *skb, struct Qdisc* sch) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); int ret; if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0) @@ -174,7 +174,7 @@ static int tbf_requeue(struct sk_buff *skb, struct Qdisc* sch) static unsigned int tbf_drop(struct Qdisc* sch) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); unsigned int len; if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) { @@ -194,7 +194,7 @@ static void tbf_watchdog(unsigned long arg) static struct sk_buff *tbf_dequeue(struct Qdisc* sch) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; skb = q->qdisc->dequeue(q->qdisc); @@ -261,7 +261,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) static void tbf_reset(struct Qdisc* sch) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); qdisc_reset(q->qdisc); sch->q.qlen = 0; @@ -300,7 +300,7 @@ static struct Qdisc *tbf_create_dflt_qdisc(struct net_device *dev, u32 limit) static int tbf_change(struct Qdisc* sch, struct rtattr *opt) { int err = -EINVAL; - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); struct rtattr *tb[TCA_TBF_PTAB]; struct tc_tbf_qopt *qopt; struct qdisc_rate_table *rtab = NULL; @@ -366,7 +366,7 @@ done: static int tbf_init(struct Qdisc* sch, struct rtattr *opt) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); if (opt == NULL) return -EINVAL; @@ -383,7 +383,7 @@ static int tbf_init(struct Qdisc* sch, struct rtattr *opt) static void tbf_destroy(struct Qdisc *sch) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); del_timer(&q->wd_timer); @@ -393,12 +393,11 @@ static void tbf_destroy(struct Qdisc *sch) qdisc_put_rtab(q->R_tab); qdisc_destroy(q->qdisc); - q->qdisc = &noop_qdisc; } static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct rtattr *rta; struct tc_tbf_qopt opt; @@ -427,7 +426,7 @@ rtattr_failure: static int tbf_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, struct tcmsg *tcm) { - struct tbf_sched_data *q = (struct tbf_sched_data*)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); if (cl != 1) /* only one class */ return -ENOENT; @@ -441,7 +440,7 @@ static int tbf_dump_class(struct Qdisc *sch, unsigned long cl, static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); if (new == NULL) new = &noop_qdisc; @@ -457,7 +456,7 @@ static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, static struct Qdisc *tbf_leaf(struct Qdisc *sch, unsigned long arg) { - struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data; + struct tbf_sched_data *q = qdisc_priv(sch); return q->qdisc; } diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index da5e89c22b83..963e87a5be45 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -81,7 +81,7 @@ struct teql_sched_data struct sk_buff_head q; }; -#define NEXT_SLAVE(q) (((struct teql_sched_data*)((q)->data))->next) +#define NEXT_SLAVE(q) (((struct teql_sched_data*)qdisc_priv(q))->next) #define FMASK (IFF_BROADCAST|IFF_POINTOPOINT|IFF_BROADCAST) @@ -91,7 +91,7 @@ static int teql_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct net_device *dev = sch->dev; - struct teql_sched_data *q = (struct teql_sched_data *)sch->data; + struct teql_sched_data *q = qdisc_priv(sch); __skb_queue_tail(&q->q, skb); if (q->q.qlen <= dev->tx_queue_len) { @@ -109,7 +109,7 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch) static int teql_requeue(struct sk_buff *skb, struct Qdisc* sch) { - struct teql_sched_data *q = (struct teql_sched_data *)sch->data; + struct teql_sched_data *q = qdisc_priv(sch); __skb_queue_head(&q->q, skb); return 0; @@ -118,7 +118,7 @@ teql_requeue(struct sk_buff *skb, struct Qdisc* sch) static struct sk_buff * teql_dequeue(struct Qdisc* sch) { - struct teql_sched_data *dat = (struct teql_sched_data *)sch->data; + struct teql_sched_data *dat = qdisc_priv(sch); struct sk_buff *skb; skb = __skb_dequeue(&dat->q); @@ -143,7 +143,7 @@ teql_neigh_release(struct neighbour *n) static void teql_reset(struct Qdisc* sch) { - struct teql_sched_data *dat = (struct teql_sched_data *)sch->data; + struct teql_sched_data *dat = qdisc_priv(sch); skb_queue_purge(&dat->q); sch->q.qlen = 0; @@ -154,7 +154,7 @@ static void teql_destroy(struct Qdisc* sch) { struct Qdisc *q, *prev; - struct teql_sched_data *dat = (struct teql_sched_data *)sch->data; + struct teql_sched_data *dat = qdisc_priv(sch); struct teql_master *master = dat->m; if ((prev = master->slaves) != NULL) { @@ -184,7 +184,7 @@ static int teql_qdisc_init(struct Qdisc *sch, struct rtattr *opt) { struct net_device *dev = sch->dev; struct teql_master *m = (struct teql_master*)sch->ops; - struct teql_sched_data *q = (struct teql_sched_data *)sch->data; + struct teql_sched_data *q = qdisc_priv(sch); if (dev->hard_header_len > m->dev->hard_header_len) return -EINVAL; @@ -229,7 +229,7 @@ static int teql_qdisc_init(struct Qdisc *sch, struct rtattr *opt) static int __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) { - struct teql_sched_data *q = (void*)dev->qdisc->data; + struct teql_sched_data *q = qdisc_priv(dev->qdisc); struct neighbour *mn = skb->dst->neighbour; struct neighbour *n = q->ncache; diff --git a/net/socket.c b/net/socket.c index 5bb81ec300e2..275d8cf6d3be 100644 --- a/net/socket.c +++ b/net/socket.c @@ -401,7 +401,7 @@ int sock_map_fd(struct socket *sock) sock->file = file; file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; - file->f_mode = 3; + file->f_mode = FMODE_READ | FMODE_WRITE; file->f_flags = O_RDWR; file->f_pos = 0; fd_install(fd, file); @@ -727,9 +727,6 @@ ssize_t sock_sendpage(struct file *file, struct page *page, struct socket *sock; int flags; - if (ppos != &file->f_pos) - return -ESPIPE; - sock = SOCKET_I(file->f_dentry->d_inode); flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index e84acd07f822..bb54be851523 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -582,9 +582,6 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data; int err; - if (ppos != &filp->f_pos) - return -ESPIPE; - if (count == 0) return 0; @@ -662,9 +659,6 @@ cache_write(struct file *filp, const char __user *buf, size_t count, int err; struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data; - if (ppos != &filp->f_pos) - return -ESPIPE; - if (count == 0) return 0; if (count >= sizeof(write_buf)) @@ -751,6 +745,7 @@ cache_open(struct inode *inode, struct file *filp) { struct cache_reader *rp = NULL; + nonseekable_open(inode, filp); if (filp->f_mode & FMODE_READ) { struct cache_detail *cd = PDE(inode)->data; @@ -1212,6 +1207,7 @@ static ssize_t write_flush(struct file * file, const char __user * buf, } static struct file_operations cache_flush_operations = { + .open = nonseekable_open, .read = read_flush, .write = write_flush, }; diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index e69a7fbb489c..1b9616a12e24 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -58,14 +58,14 @@ rpc_unregister_sysctl(void) static int proc_dodebug(ctl_table *table, int write, struct file *file, - void __user *buffer, size_t *lenp) + void __user *buffer, size_t *lenp, loff_t *ppos) { char tmpbuf[20], c, *s; char __user *p; unsigned int value; size_t left, len; - if ((file->f_pos && !write) || !*lenp) { + if ((*ppos && !write) || !*lenp) { *lenp = 0; return 0; } @@ -115,7 +115,7 @@ proc_dodebug(ctl_table *table, int write, struct file *file, done: *lenp -= left; - file->f_pos += *lenp; + *ppos += *lenp; return 0; } diff --git a/sound/core/info.c b/sound/core/info.c index 0b08203d50e5..1eb7d916a365 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -181,30 +181,37 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer, struct snd_info_entry *entry; snd_info_buffer_t *buf; size_t size = 0; + loff_t pos; data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO); snd_assert(data != NULL, return -ENXIO); + pos = *offset; + if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) + return -EIO; + if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) + return -EIO; entry = data->entry; switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: buf = data->rbuffer; if (buf == NULL) return -EIO; - if (file->f_pos >= (long)buf->size) + if (pos >= buf->size) return 0; - size = buf->size - file->f_pos; + size = buf->size - pos; size = min(count, size); - if (copy_to_user(buffer, buf->buffer + file->f_pos, size)) + if (copy_to_user(buffer, buf->buffer + pos, size)) return -EFAULT; - file->f_pos += size; break; case SNDRV_INFO_CONTENT_DATA: if (entry->c.ops->read) - return entry->c.ops->read(entry, + size = entry->c.ops->read(entry, data->file_private_data, - file, buffer, count); + file, buffer, count, pos); break; } + if ((ssize_t) size > 0) + *offset = pos + size; return size; } @@ -215,34 +222,39 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer struct snd_info_entry *entry; snd_info_buffer_t *buf; size_t size = 0; + loff_t pos; data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO); snd_assert(data != NULL, return -ENXIO); entry = data->entry; + pos = *offset; + if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) + return -EIO; + if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) + return -EIO; switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: buf = data->wbuffer; if (buf == NULL) return -EIO; - if (file->f_pos < 0) - return -EINVAL; - if (file->f_pos >= (long)buf->len) + if (pos >= buf->len) return -ENOMEM; - size = buf->len - file->f_pos; + size = buf->len - pos; size = min(count, size); - if (copy_from_user(buf->buffer + file->f_pos, buffer, size)) + if (copy_from_user(buf->buffer + pos, buffer, size)) return -EFAULT; - if ((long)buf->size < file->f_pos + size) - buf->size = file->f_pos + size; - file->f_pos += size; + if ((long)buf->size < pos + size) + buf->size = pos + size; break; case SNDRV_INFO_CONTENT_DATA: if (entry->c.ops->write) - return entry->c.ops->write(entry, + size = entry->c.ops->write(entry, data->file_private_data, - file, buffer, count); + file, buffer, count, pos); break; } + if ((ssize_t) size > 0) + *offset = pos + size; return size; } diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c index f2f364d15a26..bbea9ab1c859 100644 --- a/sound/drivers/opl4/opl4_proc.c +++ b/sound/drivers/opl4/opl4_proc.c @@ -50,41 +50,42 @@ static int snd_opl4_mem_proc_release(snd_info_entry_t *entry, } static long snd_opl4_mem_proc_read(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char __user *_buf, long count) + struct file *file, char __user *_buf, + unsigned long count, unsigned long pos) { opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO); long size; char* buf; size = count; - if (file->f_pos + size > entry->size) - size = entry->size - file->f_pos; + if (pos + size > entry->size) + size = entry->size - pos; if (size > 0) { buf = vmalloc(size); if (!buf) return -ENOMEM; - snd_opl4_read_memory(opl4, buf, file->f_pos, size); + snd_opl4_read_memory(opl4, buf, pos, size); if (copy_to_user(_buf, buf, size)) { vfree(buf); return -EFAULT; } vfree(buf); - file->f_pos += size; return size; } return 0; } static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_data, - struct file *file, const char __user *_buf, long count) + struct file *file, const char __user *_buf, + unsigned long count, unsigned long pos) { opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO); long size; char *buf; size = count; - if (file->f_pos + size > entry->size) - size = entry->size - file->f_pos; + if (pos + size > entry->size) + size = entry->size - pos; if (size > 0) { buf = vmalloc(size); if (!buf) @@ -93,9 +94,8 @@ static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_ vfree(buf); return -EFAULT; } - snd_opl4_write_memory(opl4, buf, file->f_pos, size); + snd_opl4_write_memory(opl4, buf, pos, size); vfree(buf); - file->f_pos += size; return size; } return 0; diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c index 95071a084184..6ee2d76ee828 100644 --- a/sound/isa/gus/gus_mem_proc.c +++ b/sound/isa/gus/gus_mem_proc.c @@ -33,7 +33,8 @@ typedef struct gus_proc_private { } gus_proc_private_t; static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char __user *buf, long count) + struct file *file, char __user *buf, + unsigned long count, unsigned long pos) { long size; gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return -ENXIO); @@ -41,12 +42,11 @@ static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_da int err; size = count; - if (file->f_pos + size > priv->size) - size = (long)priv->size - file->f_pos; + if (pos + size > priv->size) + size = (long)priv->size - pos; if (size > 0) { - if ((err = snd_gus_dram_read(gus, buf, file->f_pos, size, priv->rom)) < 0) + if ((err = snd_gus_dram_read(gus, buf, pos, size, priv->rom)) < 0) return err; - file->f_pos += size; return size; } return 0; diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c index 6e8be40abafe..2423b1f2d590 100644 --- a/sound/oss/ad1889.c +++ b/sound/oss/ad1889.c @@ -452,9 +452,6 @@ static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t ssize_t ret = 0; DECLARE_WAITQUEUE(wait, current); - if (ppos != &file->f_pos) - return -ESPIPE; - down(&state->sem); #if 0 if (dmabuf->mapped) { @@ -764,7 +761,7 @@ static int ad1889_open(struct inode *inode, struct file *file) ad1889_set_wav_rate(ad1889_dev, 44100); ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE); AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */ - return 0; + return nonseekable_open(inode, file); } static int ad1889_release(struct inode *inode, struct file *file) diff --git a/sound/oss/ali5455.c b/sound/oss/ali5455.c index 0d1e9dce269e..a7e2c3c0a5fd 100644 --- a/sound/oss/ali5455.c +++ b/sound/oss/ali5455.c @@ -1593,8 +1593,6 @@ static ssize_t ali_read(struct file *file, char __user *buffer, #ifdef DEBUG2 printk("ali_audio: ali_read called, count = %d\n", count); #endif - if (ppos != &file->f_pos) - return -ESPIPE; if (dmabuf->mapped) return -ENXIO; if (dmabuf->enable & DAC_RUNNING) @@ -1734,8 +1732,6 @@ static ssize_t ali_write(struct file *file, #ifdef DEBUG2 printk("ali_audio: ali_write called, count = %d\n", count); #endif - if (ppos != &file->f_pos) - return -ESPIPE; if (dmabuf->mapped) return -ENXIO; if (dmabuf->enable & ADC_RUNNING) @@ -2890,7 +2886,7 @@ found_virt: state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); outl(0x00000000, card->iobase + ALI_INTERRUPTCR); outl(0x00000000, card->iobase + ALI_INTERRUPTSR); - return 0; + return nonseekable_open(inode, file); } static int ali_release(struct inode *inode, struct file *file) @@ -3047,7 +3043,7 @@ static int ali_open_mixdev(struct inode *inode, struct file *file) if (card->ac97_codec[i] != NULL && card->ac97_codec[i]->dev_mixer == minor) { file->private_data = card->ac97_codec[i]; - return 0; + return nonseekable_open(inode, file); } } return -ENODEV; diff --git a/sound/oss/au1000.c b/sound/oss/au1000.c index 0ad69a2e7771..ccfbad2dd02f 100644 --- a/sound/oss/au1000.c +++ b/sound/oss/au1000.c @@ -886,7 +886,7 @@ static loff_t au1000_llseek(struct file *file, loff_t offset, int origin) static int au1000_open_mixdev(struct inode *inode, struct file *file) { file->private_data = &au1000_state; - return 0; + return nonseekable_open(inode, file); } static int au1000_release_mixdev(struct inode *inode, struct file *file) @@ -1120,8 +1120,6 @@ static ssize_t au1000_read(struct file *file, char *buffer, unsigned long flags; int cnt, usercnt, avail; - if (ppos != &file->f_pos) - return -ESPIPE; if (db->mapped) return -ENXIO; if (!access_ok(VERIFY_WRITE, buffer, count)) @@ -1204,8 +1202,6 @@ static ssize_t au1000_write(struct file *file, const char *buffer, dbg("write: count=%d", count); #endif - if (ppos != &file->f_pos) - return -ESPIPE; if (db->mapped) return -ENXIO; if (!access_ok(VERIFY_READ, buffer, count)) @@ -1907,7 +1903,7 @@ static int au1000_open(struct inode *inode, struct file *file) s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&s->open_sem); init_MUTEX(&s->sem); - return 0; + return nonseekable_open(inode, file); } static int au1000_release(struct inode *inode, struct file *file) diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c index c0da38bcdfc9..386107f47bd4 100644 --- a/sound/oss/cmpci.c +++ b/sound/oss/cmpci.c @@ -1852,7 +1852,7 @@ static int cm_open_mixdev(struct inode *inode, struct file *file) } VALIDATE_STATE(s); file->private_data = s; - return 0; + return nonseekable_open(inode, file); } static int cm_release_mixdev(struct inode *inode, struct file *file) @@ -1926,8 +1926,6 @@ static ssize_t cm_read(struct file *file, char __user *buffer, size_t count, lof int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) @@ -2028,8 +2026,6 @@ static ssize_t cm_write(struct file *file, const char __user *buffer, size_t cou int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac.mapped) return -ENXIO; if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) @@ -2878,7 +2874,7 @@ static int cm_open(struct inode *inode, struct file *file) set_fmt(s, fmtm, fmts); s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int cm_release(struct inode *inode, struct file *file) diff --git a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c index c2b496e3415f..a6f09cc63c46 100644 --- a/sound/oss/cs4281/cs4281m.c +++ b/sound/oss/cs4281/cs4281m.c @@ -2592,7 +2592,7 @@ static int cs4281_open_mixdev(struct inode *inode, struct file *file) CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, printk(KERN_INFO "cs4281: cs4281_open_mixdev()- 0\n")); - return 0; + return nonseekable_open(inode, file); } @@ -2874,8 +2874,6 @@ static ssize_t cs4281_read(struct file *file, char __user *buffer, size_t count, printk(KERN_INFO "cs4281: cs4281_read()+ %Zu \n", count)); VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) @@ -2990,8 +2988,6 @@ static ssize_t cs4281_write(struct file *file, const char __user *buffer, count)); VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac.mapped) return -ENXIO; if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) @@ -3725,7 +3721,7 @@ static int cs4281_open(struct inode *inode, struct file *file) } CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO "cs4281: cs4281_open()- 0\n")); - return 0; + return nonseekable_open(inode, file); } @@ -3842,8 +3838,6 @@ static ssize_t cs4281_midi_read(struct file *file, char __user *buffer, int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; ret = 0; @@ -3890,8 +3884,6 @@ static ssize_t cs4281_midi_write(struct file *file, const char __user *buffer, int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; ret = 0; @@ -4025,7 +4017,7 @@ static int cs4281_midi_open(struct inode *inode, struct file *file) f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c index 676f9881fc78..418f976c4554 100644 --- a/sound/oss/cs46xx.c +++ b/sound/oss/cs46xx.c @@ -1725,8 +1725,6 @@ static ssize_t cs_midi_read(struct file *file, char __user *buffer, size_t count unsigned ptr; int cnt; - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; ret = 0; @@ -1770,8 +1768,6 @@ static ssize_t cs_midi_write(struct file *file, const char __user *buffer, size_ unsigned ptr; int cnt; - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; ret = 0; @@ -2106,8 +2102,6 @@ static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, lof return -ENODEV; dmabuf = &state->dmabuf; - if (ppos != &file->f_pos) - return -ESPIPE; if (dmabuf->mapped) return -ENXIO; if (!access_ok(VERIFY_WRITE, buffer, count)) @@ -2216,9 +2210,6 @@ static ssize_t cs_write(struct file *file, const char __user *buffer, size_t cou return -EFAULT; dmabuf = &state->dmabuf; - if (ppos != &file->f_pos) - return -ESPIPE; - down(&state->sem); if (dmabuf->mapped) { @@ -3370,7 +3361,7 @@ static int cs_open(struct inode *inode, struct file *file) return ret; } CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n") ); - return 0; + return nonseekable_open(inode, file); } static int cs_release(struct inode *inode, struct file *file) @@ -4104,7 +4095,7 @@ static int cs_open_mixdev(struct inode *inode, struct file *file) CS_INC_USE_COUNT(&card->mixer_use_cnt); CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n")); - return 0; + return nonseekable_open(inode, file); } static int cs_release_mixdev(struct inode *inode, struct file *file) diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c index 1aac3655d68e..9cf30ab2ff42 100644 --- a/sound/oss/emu10k1/audio.c +++ b/sound/oss/emu10k1/audio.c @@ -59,9 +59,6 @@ static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t DPD(3, "emu10k1_audio_read(), buffer=%p, count=%d\n", buffer, (u32) count); - if (ppos != &file->f_pos) - return -ESPIPE; - if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; @@ -146,9 +143,6 @@ static ssize_t emu10k1_audio_write(struct file *file, const char __user *buffer, DPD(3, "emu10k1_audio_write(), buffer=%p, count=%d\n", buffer, (u32) count); - if (ppos != &file->f_pos) - return -ESPIPE; - if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; @@ -1249,7 +1243,7 @@ match: file->private_data = (void *) wave_dev; - return 0; + return nonseekable_open(inode, file); } static int emu10k1_audio_release(struct inode *inode, struct file *file) diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c index 0f220081e878..ec2424db43cb 100644 --- a/sound/oss/emu10k1/midi.c +++ b/sound/oss/emu10k1/midi.c @@ -185,7 +185,7 @@ match: up(&card->open_sem); - return 0; + return nonseekable_open(inode, file); } static int emu10k1_midi_release(struct inode *inode, struct file *file) @@ -253,9 +253,6 @@ static ssize_t emu10k1_midi_read(struct file *file, char __user *buffer, size_t DPD(4, "emu10k1_midi_read(), count %#x\n", (u32) count); - if (pos != &file->f_pos) - return -ESPIPE; - if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; @@ -328,9 +325,6 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer, DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count); - if (pos != &file->f_pos) - return -ESPIPE; - if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; diff --git a/sound/oss/es1370.c b/sound/oss/es1370.c index 68189853ac11..57f9bc147699 100644 --- a/sound/oss/es1370.c +++ b/sound/oss/es1370.c @@ -1037,7 +1037,7 @@ static int es1370_open_mixdev(struct inode *inode, struct file *file) } VALIDATE_STATE(s); file->private_data = s; - return 0; + return nonseekable_open(inode, file); } static int es1370_release_mixdev(struct inode *inode, struct file *file) @@ -1147,8 +1147,6 @@ static ssize_t es1370_read(struct file *file, char __user *buffer, size_t count, int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!access_ok(VERIFY_WRITE, buffer, count)) @@ -1225,8 +1223,6 @@ static ssize_t es1370_write(struct file *file, const char __user *buffer, size_t int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac2.mapped) return -ENXIO; if (!access_ok(VERIFY_READ, buffer, count)) @@ -1789,7 +1785,7 @@ static int es1370_open(struct inode *inode, struct file *file) s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&s->open_sem); init_MUTEX(&s->sem); - return 0; + return nonseekable_open(inode, file); } static int es1370_release(struct inode *inode, struct file *file) @@ -1841,8 +1837,6 @@ static ssize_t es1370_write_dac(struct file *file, const char __user *buffer, si int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac1.mapped) return -ENXIO; if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) @@ -2222,7 +2216,7 @@ static int es1370_open_dac(struct inode *inode, struct file *file) spin_unlock_irqrestore(&s->lock, flags); s->open_mode |= FMODE_DAC; up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int es1370_release_dac(struct inode *inode, struct file *file) @@ -2265,8 +2259,6 @@ static ssize_t es1370_midi_read(struct file *file, char __user *buffer, size_t c int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; if (count == 0) @@ -2328,8 +2320,6 @@ static ssize_t es1370_midi_write(struct file *file, const char __user *buffer, s int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; if (count == 0) @@ -2464,7 +2454,7 @@ static int es1370_midi_open(struct inode *inode, struct file *file) spin_unlock_irqrestore(&s->lock, flags); s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int es1370_midi_release(struct inode *inode, struct file *file) diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c index 7d1a108dde35..d6b59fbe5ad3 100644 --- a/sound/oss/es1371.c +++ b/sound/oss/es1371.c @@ -1223,7 +1223,7 @@ static int es1371_open_mixdev(struct inode *inode, struct file *file) } VALIDATE_STATE(s); file->private_data = s; - return 0; + return nonseekable_open(inode, file); } static int es1371_release_mixdev(struct inode *inode, struct file *file) @@ -1334,8 +1334,6 @@ static ssize_t es1371_read(struct file *file, char __user *buffer, size_t count, int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!access_ok(VERIFY_WRITE, buffer, count)) @@ -1413,8 +1411,6 @@ static ssize_t es1371_write(struct file *file, const char __user *buffer, size_t int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac2.mapped) return -ENXIO; if (!access_ok(VERIFY_READ, buffer, count)) @@ -1978,7 +1974,7 @@ static int es1371_open(struct inode *inode, struct file *file) s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&s->open_sem); init_MUTEX(&s->sem); - return 0; + return nonseekable_open(inode, file); } static int es1371_release(struct inode *inode, struct file *file) @@ -2029,8 +2025,6 @@ static ssize_t es1371_write_dac(struct file *file, const char __user *buffer, si int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac1.mapped) return -ENXIO; if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) @@ -2400,7 +2394,7 @@ static int es1371_open_dac(struct inode *inode, struct file *file) spin_unlock_irqrestore(&s->lock, flags); s->open_mode |= FMODE_DAC; up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int es1371_release_dac(struct inode *inode, struct file *file) @@ -2443,8 +2437,6 @@ static ssize_t es1371_midi_read(struct file *file, char __user *buffer, size_t c int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; if (count == 0) @@ -2506,8 +2498,6 @@ static ssize_t es1371_midi_write(struct file *file, const char __user *buffer, s int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; if (count == 0) @@ -2642,7 +2632,7 @@ static int es1371_midi_open(struct inode *inode, struct file *file) spin_unlock_irqrestore(&s->lock, flags); s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int es1371_midi_release(struct inode *inode, struct file *file) diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c index b5096b5a4401..3002cbe68bf5 100644 --- a/sound/oss/esssolo1.c +++ b/sound/oss/esssolo1.c @@ -933,7 +933,7 @@ static int solo1_open_mixdev(struct inode *inode, struct file *file) return -ENODEV; VALIDATE_STATE(s); file->private_data = s; - return 0; + return nonseekable_open(inode, file); } static int solo1_release_mixdev(struct inode *inode, struct file *file) @@ -1010,8 +1010,6 @@ static ssize_t solo1_read(struct file *file, char __user *buffer, size_t count, int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) @@ -1106,8 +1104,6 @@ static ssize_t solo1_write(struct file *file, const char __user *buffer, size_t int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac.mapped) return -ENXIO; if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) @@ -1647,7 +1643,7 @@ static int solo1_open(struct inode *inode, struct file *file) s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&s->open_sem); prog_codec(s); - return 0; + return nonseekable_open(inode, file); } static /*const*/ struct file_operations solo1_audio_fops = { @@ -1740,8 +1736,6 @@ static ssize_t solo1_midi_read(struct file *file, char __user *buffer, size_t co int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; if (count == 0) @@ -1803,8 +1797,6 @@ static ssize_t solo1_midi_write(struct file *file, const char __user *buffer, si int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; if (count == 0) @@ -1951,7 +1943,7 @@ static int solo1_midi_open(struct inode *inode, struct file *file) spin_unlock_irqrestore(&s->lock, flags); s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int solo1_midi_release(struct inode *inode, struct file *file) @@ -2161,7 +2153,7 @@ static int solo1_dmfm_open(struct inode *inode, struct file *file) outb(1, s->sbbase+3); /* enable OPL3 */ s->open_mode |= FMODE_DMFM; up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int solo1_dmfm_release(struct inode *inode, struct file *file) diff --git a/sound/oss/forte.c b/sound/oss/forte.c index 0d91bbf832f2..ac4badae5f5e 100644 --- a/sound/oss/forte.c +++ b/sound/oss/forte.c @@ -1265,7 +1265,7 @@ forte_dsp_open (struct inode *inode, struct file *file) if (file->f_mode & FMODE_READ) forte_channel_init (forte, &forte->rec); - return 0; + return nonseekable_open(inode, file); } @@ -1438,9 +1438,6 @@ forte_dsp_write (struct file *file, const char __user *buffer, size_t bytes, unsigned int i = bytes, sz = 0; unsigned long flags; - if (ppos != &file->f_pos) - return -ESPIPE; - if (!access_ok (VERIFY_READ, buffer, bytes)) return -EFAULT; @@ -1546,9 +1543,6 @@ forte_dsp_read (struct file *file, char __user *buffer, size_t bytes, unsigned int i = bytes, sz; unsigned long flags; - if (ppos != &file->f_pos) - return -ESPIPE; - if (!access_ok (VERIFY_WRITE, buffer, bytes)) return -EFAULT; diff --git a/sound/oss/hal2.c b/sound/oss/hal2.c index 1f49d04242f3..afe97c4ce069 100644 --- a/sound/oss/hal2.c +++ b/sound/oss/hal2.c @@ -959,7 +959,7 @@ static int hal2_open_mixdev(struct inode *inode, struct file *file) if (hal2) { file->private_data = hal2; - return 0; + return nonseekable_open(inode, file); } return -ENODEV; } @@ -1178,8 +1178,6 @@ static ssize_t hal2_read(struct file *file, char *buffer, if (!count) return 0; - if (ppos != &file->f_pos) - return -ESPIPE; if (down_interruptible(&adc->sem)) return -EINTR; if (file->f_flags & O_NONBLOCK) { @@ -1234,8 +1232,6 @@ static ssize_t hal2_write(struct file *file, const char *buffer, if (!count) return 0; - if (ppos != &file->f_pos) - return -ESPIPE; if (down_interruptible(&dac->sem)) return -EINTR; if (file->f_flags & O_NONBLOCK) { @@ -1350,7 +1346,7 @@ static int hal2_open(struct inode *inode, struct file *file) dac->usecount++; } - return 0; + return nonseekable_open(inode, file); } static int hal2_release(struct inode *inode, struct file *file) diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c index 3de038a6bbc4..918c2a23b679 100644 --- a/sound/oss/i810_audio.c +++ b/sound/oss/i810_audio.c @@ -1434,8 +1434,6 @@ static ssize_t i810_read(struct file *file, char __user *buffer, size_t count, l printk("i810_audio: i810_read called, count = %d\n", count); #endif - if (ppos != &file->f_pos) - return -ESPIPE; if (dmabuf->mapped) return -ENXIO; if (dmabuf->enable & DAC_RUNNING) @@ -1574,8 +1572,6 @@ static ssize_t i810_write(struct file *file, const char __user *buffer, size_t c printk("i810_audio: i810_write called, count = %d\n", count); #endif - if (ppos != &file->f_pos) - return -ESPIPE; if (dmabuf->mapped) return -ENXIO; if (dmabuf->enable & ADC_RUNNING) @@ -2518,7 +2514,7 @@ found_virt: state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - return 0; + return nonseekable_open(inode, file); } static int i810_release(struct inode *inode, struct file *file) @@ -2685,7 +2681,7 @@ static int i810_open_mixdev(struct inode *inode, struct file *file) if (card->ac97_codec[i] != NULL && card->ac97_codec[i]->dev_mixer == minor) { file->private_data = card->ac97_codec[i]; - return 0; + return nonseekable_open(inode, file); } } return -ENODEV; diff --git a/sound/oss/ite8172.c b/sound/oss/ite8172.c index f62efd8a4aa6..16e7d01efec2 100644 --- a/sound/oss/ite8172.c +++ b/sound/oss/ite8172.c @@ -878,7 +878,7 @@ static int it8172_open_mixdev(struct inode *inode, struct file *file) break; } file->private_data = s; - return 0; + return nonseekable_open(inode, file); } static int it8172_release_mixdev(struct inode *inode, struct file *file) @@ -1093,8 +1093,6 @@ static ssize_t it8172_read(struct file *file, char *buffer, unsigned long flags; int cnt, remainder, avail; - if (ppos != &file->f_pos) - return -ESPIPE; if (db->mapped) return -ENXIO; if (!access_ok(VERIFY_WRITE, buffer, count)) @@ -1176,8 +1174,6 @@ static ssize_t it8172_write(struct file *file, const char *buffer, unsigned long flags; int cnt, remainder, avail; - if (ppos != &file->f_pos) - return -ESPIPE; if (db->mapped) return -ENXIO; if (!access_ok(VERIFY_READ, buffer, count)) @@ -1843,7 +1839,7 @@ static int it8172_open(struct inode *inode, struct file *file) s->open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE)); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int it8172_release(struct inode *inode, struct file *file) diff --git a/sound/oss/maestro.c b/sound/oss/maestro.c index 4a670f4e4d3a..66456dbb2727 100644 --- a/sound/oss/maestro.c +++ b/sound/oss/maestro.c @@ -2158,7 +2158,7 @@ static int ess_open_mixdev(struct inode *inode, struct file *file) if (!card) return -ENODEV; file->private_data = card; - return 0; + return nonseekable_open(inode, file); } static int ess_release_mixdev(struct inode *inode, struct file *file) @@ -2274,8 +2274,6 @@ ess_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) unsigned char *combbuf = NULL; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) @@ -2372,8 +2370,6 @@ ess_write(struct file *file, const char __user *buffer, size_t count, loff_t *pp int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac.mapped) return -ENXIO; if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) @@ -3082,7 +3078,7 @@ ess_open(struct inode *inode, struct file *file) s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int diff --git a/sound/oss/maestro3.c b/sound/oss/maestro3.c index 2830f7f1e1d9..c27e88f476f2 100644 --- a/sound/oss/maestro3.c +++ b/sound/oss/maestro3.c @@ -1333,8 +1333,6 @@ static ssize_t m3_read(struct file *file, char __user *buffer, size_t count, lof int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) @@ -1414,8 +1412,6 @@ static ssize_t m3_write(struct file *file, const char __user *buffer, size_t cou int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac.mapped) return -ENXIO; if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) @@ -2051,7 +2047,7 @@ static int m3_open(struct inode *inode, struct file *file) up(&s->open_sem); spin_unlock_irqrestore(&c->lock, flags); - return 0; + return nonseekable_open(inode, file); } static int m3_release(struct inode *inode, struct file *file) @@ -2165,7 +2161,7 @@ static int m3_open_mixdev(struct inode *inode, struct file *file) file->private_data = card->ac97; - return 0; + return nonseekable_open(inode, file); } static int m3_release_mixdev(struct inode *inode, struct file *file) diff --git a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c index 7ac7126664a7..b40611b422a0 100644 --- a/sound/oss/nec_vrc5477.c +++ b/sound/oss/nec_vrc5477.c @@ -868,7 +868,7 @@ static int vrc5477_ac97_open_mixdev(struct inode *inode, struct file *file) break; } file->private_data = s; - return 0; + return nonseekable_open(inode, file); } static int vrc5477_ac97_release_mixdev(struct inode *inode, struct file *file) @@ -1043,8 +1043,6 @@ vrc5477_ac97_read(struct file *file, int copyCount; size_t avail; - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; @@ -1229,8 +1227,6 @@ static ssize_t vrc5477_ac97_write(struct file *file, const char *buffer, unsigned long flags; int copyCount, avail; - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; ret = 0; @@ -1574,7 +1570,8 @@ static int vrc5477_ac97_open(struct inode *inode, struct file *file) struct list_head *list; struct vrc5477_ac97_state *s; int ret=0; - + + nonseekable_open(inode, file); for (list = devs.next; ; list = list->next) { if (list == &devs) return -ENODEV; diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c index 404ba23b1592..3df045dd55f9 100644 --- a/sound/oss/rme96xx.c +++ b/sound/oss/rme96xx.c @@ -1454,6 +1454,7 @@ static int rme96xx_open(struct inode *in, struct file *f) DBG(printk("device num %d open\n",devnum)); + nonseekable_open(in, f); for (list = devs.next; ; list = list->next) { if (list == &devs) return -ENODEV; @@ -1543,9 +1544,6 @@ static ssize_t rme96xx_write(struct file *file, const char __user *buffer, size_ if(dma == NULL || (dma->s) == NULL) return -ENXIO; - if (ppos != &file->f_pos) - return -ESPIPE; - if (dma->mmapped || !dma->opened) return -ENXIO; @@ -1611,9 +1609,6 @@ static ssize_t rme96xx_read(struct file *file, char __user *buffer, size_t count if(dma == NULL || (dma->s) == NULL) return -ENXIO; - if (ppos != &file->f_pos) - return -ESPIPE; - if (dma->mmapped || !dma->opened) return -ENXIO; @@ -1775,6 +1770,7 @@ static int rme96xx_mixer_open(struct inode *inode, struct file *file) COMM ("mixer open"); + nonseekable_open(inode, file); for (list = devs.next; ; list = list->next) { if (list == &devs) return -ENODEV; diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c index e231cf0a7e3d..8bb6deaad035 100644 --- a/sound/oss/sonicvibes.c +++ b/sound/oss/sonicvibes.c @@ -1252,7 +1252,7 @@ static int sv_open_mixdev(struct inode *inode, struct file *file) } VALIDATE_STATE(s); file->private_data = s; - return 0; + return nonseekable_open(inode, file); } static int sv_release_mixdev(struct inode *inode, struct file *file) @@ -1325,8 +1325,6 @@ static ssize_t sv_read(struct file *file, char __user *buffer, size_t count, lof int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) @@ -1410,8 +1408,6 @@ static ssize_t sv_write(struct file *file, const char __user *buffer, size_t cou int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac.mapped) return -ENXIO; if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) @@ -1954,7 +1950,7 @@ static int sv_open(struct inode *inode, struct file *file) set_fmt(s, fmtm, fmts); s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int sv_release(struct inode *inode, struct file *file) @@ -2005,8 +2001,6 @@ static ssize_t sv_midi_read(struct file *file, char __user *buffer, size_t count int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; if (count == 0) @@ -2068,8 +2062,6 @@ static ssize_t sv_midi_write(struct file *file, const char __user *buffer, size_ int cnt; VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; if (count == 0) @@ -2212,7 +2204,7 @@ static int sv_midi_open(struct inode *inode, struct file *file) spin_unlock_irqrestore(&s->lock, flags); s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int sv_midi_release(struct inode *inode, struct file *file) @@ -2414,7 +2406,7 @@ static int sv_dmfm_open(struct inode *inode, struct file *file) outb(1, s->iosynth+3); /* enable OPL3 */ s->open_mode |= FMODE_DMFM; up(&s->open_sem); - return 0; + return nonseekable_open(inode, file); } static int sv_dmfm_release(struct inode *inode, struct file *file) diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 0f58fa4944c0..4846dc2cb121 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -1526,14 +1526,6 @@ static int mixer_ioctl(struct cs4297a_state *s, unsigned int cmd, // --------------------------------------------------------------------- -static loff_t cs4297a_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - - -// --------------------------------------------------------------------- - static int cs4297a_open_mixdev(struct inode *inode, struct file *file) { int minor = iminor(inode); @@ -1561,7 +1553,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file) CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n")); - return 0; + return nonseekable_open(inode, file); } @@ -1588,7 +1580,7 @@ static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file, // ****************************************************************************************** static /*const */ struct file_operations cs4297a_mixer_fops = { .owner = THIS_MODULE, - .llseek = cs4297a_llseek, + .llseek = no_llseek, .ioctl = cs4297a_ioctl_mixdev, .open = cs4297a_open_mixdev, .release = cs4297a_release_mixdev, @@ -1658,8 +1650,6 @@ static ssize_t cs4297a_read(struct file *file, char *buffer, size_t count, printk(KERN_INFO "cs4297a: cs4297a_read()+ %d \n", count)); VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) @@ -1784,8 +1774,6 @@ static ssize_t cs4297a_write(struct file *file, const char *buffer, count)); VALIDATE_STATE(s); - if (ppos != &file->f_pos) - return -ESPIPE; if (s->dma_dac.mapped) return -ENXIO; if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) @@ -2494,7 +2482,7 @@ static int cs4297a_open(struct inode *inode, struct file *file) } CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO "cs4297a: cs4297a_open()- 0\n")); - return 0; + return nonseekable_open(inode, file); } @@ -2503,7 +2491,7 @@ static int cs4297a_open(struct inode *inode, struct file *file) // ****************************************************************************************** static /*const */ struct file_operations cs4297a_audio_fops = { .owner = THIS_MODULE, - .llseek = cs4297a_llseek, + .llseek = no_llseek, .read = cs4297a_read, .write = cs4297a_write, .poll = cs4297a_poll, diff --git a/sound/oss/trident.c b/sound/oss/trident.c index ed04f4007c2d..1beb4e9ffe89 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c @@ -1874,8 +1874,6 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos pr_debug("trident: trident_read called, count = %d\n", count); VALIDATE_STATE(state); - if (ppos != &file->f_pos) - return -ESPIPE; if (dmabuf->mapped) return -ENXIO; @@ -1992,8 +1990,6 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t pr_debug("trident: trident_write called, count = %d\n", count); VALIDATE_STATE(state); - if (ppos != &file->f_pos) - return -ESPIPE; /* * Guard against an mmap or ioctl while writing @@ -2823,7 +2819,7 @@ trident_open(struct inode *inode, struct file *file) pr_debug("trident: open virtual channel %d, hard channel %d\n", state->virt, dmabuf->channel->num); - return 0; + return nonseekable_open(inode, file); } static int @@ -4079,7 +4075,7 @@ trident_open_mixdev(struct inode *inode, struct file *file) match: file->private_data = card->ac97_codec[i]; - return 0; + return nonseekable_open(inode, file); } static int diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c index 40f3f2e2ed91..dc1c25663b10 100644 --- a/sound/oss/via82cxxx_audio.c +++ b/sound/oss/via82cxxx_audio.c @@ -1580,7 +1580,7 @@ match: file->private_data = card->ac97; DPRINTK ("EXIT, returning 0\n"); - return 0; + return nonseekable_open(inode, file); } static int via_mixer_ioctl (struct inode *inode, struct file *file, unsigned int cmd, @@ -2401,11 +2401,6 @@ static ssize_t via_dsp_read(struct file *file, char __user *buffer, size_t count card = file->private_data; assert (card != NULL); - if (ppos != &file->f_pos) { - DPRINTK ("EXIT, returning -ESPIPE\n"); - return -ESPIPE; - } - rc = via_syscall_down (card, nonblock); if (rc) goto out; @@ -2589,11 +2584,6 @@ static ssize_t via_dsp_write(struct file *file, const char __user *buffer, size_ card = file->private_data; assert (card != NULL); - if (ppos != &file->f_pos) { - DPRINTK ("EXIT, returning -ESPIPE\n"); - return -ESPIPE; - } - rc = via_syscall_down (card, nonblock); if (rc) goto out; @@ -3345,7 +3335,7 @@ match: } DPRINTK ("EXIT, returning 0\n"); - return 0; + return nonseekable_open(inode, file); } diff --git a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c index afa2876b6260..13bcc7621cf8 100644 --- a/sound/oss/ymfpci.c +++ b/sound/oss/ymfpci.c @@ -1231,8 +1231,6 @@ ymf_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) unsigned int swptr; int cnt; /* This many to go in this revolution */ - if (ppos != &file->f_pos) - return -ESPIPE; if (dmabuf->mapped) return -ENXIO; if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) @@ -1350,8 +1348,6 @@ ymf_write(struct file *file, const char __user *buffer, size_t count, loff_t *pp YMFDBGW("ymf_write: count %d\n", count); - if (ppos != &file->f_pos) - return -ESPIPE; if (dmabuf->mapped) return -ENXIO; if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) @@ -1965,7 +1961,7 @@ static int ymf_open(struct inode *inode, struct file *file) #endif up(&unit->open_sem); - return 0; + return nonseekable_open(inode, file); out_nodma: /* @@ -2043,7 +2039,7 @@ static int ymf_open_mixdev(struct inode *inode, struct file *file) match: file->private_data = unit->ac97_codec[i]; - return 0; + return nonseekable_open(inode, file); } static int ymf_ioctl_mixdev(struct inode *inode, struct file *file, diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 91a60417e7ec..86430a0bcd68 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1185,35 +1185,35 @@ static void snd_cs4281_proc_read(snd_info_entry_t *entry, } static long snd_cs4281_BA0_read(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char __user *buf, long count) + struct file *file, char __user *buf, + unsigned long count, unsigned long pos) { long size; cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO); size = count; - if (file->f_pos + size > CS4281_BA0_SIZE) - size = (long)CS4281_BA0_SIZE - file->f_pos; + if (pos + size > CS4281_BA0_SIZE) + size = (long)CS4281_BA0_SIZE - pos; if (size > 0) { - if (copy_to_user_fromio(buf, chip->ba0 + file->f_pos, size)) + if (copy_to_user_fromio(buf, chip->ba0 + pos, size)) return -EFAULT; - file->f_pos += size; } return size; } static long snd_cs4281_BA1_read(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char __user *buf, long count) + struct file *file, char __user *buf, + unsigned long count, unsigned long pos) { long size; cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO); size = count; - if (file->f_pos + size > CS4281_BA1_SIZE) - size = (long)CS4281_BA1_SIZE - file->f_pos; + if (pos + size > CS4281_BA1_SIZE) + size = (long)CS4281_BA1_SIZE - pos; if (size > 0) { - if (copy_to_user_fromio(buf, chip->ba1 + file->f_pos, size)) + if (copy_to_user_fromio(buf, chip->ba1 + pos, size)) return -EFAULT; - file->f_pos += size; } return size; } diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 9a1758396395..e9810d2ea5af 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2866,18 +2866,18 @@ void __devinit snd_cs46xx_gameport(cs46xx_t *chip) */ static long snd_cs46xx_io_read(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char __user *buf, long count) + struct file *file, char __user *buf, + unsigned long count, unsigned long pos) { long size; snd_cs46xx_region_t *region = (snd_cs46xx_region_t *)entry->private_data; size = count; - if (file->f_pos + (size_t)size > region->size) - size = region->size - file->f_pos; + if (pos + (size_t)size > region->size) + size = region->size - pos; if (size > 0) { - if (copy_to_user_fromio(buf, region->remap_addr + file->f_pos, size)) + if (copy_to_user_fromio(buf, region->remap_addr + pos, size)) return -EFAULT; - file->f_pos += size; } return size; } diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 39f5307e2183..9582c3179d75 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -191,7 +191,8 @@ static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, #define TOTAL_SIZE_CODE (0x200*8) static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char __user *buf, long count) + struct file *file, char __user *buf, + unsigned long count, unsigned long pos) { long size; emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return -ENXIO); @@ -209,21 +210,20 @@ static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_ offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE; } size = count; - if (file->f_pos + size > entry->size) - size = (long)entry->size - file->f_pos; + if (pos + size > entry->size) + size = (long)entry->size - pos; if (size > 0) { unsigned int *tmp; long res; unsigned int idx; if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL) return -ENOMEM; - for (idx = 0; idx < ((file->f_pos & 3) + size + 3) >> 2; idx++) - tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (file->f_pos >> 2), 0); - if (copy_to_user(buf, ((char *)tmp) + (file->f_pos & 3), size)) + for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++) + tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0); + if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size)) res = -EFAULT; else { res = size; - file->f_pos += size; } kfree(tmp); return res; diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 2b918cc7f529..7e312df0c5bf 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1154,18 +1154,18 @@ static long long snd_mixart_BA1_llseek(snd_info_entry_t *entry, mixart_BA0 proc interface for BAR 0 - read callback */ static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char __user *buf, long count) + struct file *file, char __user *buf, + unsigned long count, unsigned long pos) { mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO); count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ if(count <= 0) return 0; - if(file->f_pos + count > MIXART_BA0_SIZE) - count = (long)(MIXART_BA0_SIZE - file->f_pos); - if(copy_to_user_fromio(buf, MIXART_MEM( mgr, file->f_pos ), count)) + if(pos + count > MIXART_BA0_SIZE) + count = (long)(MIXART_BA0_SIZE - pos); + if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count)) return -EFAULT; - file->f_pos += count; return count; } @@ -1173,18 +1173,18 @@ static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data mixart_BA1 proc interface for BAR 1 - read callback */ static long snd_mixart_BA1_read(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char __user *buf, long count) + struct file *file, char __user *buf, + unsigned long count, unsigned long pos) { mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO); count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ if(count <= 0) return 0; - if(file->f_pos + count > MIXART_BA1_SIZE) - count = (long)(MIXART_BA1_SIZE - file->f_pos); - if(copy_to_user_fromio(buf, MIXART_REG( mgr, file->f_pos ), count)) + if(pos + count > MIXART_BA1_SIZE) + count = (long)(MIXART_BA1_SIZE - pos); + if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count)) return -EFAULT; - file->f_pos += count; return count; } |
