diff options
| author | Anton Altaparmakov <aia21@cantab.net> | 2004-06-21 11:46:13 +0100 |
|---|---|---|
| committer | Anton Altaparmakov <aia21@cantab.net> | 2004-06-21 11:46:13 +0100 |
| commit | bde83043a7e018b08d808ca933962be4678ec5cb (patch) | |
| tree | 7ad914ed75f5d02383143b1354a793611668cd14 | |
| parent | cfeac312b3960ac26ed085860ee10b531ad65aa5 (diff) | |
| parent | 9a85e04ec3e527234d8a2210e6ba04d7af9a4298 (diff) | |
Merge cantab.net:/home/src/bklinux-2.6
into cantab.net:/home/src/ntfs-2.6
345 files changed, 11291 insertions, 5390 deletions
@@ -2267,8 +2267,8 @@ S: USA N: Eberhard Moenkeberg E: emoenke@gwdg.de D: CDROM driver "sbpcd" (Matsushita/Panasonic/Soundblaster) -S: Reinholdstrasse 14 -S: D-37083 Goettingen +S: Ruhstrathoehe 2 b. +S: D-37085 Goettingen S: Germany N: Thomas Molina diff --git a/Documentation/as-iosched.txt b/Documentation/block/as-iosched.txt index 0dba00d5a2d8..fd763cc4892d 100644 --- a/Documentation/as-iosched.txt +++ b/Documentation/block/as-iosched.txt @@ -151,7 +151,7 @@ The parameters are: if writes are to be given higher priority than reads, but reads are to be as efficient as possible when there are no writes. Generally though, it should be some multiple of read_expire. - + * write_expire, and * write_batch_expire are equivalent to the above, for writes. diff --git a/Documentation/block/deadline-iosched.txt b/Documentation/block/deadline-iosched.txt new file mode 100644 index 000000000000..2b1318600558 --- /dev/null +++ b/Documentation/block/deadline-iosched.txt @@ -0,0 +1,78 @@ +Deadline IO scheduler tunables +============================== + +This little file attempts to document how the deadline io scheduler works. +In particular, it will clarify the meaning of the exposed tunables that may be +of interest to power users. + +Each io queue has a set of io scheduler tunables associated with it. These +tunables control how the io scheduler works. You can find these entries +in: + +/sys/block/<device>/iosched + +assuming that you have sysfs mounted on /sys. If you don't have sysfs mounted, +you can do so by typing: + +# mount none /sys -t sysfs + + +******************************************************************************** + + +read_expire (in ms) +----------- + +The goal of the deadline io scheduler is to attempt to guarentee a start +service time for a request. As we focus mainly on read latencies, this is +tunable. When a read request first enters the io scheduler, it is assigned +a deadline that is the current time + the read_expire value in units of +miliseconds. + + +write_expire (in ms) +----------- + +Similar to read_expire mentioned above, but for writes. + + +fifo_batch +---------- + +When a read request expires its deadline, we must move some requests from +the sorted io scheduler list to the block device dispatch queue. fifo_batch +controls how many requests we move, based on the cost of each request. A +request is either qualified as a seek or a stream. The io scheduler knows +the last request that was serviced by the drive (or will be serviced right +before this one). See seek_cost and stream_unit. + + +write_starved (number of dispatches) +------------- + +When we have to move requests from the io scheduler queue to the block +device dispatch queue, we always give a preference to reads. However, we +don't want to starve writes indefinitely either. So writes_starved controls +how many times we give preference to reads over writes. When that has been +done writes_starved number of times, we dispatch some writes based on the +same criteria as reads. + + +front_merges (bool) +------------ + +Sometimes it happens that a request enters the io scheduler that is contigious +with a request that is already on the queue. Either it fits in the back of that +request, or it fits at the front. That is called either a back merge candidate +or a front merge candidate. Due to the way files are typically laid out, +back merges are much more common than front merges. For some work loads, you +may even know that it is a waste of time to spend any time attempting to +front merge requests. Setting front_merges to 0 disables this functionality. +Front merges may still occur due to the cached last_merge hint, but since +that comes at basically 0 cost we leave that on. We simply disable the +rbtree front sector lookup when the io scheduler merge function is called. + + +Nov 11 2002, Jens Axboe <axboe@suse.de> + + diff --git a/Documentation/filesystems/hpfs.txt b/Documentation/filesystems/hpfs.txt index be65317bca51..33dc360c8e89 100644 --- a/Documentation/filesystems/hpfs.txt +++ b/Documentation/filesystems/hpfs.txt @@ -1,5 +1,5 @@ -Read/Write HPFS 2.05 -1998-2001, Mikulas Patocka +Read/Write HPFS 2.09 +1998-2004, Mikulas Patocka email: mikulas@artax.karlin.mff.cuni.cz homepage: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi @@ -283,6 +283,14 @@ History 2.05 Fixed crash when got mount parameters without = Fixed crash when allocation of anode failed due to full disk Fixed some crashes when block io or inode allocation failed +2.06 Fixed some crash on corrupted disk structures + Better allocation strategy + Reschedule points added so that it doesn't lock CPU long time + It should work in read-only mode on Warp Server +2.07 More fixes for Warp Server. Now it really works +2.08 Creating new files is not so slow on large disks + An attempt to sync deleted file does not generate filesystem error +2.09 Fixed error on extremly fragmented files vim: set textwidth=80: @@ -290,8 +290,6 @@ STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump AWK = awk -RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \ - else echo rpm; fi) GENKSYMS = scripts/genksyms/genksyms DEPMOD = /sbin/depmod KALLSYMS = scripts/kallsyms @@ -409,13 +407,6 @@ scripts: scripts_basic include/config/MARKER scripts_basic: include/linux/autoconf.h - -# That's our default target when none is given on the command line -# Note that 'modules' will be added as a prerequisite as well, -# in the CONFIG_MODULES part below - -all: vmlinux - # Objects we will link into vmlinux / subdirs we need to visit init-y := init/ drivers-y := drivers/ sound/ @@ -449,6 +440,19 @@ endif include $(srctree)/arch/$(ARCH)/Makefile +# Default kernel image to build when no specific target is given. +# KBUILD_IMAGE may be overruled on the commandline or +# set in the environment +# Also any assingments in arch/$(ARCH)/Makefiel take precedence over +# this default value +export KBUILD_IMAGE ?= vmlinux + +# The all: target is the default when no target is given on the +# command line. +# This allow a user to issue only 'make' to build a kernel including modules +# Defaults vmlinux but it is usually overriden in the arch makefile +all: vmlinux + ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE CFLAGS += -Os else @@ -795,7 +799,7 @@ endef # Directories & files removed with 'make clean' CLEAN_DIRS += $(MODVERDIR) -CLEAN_FILES += vmlinux System.map kernel.spec \ +CLEAN_FILES += vmlinux System.map \ .tmp_kallsyms* .tmp_version .tmp_vmlinux* # Directories & files removed with 'make mrproper' @@ -848,37 +852,19 @@ distclean: mrproper -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ -type f -print | xargs rm -f -# RPM target -# --------------------------------------------------------------------------- - -.PHONY: rpm - -# Remove hyphens since they have special meaning in RPM filenames -KERNELPATH=kernel-$(subst -,,$(KERNELRELEASE)) -# If you do a make spec before packing the tarball you can rpm -ta it - -spec: - $(CONFIG_SHELL) $(srctree)/scripts/mkspec > $(objtree)/kernel.spec - -# a) Build a tar ball -# b) generate an rpm from it -# c) and pack the result -# - Use /. to avoid tar packing just the symlink +# Packaging of the kernel to various formats +# --------------------------------------------------------------------------- +# rpm target kept for backward compatibility +package-dir := $(srctree)/scripts/package -rpm: clean spec - set -e; \ - cd .. ; \ - ln -sf $(srctree) $(KERNELPATH) ; \ - tar -cvz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. ; \ - rm $(KERNELPATH) +.PHONY: %-pkg rpm - set -e; \ - $(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version;\ - mv -f $(objtree)/.tmp_version $(objtree)/.version; +%pkg: FORCE + $(Q)$(MAKE) -f $(package-dir)/Makefile $@ +rpm: FORCE + $(Q)$(MAKE) -f $(package-dir)/Makefile $@ - $(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz - rm ../$(KERNELPATH).tar.gz # Brief documentation of the typical targets used # --------------------------------------------------------------------------- @@ -905,6 +891,8 @@ help: @echo ' tags/TAGS - Generate tags file for editors' @echo ' cscope - Generate cscope index' @echo ' checkstack - Generate a list of stack hogs' + @echo 'Kernel packaging:' + @$(MAKE) -f $(package-dir)/Makefile help @echo '' @echo 'Documentation targets:' @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ff2a826db9e5..a9a5535fffa9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -257,7 +257,7 @@ config DISCONTIGMEM # Now handle the bus types config PCI bool "PCI support" if ARCH_INTEGRATOR_AP - default y if ARCH_FTVPCI || ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX + default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside @@ -270,11 +270,6 @@ config PCI doesn't. # Select the host bridge type -config PCI_HOST_PLX90X0 - bool - depends on PCI && ARCH_FTVPCI - default y - config PCI_HOST_VIA82C505 bool depends on PCI && ARCH_SHARK @@ -550,7 +545,7 @@ config CMDLINE config LEDS bool "Timer and CPU usage LEDs" - depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB + depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. @@ -564,7 +559,7 @@ config LEDS config LEDS_TIMER bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB) - depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB + depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB default y if ARCH_EBSA110 help If you say Y here, one of the system LEDs (the green one on the @@ -620,7 +615,7 @@ source "drivers/acorn/block/Kconfig" source "net/Kconfig" -if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_FTVPCI || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE +if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE source "drivers/ide/Kconfig" endif diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 598a521ce18e..954004064480 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -74,9 +74,6 @@ textaddr-y := 0xC0008000 textaddr-$(CONFIG_ARCH_CO285) := 0x60008000 machine-$(CONFIG_ARCH_CO285) := footbridge incdir-$(CONFIG_ARCH_CO285) := ebsa285 - machine-$(CONFIG_ARCH_FTVPCI) := ftvpci - incdir-$(CONFIG_ARCH_FTVPCI) := nexuspci - machine-$(CONFIG_ARCH_TBOX) := tbox machine-$(CONFIG_ARCH_SHARK) := shark machine-$(CONFIG_ARCH_SA1100) := sa1100 ifeq ($(CONFIG_ARCH_SA1100),y) diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index f326bac694fd..72a12c24689f 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -6,6 +6,5 @@ obj-y += platform.o obj-$(CONFIG_ARM_AMBA) += amba.o obj-$(CONFIG_ICST525) += icst525.o obj-$(CONFIG_SA1111) += sa1111.o -obj-$(CONFIG_PCI_HOST_PLX90X0) += plx90x0.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 0d0d8e8821c6..c3a87663b040 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -234,7 +234,7 @@ map_single(struct device *dev, void *ptr, size_t size, } } - dma_addr = virt_to_bus(ptr); + dma_addr = virt_to_dma(dev, ptr); if (device_info && dma_needs_bounce(dev, dma_addr, size)) { struct safe_buffer *buf; @@ -248,7 +248,7 @@ map_single(struct device *dev, void *ptr, size_t size, dev_dbg(dev, "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", - __func__, buf->ptr, (void *) virt_to_bus(buf->ptr), + __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr), buf->safe, (void *) buf->safe_dma_addr); if ((dir == DMA_TO_DEVICE) || @@ -290,7 +290,7 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, dev_dbg(dev, "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", - __func__, buf->ptr, (void *) virt_to_bus(buf->ptr), + __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr), buf->safe, (void *) buf->safe_dma_addr); @@ -342,7 +342,7 @@ sync_single(struct device *dev, dma_addr_t dma_addr, size_t size, dev_dbg(dev, "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", - __func__, buf->ptr, (void *) virt_to_bus(buf->ptr), + __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr), buf->safe, (void *) buf->safe_dma_addr); DO_STATS ( device_info->bounce_count++ ); @@ -367,7 +367,7 @@ sync_single(struct device *dev, dma_addr_t dma_addr, size_t size, } consistent_sync(buf->safe, size, dir); } else { - consistent_sync(bus_to_virt(dma_addr), size, dir); + consistent_sync(dma_to_virt(dev, dma_addr), size, dir); } } diff --git a/arch/arm/common/plx90x0.c b/arch/arm/common/plx90x0.c deleted file mode 100644 index 60d7d3566af4..000000000000 --- a/arch/arm/common/plx90x0.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Driver for PLX Technology PCI9000-series host bridge. - * - * Copyright (C) 1997, 1998, 1999, 2000 FutureTV Labs Ltd - */ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/init.h> - -#include <asm/hardware.h> -#include <asm/io.h> -#include <asm/ptrace.h> -#include <asm/irq.h> -#include <asm/mach/pci.h> - -/* - * Since the following functions are all very similar, the common parts - * are pulled out into these macros. - */ - -#define PLX_CLEAR_CONFIG \ - __raw_writel(0, PLX_BASE + 0xac); \ - local_irq_restore(flags); } - -#define PLX_SET_CONFIG \ - { unsigned long flags; \ - local_irq_save(flags); \ - __raw_writel((1<<31 | (bus->number << 16) \ - | (devfn << 8) | (where & ~3) \ - | ((bus->number == 0)?0:1)), PLX_BASE + 0xac); \ - -#define PLX_CONFIG_WRITE(size) \ - PLX_SET_CONFIG \ - __raw_write##size(value, PCIO_BASE + (where & 3)); \ - if (__raw_readw(PLX_BASE + 0x6) & 0x2000) \ - __raw_writew(0x2000, PLX_BASE + 0x6); \ - PLX_CLEAR_CONFIG \ - return PCIBIOS_SUCCESSFUL; - -#define PLX_CONFIG_READ(size) \ - PLX_SET_CONFIG \ - *value = __raw_read##size(PCIO_BASE + (where & 3)); \ - if (__raw_readw(PLX_BASE + 0x6) & 0x2000) { \ - __raw_writew(0x2000, PLX_BASE + 0x6); \ - *value = 0xffffffffUL; \ - } \ - PLX_CLEAR_CONFIG \ - return PCIBIOS_SUCCESSFUL; - -/* Configuration space access routines */ - -static int -plx90x0_read_config (struct pci_bus *bus, unsigned int devfn, int where, - int where, int size, u32 *value) -{ - switch (size) { - case 1: - PLX_CONFIG_READ(b) - break; - case 2: - PLX_CONFIG_READ(w) - break; - case 4: - PLX_CONFIG_READ(l) - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int -plx90x0_write_config (struct pci_bus *bus, unsigned int devfn, int where, - int where, int size, u32 value) -{ - switch (size) { - case 1: - PLX_CONFIG_WRITE(b) - break; - case 2: - PLX_CONFIG_WRITE(w) - break; - case 4: - PLX_CONFIG_WRITE(l) - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops plx90x0_ops = -{ - .read = plx90x0_read_config, - .write = plx90x0_write_config, -}; - -static void -plx_syserr_handler(int irq, void *handle, struct pt_regs *regs) -{ - printk("PLX90x0: machine check %04x (pc=%08lx)\n", - readw(PLX_BASE + 6), regs->ARM_pc); - __raw_writew(0xf000, PLX_BASE + 6); -} - -/* - * Initialise the PCI system. - */ - -void __init -plx90x0_init(struct arm_sysdata *sysdata) -{ - static const unsigned long int base = PLX_BASE; - char *what; - unsigned long bar = (unsigned long)virt_to_bus((void *)PAGE_OFFSET); - - /* Have a sniff around and see which PLX device is present. */ - unsigned long id = __raw_readl(base + 0xf0); - -#if 0 - /* This check was a good idea, but can fail. The PLX9060 puts no - default value in these registers unless NB# is asserted (which it - isn't on these cards). */ - if ((id & 0xffff) != PCI_VENDOR_ID_PLX) - return; /* Nothing found */ -#endif - - /* Found one - now work out what it is. */ - switch (id >> 16) { - case 0: /* PCI_DEVICE_ID_PLX_9060 */ - what = "PCI9060"; - break; - case PCI_DEVICE_ID_PLX_9060ES: - what = "PCI9060ES"; - break; - case PCI_DEVICE_ID_PLX_9060SD: - what = "PCI9060SD"; /* uhuhh.. */ - break; - case PCI_DEVICE_ID_PLX_9080: - what = "PCI9080"; - break; - default: - printk("PCI: Unknown PLX device %04lx found -- ignored.\n", - id >> 16); - return; - } - - printk("PCI: PLX Technology %s host bridge found.\n", what); - - /* Now set it up for both master and slave accesses. */ - __raw_writel(0xffff0147, base + 0x4); - __raw_writeb(32, base + 0xd); - __raw_writel(0x8 | bar, base + 0x18); - __raw_writel(0xf8000008, base + 0x80); - __raw_writel(0x40000001, base + 0x84); - __raw_writel(0, base + 0x88); - __raw_writel(0, base + 0x8c); - __raw_writel(0x11, base + 0x94); - __raw_writel(0xC3 + (4 << 28) - + (8 << 11) + (1 << 10) - + (1 << 24), base + 0x98); - __raw_writel(0xC0000000, base + 0x9c); - __raw_writel(PLX_MEM_START, base + 0xa0); - __raw_writel(PLX_IO_START, base + 0xa4); - __raw_writel(0x3, base + 0xa8); - __raw_writel(0, base + 0xac); - __raw_writel(0x10001, base + 0xe8); - __raw_writel(0x8000767e, base + 0xec); - - request_irq(IRQ_SYSERR, plx_syserr_handler, 0, - "system error", NULL); - - pci_scan_bus(0, &plx90x0_ops, sysdata); -} diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3f28167930be..5b21d2023501 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -426,7 +426,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) /* * Flush a region from virtual address 'r0' to virtual address 'r1' - * _inclusive_. There is no alignment requirement on either address; + * _exclusive_. There is no alignment requirement on either address; * user space does not need to know the hardware cache layout. * * r2 contains flags. It should ALWAYS be passed as ZERO until it diff --git a/arch/arm/mach-ftvpci/Makefile b/arch/arm/mach-ftvpci/Makefile deleted file mode 100644 index 8b1ad14a256c..000000000000 --- a/arch/arm/mach-ftvpci/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Object file lists. - -obj-y := core.o -obj-m := -obj-n := -obj- := - -obj-$(CONFIG_PCI) += pci.o -obj-$(CONFIG_LEDS) += leds.o diff --git a/arch/arm/mach-ftvpci/core.c b/arch/arm/mach-ftvpci/core.c deleted file mode 100644 index ea6d5c34e87f..000000000000 --- a/arch/arm/mach-ftvpci/core.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * linux/arch/arm/mach-ftvpci/core.c - * - * Architecture specific fixups. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/init.h> - -#include <asm/setup.h> -#include <asm/mach-types.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> - -extern unsigned long soft_irq_mask; - -static const unsigned char irq_cmd[] = -{ - INTCONT_IRQ_DUART, - INTCONT_IRQ_PLX, - INTCONT_IRQ_D, - INTCONT_IRQ_C, - INTCONT_IRQ_B, - INTCONT_IRQ_A, - INTCONT_IRQ_SYSERR -}; - -static void ftvpci_mask_irq(unsigned int irq) -{ - __raw_writel(irq_cmd[irq], INTCONT_BASE); - soft_irq_mask &= ~(1<<irq); -} - -static void ftvpci_unmask_irq(unsigned int irq) -{ - soft_irq_mask |= (1<<irq); - __raw_writel(irq_cmd[irq] | 1, INTCONT_BASE); -} - -static void __init ftvpci_init_irq(void) -{ - unsigned int i; - - /* Mask all FIQs */ - __raw_writel(INTCONT_FIQ_PLX, INTCONT_BASE); - __raw_writel(INTCONT_FIQ_D, INTCONT_BASE); - __raw_writel(INTCONT_FIQ_C, INTCONT_BASE); - __raw_writel(INTCONT_FIQ_B, INTCONT_BASE); - __raw_writel(INTCONT_FIQ_A, INTCONT_BASE); - __raw_writel(INTCONT_FIQ_SYSERR, INTCONT_BASE); - - /* Disable all interrupts initially. */ - for (i = 0; i < NR_IRQS; i++) { - if (i >= FIRST_IRQ && i <= LAST_IRQ) { - irq_desc[i].valid = 1; - irq_desc[i].probe_ok = 1; - irq_desc[i].mask_ack = ftvpci_mask_irq; - irq_desc[i].mask = ftvpci_mask_irq; - irq_desc[i].unmask = ftvpci_unmask_irq; - ftvpci_mask_irq(i); - } else { - irq_desc[i].valid = 0; - irq_desc[i].probe_ok = 0; - } - } -} - -static struct map_desc ftvpci_io_desc[] __initdata = { - { INTCONT_BASE, INTCONT_START, 0x00001000, MT_DEVICE }, - { PLX_BASE, PLX_START, 0x00001000, MT_DEVICE }, - { PCIO_BASE, PLX_IO_START, 0x00100000, MT_DEVICE }, - { DUART_BASE, DUART_START, 0x00001000, MT_DEVICE }, - { STATUS_BASE, STATUS_START, 0x00001000, MT_DEVICE } -}; - -static void __init ftvpci_map_io(void) -{ - iotable_init(ftvpci_io_desc, ARRAY_SIZE(ftvpci_io_desc)); -} - -MACHINE_START(NEXUSPCI, "FTV/PCI") - MAINTAINER("Philip Blundell") - BOOT_MEM(0x40000000, 0x10000000, 0xe0000000) - MAPIO(ftvpci_map_io) - INITIRQ(ftvpci_init_irq) -MACHINE_END diff --git a/arch/arm/mach-ftvpci/leds.c b/arch/arm/mach-ftvpci/leds.c deleted file mode 100644 index 64345acb9866..000000000000 --- a/arch/arm/mach-ftvpci/leds.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * linux/arch/arm/kernel/leds-ftvpci.c - * - * Copyright (C) 1999 FutureTV Labs Ltd - */ - -#include <linux/module.h> -#include <linux/init.h> - -#include <asm/hardware.h> -#include <asm/leds.h> -#include <asm/system.h> -#include <asm/io.h> - -static void ftvpci_leds_event(led_event_t ledevt) -{ - static int led_state = 0; - - switch(ledevt) { - case led_timer: - led_state ^= 1; - raw_writeb(0x1a | led_state, INTCONT_BASE); - break; - - default: - break; - } -} - -static int __init ftvpci_leds_init(void) -{ - leds_event = ftvpci_leds_event; - return 0; -} - -arch_initcall(ftvpci_leds_init); diff --git a/arch/arm/mach-ftvpci/pci.c b/arch/arm/mach-ftvpci/pci.c deleted file mode 100644 index a9941a1e46e4..000000000000 --- a/arch/arm/mach-ftvpci/pci.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * linux/arch/arm/kernel/ftv-pci.c - * - * PCI bios-type initialisation for PCI machines - * - * Bits taken from various places. - */ -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/init.h> - -#include <asm/irq.h> -#include <asm/mach/pci.h> -#include <asm/mach-types.h> - -/* - * Owing to a PCB cockup, issue A backplanes are wired thus: - * - * Slot 1 2 3 4 5 Bridge S1 S2 S3 S4 - * IRQ D C B A A C B A D - * A D C B B D C B A - * B A D C C A D C B - * C B A D D B A D C - * - * ID A31 A30 A29 A28 A27 A26 DEV4 DEV5 DEV6 DEV7 - * - * Actually, this isn't too bad, because with the processor card - * in slot 5 on the primary bus, the IRQs rotate on both sides - * as you'd expect. - */ - -static int irqmap_ftv[] __initdata = { IRQ_PCI_D, IRQ_PCI_C, IRQ_PCI_B, IRQ_PCI_A }; - -static int __init ftv_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - if (slot > 0x10) - slot--; - return irqmap_ftv[(slot - pin) & 3]; -} - -static u8 __init ftv_swizzle(struct pci_dev *dev, u8 *pin) -{ - return PCI_SLOT(dev->devfn); -} - -/* ftv host-specific stuff */ -static struct hw_pci ftv_pci __initdata = { - .init = plx90x0_init, - .swizzle = ftv_swizzle, - .map_irq = ftv_map_irq, -}; - -static int __init ftv_pci_init(void) -{ - if (machine_is_ftvpci()) - pci_common_init(&ftv_pci); - return 0; -} - -subsys_initcall(ftv_pci_init); diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 24f3da29df3e..20b776ff92d2 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -59,6 +59,24 @@ void pxa_gpio_mode(int gpio_mode) EXPORT_SYMBOL(pxa_gpio_mode); /* + * Routine to safely enable or disable a clock in the CKEN + */ +void pxa_set_cken(int clock, int enable) +{ + unsigned long flags; + local_irq_save(flags); + + if (enable) + CKEN |= clock; + else + CKEN &= ~clock; + + local_irq_restore(flags); +} + +EXPORT_SYMBOL(pxa_set_cken); + +/* * Intel PXA2xx internal register mapping. * * Note 1: not all PXA2xx variants implement all those addresses. diff --git a/arch/arm/mach-tbox/Makefile b/arch/arm/mach-tbox/Makefile deleted file mode 100644 index 4bd8ebd70e7b..000000000000 --- a/arch/arm/mach-tbox/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Object file lists. - -obj-y := core.o -obj-m := -obj-n := -obj- := - diff --git a/arch/arm/mach-tbox/core.c b/arch/arm/mach-tbox/core.c deleted file mode 100644 index db9ac783cfce..000000000000 --- a/arch/arm/mach-tbox/core.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * linux/arch/arm/mm/mm-tbox.c - * - * Copyright (C) 1998, 1999, 2000 Phil Blundell - * Copyright (C) 1998-1999 Russell King - * - * Extra MM routines for the Tbox architecture - */ -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/init.h> - -#include <asm/elf.h> -#include <asm/setup.h> -#include <asm/mach-types.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> - -extern unsigned long soft_irq_mask; - -static void tbox_mask_irq(unsigned int irq) -{ - __raw_writel(0, INTCONT + (irq << 2)); - soft_irq_mask &= ~(1<<irq); -} - -static void tbox_unmask_irq(unsigned int irq) -{ - soft_irq_mask |= (1<<irq); - __raw_writel(1, INTCONT + (irq << 2)); -} - -static void tbox_init_irq(void) -{ - unsigned int i; - - /* Disable all interrupts initially. */ - for (i = 0; i < NR_IRQS; i++) { - if (i <= 10 || (i >= 12 && i <= 13)) { - irq_desc[i].valid = 1; - irq_desc[i].probe_ok = 0; - irq_desc[i].mask_ack = tbox_mask_irq; - irq_desc[i].mask = tbox_mask_irq; - irq_desc[i].unmask = tbox_unmask_irq; - tbox_mask_irq(i); - } else { - irq_desc[i].valid = 0; - irq_desc[i].probe_ok = 0; - } - } -} - -static struct map_desc tbox_io_desc[] __initdata = { - /* See hardware.h for details */ - { IO_BASE, IO_START, 0x00100000, MT_DEVICE } -}; - -static void __init tbox_map_io(void) -{ - iotable_init(tbox_io_desc, ARRAY_SIZE(tbox_io_desc)); -} - -MACHINE_START(TBOX, "unknown-TBOX") - MAINTAINER("Philip Blundell") - BOOT_MEM(0x80000000, 0x00400000, 0xe0000000) - MAPIO(tbox_map_io) - INITIRQ(tbox_init_irq) -MACHINE_END - diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 7d3fb20ea212..f9b8fe2c7594 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -194,7 +194,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp, /* * Set the "dma handle" */ - *handle = page_to_bus(page); + *handle = page_to_dma(dev, page); do { BUG_ON(!pte_none(*pte)); diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 299b5f2bba53..d83df8b413c5 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -121,22 +121,23 @@ boot := arch/i386/boot all: bzImage -BOOTIMAGE=arch/i386/boot/bzImage -zImage zlilo zdisk: BOOTIMAGE=arch/i386/boot/zImage +# KBUILD_IMAGE specify target image being built + KBUILD_IMAGE := $(boot)/bzImage +zImage zlilo zdisk: KBUILD_IMAGE := arch/i386/boot/zImage zImage bzImage: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE) + $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE) compressed: zImage zlilo bzlilo: vmlinux - $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zlilo + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zlilo zdisk bzdisk: vmlinux - $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk install fdimage fdimage144 fdimage288: vmlinux - $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@ prepare: include/asm-$(ARCH)/asm_offsets.h CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index aafc78898f93..362ab86e6f0b 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c @@ -10,6 +10,7 @@ #include <asm/io.h> #include <linux/pm.h> #include <asm/system.h> +#include <linux/dmi.h> #include <linux/bootmem.h> unsigned long dmi_broken; @@ -139,21 +140,6 @@ static int __init dmi_iterate(void (*decode)(struct dmi_header *)) return -1; } - -enum -{ - DMI_BIOS_VENDOR, - DMI_BIOS_VERSION, - DMI_BIOS_DATE, - DMI_SYS_VENDOR, - DMI_PRODUCT_NAME, - DMI_PRODUCT_VERSION, - DMI_BOARD_VENDOR, - DMI_BOARD_NAME, - DMI_BOARD_VERSION, - DMI_STRING_MAX -}; - static char *dmi_ident[DMI_STRING_MAX]; /* @@ -176,26 +162,11 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) } /* - * DMI callbacks for problem boards + * Ugly compatibility crap. */ - -struct dmi_strmatch -{ - u8 slot; - char *substr; -}; - -#define NONE 255 - -struct dmi_blacklist -{ - int (*callback)(struct dmi_blacklist *); - char *ident; - struct dmi_strmatch matches[4]; -}; - -#define NO_MATCH { NONE, NULL} -#define MATCH(a,b) { a, b } +#define dmi_blacklist dmi_system_id +#define NO_MATCH { DMI_NONE, NULL} +#define MATCH DMI_MATCH /* * Reboot options and system auto-detection code provided by @@ -343,23 +314,6 @@ static __init int disable_smbus(struct dmi_blacklist *d) } /* - * Work around broken HP Pavilion Notebooks which assign USB to - * IRQ 9 even though it is actually wired to IRQ 11 - */ -static __init int fix_broken_hp_bios_irq9(struct dmi_blacklist *d) -{ -#ifdef CONFIG_PCI - extern int broken_hp_bios_irq9; - if (broken_hp_bios_irq9 == 0) - { - broken_hp_bios_irq9 = 1; - printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); - } -#endif - return 0; -} - -/* * Check for clue free BIOS implementations who use * the following QA technique * @@ -845,14 +799,6 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={ NO_MATCH, NO_MATCH } }, - { fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", { - MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - MATCH(DMI_BIOS_VERSION, "GE.M1.03"), - MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), - MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736") - } }, - - /* * Generic per vendor APM settings */ @@ -1054,9 +1000,6 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={ static __init void dmi_check_blacklist(void) { - struct dmi_blacklist *d; - int i; - #ifdef CONFIG_ACPI_BOOT #define ACPI_BLACKLIST_CUTOFF_YEAR 2001 @@ -1078,25 +1021,7 @@ static __init void dmi_check_blacklist(void) } } #endif - - d=&dmi_blacklist[0]; - while(d->callback) - { - for(i=0;i<4;i++) - { - int s = d->matches[i].slot; - if(s==NONE) - continue; - if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr)) - continue; - /* No match */ - goto fail; - } - if(d->callback(d)) - return; -fail: - d++; - } + dmi_check_system(dmi_blacklist); } @@ -1163,3 +1088,52 @@ void __init dmi_scan_machine(void) } EXPORT_SYMBOL(is_unsafe_smbus); + + +/** + * dmi_check_system - check system DMI data + * @list: array of dmi_system_id structures to match against + * + * Walk the blacklist table running matching functions until someone + * returns non zero or we hit the end. Callback function is called for + * each successfull match. Returns the number of matches. + */ +int dmi_check_system(struct dmi_system_id *list) +{ + int i, count = 0; + struct dmi_system_id *d = list; + + while (d->ident) { + for (i = 0; i < ARRAY_SIZE(d->matches); i++) { + int s = d->matches[i].slot; + if (s == DMI_NONE) + continue; + if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr)) + continue; + /* No match */ + goto fail; + } + if (d->callback && d->callback(d)) + break; + count++; +fail: d++; + } + + return count; +} + +EXPORT_SYMBOL(dmi_check_system); + +/** + * dmi_get_system_info - return DMI data value + * @field: data index (see enum dmi_filed) + * + * Returns one DMI data value, can be used to perform + * complex DMI data checks. + */ +char * dmi_get_system_info(int field) +{ + return dmi_ident[field]; +} + +EXPORT_SYMBOL(dmi_get_system_info); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 95e9fa75efb6..fc466fb4488a 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -57,8 +57,6 @@ unsigned long init_pg_tables_end __initdata = ~0UL; int disable_pse __initdata = 0; -static inline char * __init machine_specific_memory_setup(void); - /* * Machine setup.. */ @@ -660,14 +658,6 @@ static inline void copy_edd(void) */ #define LOWMEMSIZE() (0x9f000) -static void __init setup_memory_region(void) -{ - char *who = machine_specific_memory_setup(); - printk(KERN_INFO "BIOS-provided physical RAM map:\n"); - print_memory_map(who); -} /* setup_memory_region */ - - static void __init parse_cmdline_early (char ** cmdline_p) { char c = ' ', *to = command_line, *from = saved_command_line; @@ -1270,6 +1260,8 @@ static int __init noreplacement_setup(char *s) __setup("noreplacement", noreplacement_setup); +static char * __init machine_specific_memory_setup(void); + /* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures @@ -1320,8 +1312,10 @@ void __init setup_arch(char **cmdline_p) ARCH_SETUP if (efi_enabled) efi_init(); - else - setup_memory_region(); + else { + printk(KERN_INFO "BIOS-provided physical RAM map:\n"); + print_memory_map(machine_specific_memory_setup()); + } copy_edd(); diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index e29b67b9cc27..08314fa39f24 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/dmi.h> #include <asm/io.h> #include <asm/smp.h> #include <asm/io_apic.h> @@ -22,7 +23,7 @@ #define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) #define PIRQ_VERSION 0x0100 -int broken_hp_bios_irq9; +static int broken_hp_bios_irq9; static struct irq_routing_table *pirq_table; @@ -893,6 +894,33 @@ static void __init pcibios_fixup_irqs(void) } } +/* + * Work around broken HP Pavilion Notebooks which assign USB to + * IRQ 9 even though it is actually wired to IRQ 11 + */ +static int __init fix_broken_hp_bios_irq9(struct dmi_system_id *d) +{ + if (!broken_hp_bios_irq9) { + broken_hp_bios_irq9 = 1; + printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); + } + return 0; +} + +static struct dmi_system_id __initdata pciirq_dmi_table[] = { + { + .callback = fix_broken_hp_bios_irq9, + .ident = "HP Pavilion N5400 Series Laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), + DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"), + }, + }, + { } +}; + static int __init pcibios_irq_init(void) { DBG("PCI: IRQ init\n"); @@ -900,6 +928,8 @@ static int __init pcibios_irq_init(void) if (pcibios_enable_irq || raw_pci_ops == NULL) return 0; + dmi_check_system(pciirq_dmi_table); + pirq_table = pirq_find_routing_table(); #ifdef CONFIG_PCI_BIOS diff --git a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c index 3a359a7c45f1..6a9248784439 100644 --- a/arch/i386/pci/visws.c +++ b/arch/i386/pci/visws.c @@ -15,8 +15,6 @@ #include "pci.h" -int broken_hp_bios_irq9; - extern struct pci_raw_ops pci_direct_conf1; static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; } diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 64e4ec65fc7e..1d553f525953 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -149,20 +149,6 @@ config IA64_L1_CACHE_SHIFT default "6" if ITANIUM # align cache-sensitive data to 64 bytes -config MCKINLEY_ASTEP_SPECIFIC - bool "McKinley A-step specific code" - depends on MCKINLEY - help - Select this option to build a kernel for an IA-64 McKinley prototype - system with any A-stepping CPU. - -config MCKINLEY_A0_SPECIFIC - bool "McKinley A0/A1-step specific code" - depends on MCKINLEY_ASTEP_SPECIFIC - help - Select this option to build a kernel for an IA-64 McKinley prototype - system with an A0 or A1 stepping CPU. - config NUMA bool "NUMA support" depends on !IA64_HP_SIM diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index 8e790347d14a..8acfb89bc79e 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -14,18 +14,22 @@ CONFIG_STANDALONE=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=20 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y 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 is not set # @@ -60,7 +64,6 @@ CONFIG_MCKINLEY=y CONFIG_IA64_PAGE_SIZE_16KB=y # CONFIG_IA64_PAGE_SIZE_64KB is not set CONFIG_IA64_L1_CACHE_SHIFT=7 -# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set CONFIG_NUMA=y CONFIG_VIRTUAL_MEM_MAP=y CONFIG_DISCONTIGMEM=y @@ -70,12 +73,17 @@ CONFIG_IA64_SGI_SN_SIM=y CONFIG_FORCE_MAX_ZONEORDER=18 CONFIG_SMP=y CONFIG_NR_CPUS=512 +# CONFIG_HOTPLUG_CPU is not set # CONFIG_PREEMPT is not set CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y + +# +# Firmware Drivers +# CONFIG_EFI_VARS=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set @@ -105,6 +113,7 @@ CONFIG_ACPI_SYSTEM=y # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_USE_VECTOR is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y @@ -174,7 +183,6 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=m CONFIG_BLK_DEV_IDETAPE=m CONFIG_BLK_DEV_IDEFLOPPY=y @@ -218,6 +226,7 @@ CONFIG_BLK_DEV_SGIIOC4=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y @@ -243,7 +252,6 @@ CONFIG_CHR_DEV_SG=m # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_REPORT_LUNS=y CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set @@ -281,7 +289,9 @@ CONFIG_SCSI_SATA=y CONFIG_SCSI_SATA_SVW=m CONFIG_SCSI_ATA_PIIX=m CONFIG_SCSI_SATA_PROMISE=m +# CONFIG_SCSI_SATA_SX4 is not set # CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIS is not set CONFIG_SCSI_SATA_VIA=m CONFIG_SCSI_SATA_VITESSE=y # CONFIG_SCSI_BUSLOGIC is not set @@ -298,6 +308,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y @@ -343,6 +354,7 @@ CONFIG_FUSION_CTL=m # # I2O device support # +# CONFIG_I2O is not set # # Networking support @@ -389,8 +401,6 @@ CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_TUNNEL=m -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -452,6 +462,7 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m # CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set +# CONFIG_IP_NF_RAW is not set # # IPv6: Netfilter Configuration @@ -471,7 +482,9 @@ CONFIG_XFRM_USER=m # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +CONFIG_BRIDGE=m CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -516,12 +529,14 @@ CONFIG_NET_CLS_POLICE=y # Network testing # # CONFIG_NET_PKTGEN is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_EQUALIZER=m @@ -529,6 +544,11 @@ CONFIG_TUN=m # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -582,7 +602,6 @@ CONFIG_NS83820=m CONFIG_HAMACHI=m CONFIG_YELLOWFIN=m CONFIG_R8169=m -CONFIG_SIS190=m CONFIG_SK98LIN=m CONFIG_TIGON3=y @@ -591,6 +610,22 @@ CONFIG_TIGON3=y # CONFIG_IXGB=m # CONFIG_IXGB_NAPI is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set CONFIG_PPP=m @@ -602,45 +637,11 @@ CONFIG_PPP_DEFLATE=m # CONFIG_PPP_BSDCOMP is not set # CONFIG_PPPOE is not set # CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set CONFIG_NET_FC=y # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y # -# 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_NETPOLL=y -# CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y - -# # ISDN subsystem # # CONFIG_ISDN is not set @@ -703,6 +704,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_SERIAL_NONSTANDARD=y # CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set # CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set @@ -713,18 +715,11 @@ CONFIG_SGI_L1_SERIAL_CONSOLE=y # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_HCDP=y -CONFIG_SERIAL_8250_ACPI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -740,7 +735,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -# CONFIG_GEN_RTC is not set CONFIG_EFI_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -852,6 +846,7 @@ CONFIG_VFAT_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y @@ -897,7 +892,6 @@ CONFIG_SMB_FS=m # 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 # @@ -968,6 +962,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # Library routines # CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m @@ -1019,4 +1014,5 @@ CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_ARC4 is not set CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_TEST is not set diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig index 6f718fb8e5ba..426eb10794be 100644 --- a/arch/ia64/defconfig +++ b/arch/ia64/defconfig @@ -26,6 +26,7 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y @@ -66,7 +67,6 @@ CONFIG_MCKINLEY=y CONFIG_IA64_PAGE_SIZE_16KB=y # CONFIG_IA64_PAGE_SIZE_64KB is not set CONFIG_IA64_L1_CACHE_SHIFT=7 -# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set # CONFIG_NUMA is not set CONFIG_VIRTUAL_MEM_MAP=y # CONFIG_IA64_CYCLONE is not set @@ -74,6 +74,7 @@ CONFIG_IOSAPIC=y CONFIG_FORCE_MAX_ZONEORDER=18 CONFIG_SMP=y CONFIG_NR_CPUS=16 +# CONFIG_HOTPLUG_CPU is not set # CONFIG_PREEMPT is not set CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y @@ -178,7 +179,6 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=m @@ -220,6 +220,7 @@ CONFIG_BLK_DEV_SIIMAGE=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y @@ -245,7 +246,6 @@ CONFIG_CHR_DEV_SG=y # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_REPORT_LUNS=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -282,6 +282,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_QLOGIC_ISP is not set @@ -328,6 +329,7 @@ CONFIG_FUSION_MAX_SGE=40 # # I2O device support # +# CONFIG_I2O is not set # # Networking support @@ -573,7 +575,12 @@ CONFIG_LEGACY_PTY_COUNT=256 # # IPMI # -# CONFIG_IPMI_HANDLER is not set +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_PANIC_EVENT=y +CONFIG_IPMI_PANIC_STRING=y +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m # # Watchdog Cards @@ -651,6 +658,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set @@ -662,6 +670,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_SENSORS_EEPROM is not set # 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 @@ -688,6 +697,7 @@ CONFIG_FB=y # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set # CONFIG_FB_IMSTT is not set CONFIG_FB_RIVA=m # CONFIG_FB_MATROX is not set @@ -852,6 +862,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # CONFIG_USB_MTOUCH is not set +# CONFIG_USB_EGALAX is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -901,6 +912,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_TEST is not set # @@ -998,7 +1010,6 @@ CONFIG_RPCSEC_GSS_KRB5=y # 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 # @@ -1083,7 +1094,7 @@ CONFIG_IA64_GRANULE_16MB=y # CONFIG_IA64_GRANULE_64MB is not set CONFIG_DEBUG_KERNEL=y CONFIG_IA64_PRINT_HAZARDS=y -CONFIG_DISABLE_VHPT=y +# CONFIG_DISABLE_VHPT is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_IA64_EARLY_PRINTK_VGA is not set # CONFIG_DEBUG_SLAB is not set diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index babf3d1fcf40..1726c6114d81 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c @@ -197,6 +197,10 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) } up_write(¤t->mm->mmap_sem); + /* Can't do it in ia64_elf32_init(). Needs to be done before calls to + elf32_map() */ + current->thread.ppl = ia32_init_pp_list(); + return 0; } diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index 0c7db9e10f23..8d8936e01620 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -371,7 +371,7 @@ ia32_syscall_table: data8 sys_sched_get_priority_min /* 160 */ data8 sys32_sched_rr_get_interval data8 compat_sys_nanosleep - data8 sys_mremap + data8 sys32_mremap data8 sys_setresuid /* 16-bit version */ data8 sys32_getresuid16 /* 16-bit version */ /* 165 */ data8 sys_ni_syscall /* vm86 */ diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c index c56fd9f3c5c8..4b43f1753c0f 100644 --- a/arch/ia64/ia32/ia32_support.c +++ b/arch/ia64/ia32/ia32_support.c @@ -218,6 +218,18 @@ ia32_init (void) ia32_exec_domain.signal_map = default_exec_domain.signal_map; ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap; register_exec_domain(&ia32_exec_domain); + +#if PAGE_SHIFT > IA32_PAGE_SHIFT + { + extern kmem_cache_t *partial_page_cachep; + + partial_page_cachep = kmem_cache_create("partial_page_cache", + sizeof(struct partial_page), 0, 0, + NULL, NULL); + if (!partial_page_cachep) + panic("Cannot create partial page SLAB cache"); + } +#endif return 0; } diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h index e6f95af15972..ba875e0bbbdc 100644 --- a/arch/ia64/ia32/ia32priv.h +++ b/arch/ia64/ia32/ia32priv.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IA64_IA32_H -#define _ASM_IA64_IA32_H +#ifndef _ASM_IA64_IA32_PRIV_H +#define _ASM_IA64_IA32_PRIV_H #include <linux/config.h> @@ -9,6 +9,7 @@ #include <linux/binfmts.h> #include <linux/compat.h> +#include <linux/rbtree.h> #include <asm/processor.h> @@ -16,12 +17,39 @@ * 32 bit structures for IA32 support. */ -#define IA32_PAGE_SHIFT 12 /* 4KB pages */ #define IA32_PAGE_SIZE (1UL << IA32_PAGE_SHIFT) #define IA32_PAGE_MASK (~(IA32_PAGE_SIZE - 1)) #define IA32_PAGE_ALIGN(addr) (((addr) + IA32_PAGE_SIZE - 1) & IA32_PAGE_MASK) #define IA32_CLOCKS_PER_SEC 100 /* Cast in stone for IA32 Linux */ +/* + * partially mapped pages provide precise accounting of which 4k sub pages + * are mapped and which ones are not, thereby improving IA-32 compatibility. + */ +struct partial_page { + struct partial_page *next; /* linked list, sorted by address */ + struct rb_node pp_rb; + /* 64K is the largest "normal" page supported by ia64 ABI. So 4K*32 + * should suffice.*/ + unsigned int bitmap; + unsigned int base; +}; + +struct partial_page_list { + struct partial_page *pp_head; /* list head, points to the lowest + * addressed partial page */ + struct rb_root ppl_rb; + struct partial_page *pp_hint; /* pp_hint->next is the last + * accessed partial page */ + atomic_t pp_count; /* reference count */ +}; + +#if PAGE_SHIFT > IA32_PAGE_SHIFT +struct partial_page_list* ia32_init_pp_list (void); +#else +# define ia32_init_pp_list() 0 +#endif + /* sigcontext.h */ /* * As documented in the iBCS2 standard.. @@ -528,4 +556,4 @@ extern int save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_st #endif /* !CONFIG_IA32_SUPPORT */ -#endif /* _ASM_IA64_IA32_H */ +#endif /* _ASM_IA64_IA32_PRIV_H */ diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 8994c9d11a55..6b5917ca7c4c 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -8,6 +8,7 @@ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 2000-2003 Hewlett-Packard Co * David Mosberger-Tang <davidm@hpl.hp.com> + * Copyright (C) 2004 Gordon Jin <gordon.jin@intel.com> * * These routines maintain argument size conversion between 32bit and 64bit * environment. @@ -48,6 +49,7 @@ #include <linux/ipc.h> #include <linux/compat.h> #include <linux/vfs.h> +#include <linux/mman.h> #include <asm/intrinsics.h> #include <asm/semaphore.h> @@ -250,6 +252,508 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro return ret; } +/* SLAB cache for partial_page structures */ +kmem_cache_t *partial_page_cachep; + +/* + * init partial_page_list. + * return 0 means kmalloc fail. + */ +struct partial_page_list* +ia32_init_pp_list(void) +{ + struct partial_page_list *p; + + if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL) + return p; + p->pp_head = 0; + p->ppl_rb = RB_ROOT; + p->pp_hint = 0; + atomic_set(&p->pp_count, 1); + return p; +} + +/* + * Search for the partial page with @start in partial page list @ppl. + * If finds the partial page, return the found partial page. + * Else, return 0 and provide @pprev, @rb_link, @rb_parent to + * be used by later __ia32_insert_pp(). + */ +static struct partial_page * +__ia32_find_pp(struct partial_page_list *ppl, unsigned int start, + struct partial_page **pprev, struct rb_node ***rb_link, + struct rb_node **rb_parent) +{ + struct partial_page *pp; + struct rb_node **__rb_link, *__rb_parent, *rb_prev; + + pp = ppl->pp_hint; + if (pp && pp->base == start) + return pp; + + __rb_link = &ppl->ppl_rb.rb_node; + rb_prev = __rb_parent = NULL; + + while (*__rb_link) { + __rb_parent = *__rb_link; + pp = rb_entry(__rb_parent, struct partial_page, pp_rb); + + if (pp->base == start) { + ppl->pp_hint = pp; + return pp; + } else if (pp->base < start) { + rb_prev = __rb_parent; + __rb_link = &__rb_parent->rb_right; + } else { + __rb_link = &__rb_parent->rb_left; + } + } + + *rb_link = __rb_link; + *rb_parent = __rb_parent; + *pprev = NULL; + if (rb_prev) + *pprev = rb_entry(rb_prev, struct partial_page, pp_rb); + return NULL; +} + +/* + * insert @pp into @ppl. + */ +static void +__ia32_insert_pp(struct partial_page_list *ppl, struct partial_page *pp, + struct partial_page *prev, struct rb_node **rb_link, + struct rb_node *rb_parent) +{ + /* link list */ + if (prev) { + pp->next = prev->next; + prev->next = pp; + } else { + ppl->pp_head = pp; + if (rb_parent) + pp->next = rb_entry(rb_parent, + struct partial_page, pp_rb); + else + pp->next = NULL; + } + + /* link rb */ + rb_link_node(&pp->pp_rb, rb_parent, rb_link); + rb_insert_color(&pp->pp_rb, &ppl->ppl_rb); + + ppl->pp_hint = pp; +} + +/* + * delete @pp from partial page list @ppl. + */ +static void +__ia32_delete_pp(struct partial_page_list *ppl, struct partial_page *pp, + struct partial_page *prev) +{ + if (prev) { + prev->next = pp->next; + if (ppl->pp_hint == pp) + ppl->pp_hint = prev; + } else { + ppl->pp_head = pp->next; + if (ppl->pp_hint == pp) + ppl->pp_hint = pp->next; + } + rb_erase(&pp->pp_rb, &ppl->ppl_rb); + kmem_cache_free(partial_page_cachep, pp); +} + +static struct partial_page * +__pp_prev(struct partial_page *pp) +{ + struct rb_node *prev = rb_prev(&pp->pp_rb); + if (prev) + return rb_entry(prev, struct partial_page, pp_rb); + else + return NULL; +} + +/* + * Delete partial pages with address between @start and @end. + * @start and @end are page aligned. + */ +static void +__ia32_delete_pp_range(unsigned int start, unsigned int end) +{ + struct partial_page *pp, *prev; + struct rb_node **rb_link, *rb_parent; + + if (start >= end) + return; + + pp = __ia32_find_pp(current->thread.ppl, start, &prev, + &rb_link, &rb_parent); + if (pp) + prev = __pp_prev(pp); + else { + if (prev) + pp = prev->next; + else + pp = current->thread.ppl->pp_head; + } + + while (pp && pp->base < end) { + struct partial_page *tmp = pp->next; + __ia32_delete_pp(current->thread.ppl, pp, prev); + pp = tmp; + } +} + +/* + * Set the range between @start and @end in bitmap. + * @start and @end should be IA32 page aligned and in the same IA64 page. + */ +static int +__ia32_set_pp(unsigned int start, unsigned int end, int flags) +{ + struct partial_page *pp, *prev; + struct rb_node ** rb_link, *rb_parent; + unsigned int pstart, start_bit, end_bit, i; + + pstart = PAGE_START(start); + start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; + end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; + if (end_bit == 0) + end_bit = PAGE_SIZE / IA32_PAGE_SIZE; + pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, + &rb_link, &rb_parent); + if (pp) { + for (i = start_bit; i < end_bit; i++) + set_bit(i, &pp->bitmap); + /* + * Check: if this partial page has been set to a full page, + * then delete it. + */ + if (find_first_zero_bit(&pp->bitmap, sizeof(pp->bitmap)*8) >= + PAGE_SIZE/IA32_PAGE_SIZE) { + __ia32_delete_pp(current->thread.ppl, pp, __pp_prev(pp)); + } + return 0; + } + + /* + * MAP_FIXED may lead to overlapping mmap. + * In this case, the requested mmap area may already mmaped as a full + * page. So check vma before adding a new partial page. + */ + if (flags & MAP_FIXED) { + struct vm_area_struct *vma = find_vma(current->mm, pstart); + if (vma && vma->vm_start <= pstart) + return 0; + } + + /* new a partial_page */ + pp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL); + if (!pp) + return -ENOMEM; + pp->base = pstart; + pp->bitmap = 0; + for (i=start_bit; i<end_bit; i++) + set_bit(i, &(pp->bitmap)); + pp->next = NULL; + __ia32_insert_pp(current->thread.ppl, pp, prev, rb_link, rb_parent); + return 0; +} + +/* + * @start and @end should be IA32 page aligned, but don't need to be in the + * same IA64 page. Split @start and @end to make sure they're in the same IA64 + * page, then call __ia32_set_pp(). + */ +static void +ia32_set_pp(unsigned int start, unsigned int end, int flags) +{ + down_write(¤t->mm->mmap_sem); + if (flags & MAP_FIXED) { + /* + * MAP_FIXED may lead to overlapping mmap. When this happens, + * a series of complete IA64 pages results in deletion of + * old partial pages in that range. + */ + __ia32_delete_pp_range(PAGE_ALIGN(start), PAGE_START(end)); + } + + if (end < PAGE_ALIGN(start)) { + __ia32_set_pp(start, end, flags); + } else { + if (offset_in_page(start)) + __ia32_set_pp(start, PAGE_ALIGN(start), flags); + if (offset_in_page(end)) + __ia32_set_pp(PAGE_START(end), end, flags); + } + up_write(¤t->mm->mmap_sem); +} + +/* + * Unset the range between @start and @end in bitmap. + * @start and @end should be IA32 page aligned and in the same IA64 page. + * After doing that, if the bitmap is 0, then free the page and return 1, + * else return 0; + * If not find the partial page in the list, then + * If the vma exists, then the full page is set to a partial page; + * Else return -ENOMEM. + */ +static int +__ia32_unset_pp(unsigned int start, unsigned int end) +{ + struct partial_page *pp, *prev; + struct rb_node ** rb_link, *rb_parent; + unsigned int pstart, start_bit, end_bit, i; + struct vm_area_struct *vma; + + pstart = PAGE_START(start); + start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; + end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; + if (end_bit == 0) + end_bit = PAGE_SIZE / IA32_PAGE_SIZE; + + pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, + &rb_link, &rb_parent); + if (pp) { + for (i = start_bit; i < end_bit; i++) + clear_bit(i, &pp->bitmap); + if (pp->bitmap == 0) { + __ia32_delete_pp(current->thread.ppl, pp, __pp_prev(pp)); + return 1; + } + return 0; + } + + vma = find_vma(current->mm, pstart); + if (!vma || vma->vm_start > pstart) { + return -ENOMEM; + } + + /* new a partial_page */ + pp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL); + if (!pp) + return -ENOMEM; + pp->base = pstart; + pp->bitmap = 0; + for (i = 0; i < start_bit; i++) + set_bit(i, &(pp->bitmap)); + for (i = end_bit; i < PAGE_SIZE / IA32_PAGE_SIZE; i++) + set_bit(i, &(pp->bitmap)); + pp->next = NULL; + __ia32_insert_pp(current->thread.ppl, pp, prev, rb_link, rb_parent); + return 0; +} + +/* + * Delete pp between PAGE_ALIGN(start) and PAGE_START(end) by calling + * __ia32_delete_pp_range(). Unset possible partial pages by calling + * __ia32_unset_pp(). + * The returned value see __ia32_unset_pp(). + */ +static int +ia32_unset_pp(unsigned int *startp, unsigned int *endp) +{ + unsigned int start = *startp, end = *endp; + int ret = 0; + + down_write(¤t->mm->mmap_sem); + + __ia32_delete_pp_range(PAGE_ALIGN(start), PAGE_START(end)); + + if (end < PAGE_ALIGN(start)) { + ret = __ia32_unset_pp(start, end); + if (ret == 1) { + *startp = PAGE_START(start); + *endp = PAGE_ALIGN(end); + } + if (ret == 0) { + /* to shortcut sys_munmap() in sys32_munmap() */ + *startp = PAGE_START(start); + *endp = PAGE_START(end); + } + } else { + if (offset_in_page(start)) { + ret = __ia32_unset_pp(start, PAGE_ALIGN(start)); + if (ret == 1) + *startp = PAGE_START(start); + if (ret == 0) + *startp = PAGE_ALIGN(start); + if (ret < 0) + goto out; + } + if (offset_in_page(end)) { + ret = __ia32_unset_pp(PAGE_START(end), end); + if (ret == 1) + *endp = PAGE_ALIGN(end); + if (ret == 0) + *endp = PAGE_START(end); + } + } + + out: + up_write(¤t->mm->mmap_sem); + return ret; +} + +/* + * Compare the range between @start and @end with bitmap in partial page. + * @start and @end should be IA32 page aligned and in the same IA64 page. + */ +static int +__ia32_compare_pp(unsigned int start, unsigned int end) +{ + struct partial_page *pp, *prev; + struct rb_node ** rb_link, *rb_parent; + unsigned int pstart, start_bit, end_bit, size; + unsigned int first_bit, next_zero_bit; /* the first range in bitmap */ + + pstart = PAGE_START(start); + + pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, + &rb_link, &rb_parent); + if (!pp) + return 1; + + start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; + end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; + size = sizeof(pp->bitmap) * 8; + first_bit = find_first_bit(&pp->bitmap, size); + next_zero_bit = find_next_zero_bit(&pp->bitmap, size, first_bit); + if ((start_bit < first_bit) || (end_bit > next_zero_bit)) { + /* exceeds the first range in bitmap */ + return -ENOMEM; + } else if ((start_bit == first_bit) && (end_bit == next_zero_bit)) { + first_bit = find_next_bit(&pp->bitmap, size, next_zero_bit); + if ((next_zero_bit < first_bit) && (first_bit < size)) + return 1; /* has next range */ + else + return 0; /* no next range */ + } else + return 1; +} + +/* + * @start and @end should be IA32 page aligned, but don't need to be in the + * same IA64 page. Split @start and @end to make sure they're in the same IA64 + * page, then call __ia32_compare_pp(). + * + * Take this as example: the range is the 1st and 2nd 4K page. + * Return 0 if they fit bitmap exactly, i.e. bitmap = 00000011; + * Return 1 if the range doesn't cover whole bitmap, e.g. bitmap = 00001111; + * Return -ENOMEM if the range exceeds the bitmap, e.g. bitmap = 00000001 or + * bitmap = 00000101. + */ +static int +ia32_compare_pp(unsigned int *startp, unsigned int *endp) +{ + unsigned int start = *startp, end = *endp; + int retval = 0; + + down_write(¤t->mm->mmap_sem); + + if (end < PAGE_ALIGN(start)) { + retval = __ia32_compare_pp(start, end); + if (retval == 0) { + *startp = PAGE_START(start); + *endp = PAGE_ALIGN(end); + } + } else { + if (offset_in_page(start)) { + retval = __ia32_compare_pp(start, + PAGE_ALIGN(start)); + if (retval == 0) + *startp = PAGE_START(start); + if (retval < 0) + goto out; + } + if (offset_in_page(end)) { + retval = __ia32_compare_pp(PAGE_START(end), end); + if (retval == 0) + *endp = PAGE_ALIGN(end); + } + } + + out: + up_write(¤t->mm->mmap_sem); + return retval; +} + +static void +__ia32_drop_pp_list(struct partial_page_list *ppl) +{ + struct partial_page *pp = ppl->pp_head; + + while (pp) { + struct partial_page *next = pp->next; + kmem_cache_free(partial_page_cachep, pp); + pp = next; + } + + kfree(ppl); +} + +void +ia32_drop_partial_page_list(struct task_struct *task) +{ + struct partial_page_list* ppl = task->thread.ppl; + + if (ppl && atomic_dec_and_test(&ppl->pp_count)) + __ia32_drop_pp_list(ppl); +} + +/* + * Copy current->thread.ppl to ppl (already initialized). + */ +static int +__ia32_copy_pp_list(struct partial_page_list *ppl) +{ + struct partial_page *pp, *tmp, *prev; + struct rb_node **rb_link, *rb_parent; + + ppl->pp_head = NULL; + ppl->pp_hint = NULL; + ppl->ppl_rb = RB_ROOT; + rb_link = &ppl->ppl_rb.rb_node; + rb_parent = NULL; + prev = NULL; + + for (pp = current->thread.ppl->pp_head; pp; pp = pp->next) { + tmp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + *tmp = *pp; + __ia32_insert_pp(ppl, tmp, prev, rb_link, rb_parent); + prev = tmp; + rb_link = &tmp->pp_rb.rb_right; + rb_parent = &tmp->pp_rb; + } + return 0; +} + +int +ia32_copy_partial_page_list(struct task_struct *p, unsigned long clone_flags) +{ + int retval = 0; + + if (clone_flags & CLONE_VM) { + atomic_inc(¤t->thread.ppl->pp_count); + p->thread.ppl = current->thread.ppl; + } else { + p->thread.ppl = ia32_init_pp_list(); + if (!p->thread.ppl) + return -ENOMEM; + down_write(¤t->mm->mmap_sem); + { + retval = __ia32_copy_pp_list(p->thread.ppl); + } + up_write(¤t->mm->mmap_sem); + } + + return retval; +} + static unsigned long emulate_mmap (struct file *file, unsigned long start, unsigned long len, int prot, int flags, loff_t off) @@ -263,6 +767,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro pend = PAGE_ALIGN(end); if (flags & MAP_FIXED) { + ia32_set_pp((unsigned int)start, (unsigned int)end, flags); if (start > pstart) { if (flags & MAP_SHARED) printk(KERN_INFO @@ -274,7 +779,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro return ret; pstart += PAGE_SIZE; if (pstart >= pend) - return start; /* done */ + goto out; /* done */ } if (end < pend) { if (flags & MAP_SHARED) @@ -287,7 +792,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro return ret; pend -= PAGE_SIZE; if (pstart >= pend) - return start; /* done */ + goto out; /* done */ } } else { /* @@ -341,6 +846,10 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro if (!(prot & PROT_WRITE) && sys_mprotect(pstart, pend - pstart, prot) < 0) return -EINVAL; } + + if (!(flags & MAP_FIXED)) + ia32_set_pp((unsigned int)start, (unsigned int)end, flags); +out: return start; } @@ -478,11 +987,16 @@ sys32_munmap (unsigned int start, unsigned int len) #if PAGE_SHIFT <= IA32_PAGE_SHIFT ret = sys_munmap(start, end - start); #else + if (OFFSET4K(start)) + return -EINVAL; + + end = IA32_PAGE_ALIGN(end); if (start >= end) return -EINVAL; - start = PAGE_ALIGN(start); - end = PAGE_START(end); + ret = ia32_unset_pp(&start, &end); + if (ret < 0) + return ret; if (start >= end) return 0; @@ -521,7 +1035,7 @@ mprotect_subpage (unsigned long address, int new_prot) asmlinkage long sys32_mprotect (unsigned int start, unsigned int len, int prot) { - unsigned long end = start + len; + unsigned int end = start + len; #if PAGE_SHIFT > IA32_PAGE_SHIFT long retval = 0; #endif @@ -538,6 +1052,11 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot) if (end < start) return -EINVAL; + retval = ia32_compare_pp(&start, &end); + + if (retval < 0) + return retval; + down(&ia32_mmap_sem); { if (offset_in_page(start)) { @@ -568,6 +1087,59 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot) } asmlinkage long +sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len, + unsigned int flags, unsigned int new_addr) +{ + long ret; + +#if PAGE_SHIFT <= IA32_PAGE_SHIFT + ret = sys_mremap(addr, old_len, new_len, flags, new_addr); +#else + unsigned int old_end, new_end; + + if (OFFSET4K(addr)) + return -EINVAL; + + old_len = IA32_PAGE_ALIGN(old_len); + new_len = IA32_PAGE_ALIGN(new_len); + old_end = addr + old_len; + new_end = addr + new_len; + + if (!new_len) + return -EINVAL; + + if ((flags & MREMAP_FIXED) && (OFFSET4K(new_addr))) + return -EINVAL; + + if (old_len >= new_len) { + ret = sys32_munmap(addr + new_len, old_len - new_len); + if (ret && old_len != new_len) + return ret; + ret = addr; + if (!(flags & MREMAP_FIXED) || (new_addr == addr)) + return ret; + old_len = new_len; + } + + addr = PAGE_START(addr); + old_len = PAGE_ALIGN(old_end) - addr; + new_len = PAGE_ALIGN(new_end) - addr; + + down(&ia32_mmap_sem); + { + ret = sys_mremap(addr, old_len, new_len, flags, new_addr); + } + up(&ia32_mmap_sem); + + if ((ret >= 0) && (old_len < new_len)) { + /* mremap expanded successfully */ + ia32_set_pp(old_end, new_end, flags); + } +#endif + return ret; +} + +asmlinkage long sys32_pipe (int *fd) { int retval; diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 45a49b600c20..d148a2c92174 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -179,17 +179,19 @@ GLOBAL_ENTRY(ia64_switch_to) .body adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13 + movl r25=init_task mov r27=IA64_KR(CURRENT_STACK) + adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0 dep r20=0,in0,61,3 // physical address of "current" ;; st8 [r22]=sp // save kernel stack pointer of old task shr.u r26=r20,IA64_GRANULE_SHIFT - adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0 + cmp.eq p7,p6=r25,in0 ;; /* * If we've already mapped this task's page, we can skip doing it again. */ - cmp.eq p7,p6=r26,r27 +(p6) cmp.eq p7,p6=r26,r27 (p6) br.cond.dpnt .map ;; .done: diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 0a5eb48d5de9..406d3e6ca797 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -154,6 +154,10 @@ start_ap: #endif ;; tpa r3=r2 // r3 == phys addr of task struct + ;; + shr.u r16=r3,IA64_GRANULE_SHIFT +(isBP) br.cond.dpnt .load_current // BP stack is on region 5 --- no need to map it + // load mapping for stack (virtaddr in r2, physaddr in r3) rsm psr.ic movl r17=PAGE_KERNEL @@ -165,7 +169,6 @@ start_ap: dep r2=-1,r3,61,3 // IMVA of task ;; mov r17=rr[r2] - shr.u r16=r3,IA64_GRANULE_SHIFT ;; dep r17=0,r17,8,24 ;; @@ -180,6 +183,7 @@ start_ap: srlz.d ;; +.load_current: // load the "current" pointer (r13) and ar.k6 with the current task mov IA64_KR(CURRENT)=r2 // virtual address mov IA64_KR(CURRENT_STACK)=r16 diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 1e1f05c98b6e..ae00f7e21472 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -100,7 +100,6 @@ #endif static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; -extern cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ @@ -335,21 +334,6 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) #endif } -static inline void move_irq(int irq) -{ - /* note - we hold desc->lock */ - cpumask_t tmp; - irq_desc_t *desc = irq_descp(irq); - - if (!cpus_empty(pending_irq_cpumask[irq])) { - cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); - if (unlikely(!cpus_empty(tmp))) { - desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); - } - cpus_clear(pending_irq_cpumask[irq]); - } -} - /* * Handlers for level-triggered interrupts. */ diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 42056fbaa151..3087c13d08d7 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -1018,6 +1018,22 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, return full_count; } +void move_irq(int irq) +{ + /* note - we hold desc->lock */ + cpumask_t tmp; + irq_desc_t *desc = irq_descp(irq); + + if (!cpus_empty(pending_irq_cpumask[irq])) { + cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); + if (unlikely(!cpus_empty(tmp))) { + desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); + } + cpus_clear(pending_irq_cpumask[irq]); + } +} + + #endif /* CONFIG_SMP */ #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 3f2e929a207a..603b1713b1de 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -108,6 +108,7 @@ struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS]; #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */ #define MIN_CPE_POLL_INTERVAL (2*60*HZ) /* 2 minutes */ #define CMC_POLL_INTERVAL (1*60*HZ) /* 1 minute */ +#define CPE_HISTORY_LENGTH 5 #define CMC_HISTORY_LENGTH 5 static struct timer_list cpe_poll_timer; @@ -127,6 +128,8 @@ static int cmc_polling_enabled = 1; */ static int cpe_poll_enabled = 1; +static int cpe_vector = -1; + extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe); /* @@ -267,20 +270,65 @@ ia64_mca_log_sal_error_record(int sal_info_type) */ #ifndef PLATFORM_MCA_HANDLERS +#ifdef CONFIG_ACPI + static irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) { - IA64_MCA_DEBUG("%s: received interrupt. CPU:%d vector = %#x\n", - __FUNCTION__, smp_processor_id(), cpe_irq); + static unsigned long cpe_history[CPE_HISTORY_LENGTH]; + static int index; + static spinlock_t cpe_history_lock = SPIN_LOCK_UNLOCKED; + + IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n", + __FUNCTION__, cpe_irq, smp_processor_id()); /* SAL spec states this should run w/ interrupts enabled */ local_irq_enable(); - /* Get the CMC error record and log it */ + /* Get the CPE error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE); + + spin_lock(&cpe_history_lock); + if (!cpe_poll_enabled && cpe_vector >= 0) { + + int i, count = 1; /* we know 1 happened now */ + unsigned long now = jiffies; + + for (i = 0; i < CPE_HISTORY_LENGTH; i++) { + if (now - cpe_history[i] <= HZ) + count++; + } + + IA64_MCA_DEBUG(KERN_INFO "CPE threshold %d/%d\n", count, CPE_HISTORY_LENGTH); + if (count >= CPE_HISTORY_LENGTH) { + + cpe_poll_enabled = 1; + spin_unlock(&cpe_history_lock); + disable_irq_nosync(local_vector_to_irq(IA64_CPE_VECTOR)); + + /* + * Corrected errors will still be corrected, but + * make sure there's a log somewhere that indicates + * something is generating more than we can handle. + */ + printk(KERN_WARNING "WARNING: Switching to polling CPE handler; error records may be lost\n"); + + mod_timer(&cpe_poll_timer, jiffies + MIN_CPE_POLL_INTERVAL); + + /* lock already released, get out now */ + return IRQ_HANDLED; + } else { + cpe_history[index++] = now; + if (index == CPE_HISTORY_LENGTH) + index = 0; + } + } + spin_unlock(&cpe_history_lock); return IRQ_HANDLED; } +#endif /* CONFIG_ACPI */ + static void show_min_state (pal_min_state_area_t *minstate) { @@ -901,7 +949,7 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs) * handled */ static irqreturn_t -ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) +ia64_mca_cmc_int_caller(int cmc_irq, void *arg, struct pt_regs *ptregs) { static int start_count = -1; unsigned int cpuid; @@ -912,7 +960,7 @@ ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) if (start_count == -1) start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC); - ia64_mca_cmc_int_handler(cpe_irq, arg, ptregs); + ia64_mca_cmc_int_handler(cmc_irq, arg, ptregs); for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++); @@ -967,11 +1015,13 @@ ia64_mca_cmc_poll (unsigned long dummy) * Outputs * handled */ +#ifdef CONFIG_ACPI + static irqreturn_t ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) { static int start_count = -1; - static int poll_time = MAX_CPE_POLL_INTERVAL; + static int poll_time = MIN_CPE_POLL_INTERVAL; unsigned int cpuid; cpuid = smp_processor_id(); @@ -989,20 +1039,30 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) } else { /* * If a log was recorded, increase our polling frequency, - * otherwise, backoff. + * otherwise, backoff or return to interrupt mode. */ if (start_count != IA64_LOG_COUNT(SAL_INFO_TYPE_CPE)) { poll_time = max(MIN_CPE_POLL_INTERVAL, poll_time / 2); - } else { + } else if (cpe_vector < 0) { poll_time = min(MAX_CPE_POLL_INTERVAL, poll_time * 2); + } else { + poll_time = MIN_CPE_POLL_INTERVAL; + + printk(KERN_WARNING "Returning to interrupt driven CPE handler\n"); + enable_irq(local_vector_to_irq(IA64_CPE_VECTOR)); + cpe_poll_enabled = 0; } + + if (cpe_poll_enabled) + mod_timer(&cpe_poll_timer, jiffies + poll_time); start_count = -1; - mod_timer(&cpe_poll_timer, jiffies + poll_time); } return IRQ_HANDLED; } +#endif /* CONFIG_ACPI */ + /* * ia64_mca_cpe_poll * @@ -1240,21 +1300,23 @@ ia64_mca_init(void) register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); #ifdef CONFIG_ACPI - /* Setup the CPE interrupt vector */ + /* Setup the CPEI/P vector and handler */ { irq_desc_t *desc; unsigned int irq; - int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI); - if (cpev >= 0) { + cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI); + + if (cpe_vector >= 0) { for (irq = 0; irq < NR_IRQS; ++irq) - if (irq_to_vector(irq) == cpev) { + if (irq_to_vector(irq) == cpe_vector) { desc = irq_descp(irq); desc->status |= IRQ_PER_CPU; setup_irq(irq, &mca_cpe_irqaction); } - ia64_mca_register_cpev(cpev); + ia64_mca_register_cpev(cpe_vector); } + register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); } #endif @@ -1294,9 +1356,10 @@ ia64_mca_late_init(void) #ifdef CONFIG_ACPI /* If platform doesn't support CPEI, get the timer going. */ - if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) { - register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); + if (cpe_vector < 0 && cpe_poll_enabled) { ia64_mca_cpe_poll(0UL); + } else { + cpe_poll_enabled = 0; } #endif diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index fab4296e2cf4..3cbe961ed746 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c @@ -515,10 +515,10 @@ static const char *bus_features[]={ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - "Enable Cache Line Repl. Exclusive", "Enable Cache Line Repl. Shared", + "Enable Cache Line Repl. Exclusive", "Disable Transaction Queuing", - "Disable Reponse Error Checking", + "Disable Response Error Checking", "Disable Bus Error Checking", "Disable Bus Requester Internal Error Signalling", "Disable Bus Requester Error Signalling", diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 85371f48a9af..0520ef37be55 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -311,6 +311,7 @@ typedef struct pfm_context { unsigned int ctx_cpu; /* cpu to which perfmon is applied (system wide) */ int ctx_fd; /* file descriptor used my this context */ + pfm_ovfl_arg_t ctx_ovfl_arg; /* argument to custom buffer format handler */ pfm_buffer_fmt_t *ctx_buf_fmt; /* buffer format callbacks */ void *ctx_smpl_hdr; /* points to sampling buffer header kernel vaddr */ @@ -4584,31 +4585,6 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg return 0; } -static void -pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs) -{ - struct task_struct *task = ctx->ctx_task; - - ia64_psr(regs)->up = 0; - ia64_psr(regs)->sp = 1; - - if (GET_PMU_OWNER() == task) { - DPRINT(("cleared ownership for [%d]\n", ctx->ctx_task->pid)); - SET_PMU_OWNER(NULL, NULL); - } - - /* - * disconnect the task from the context and vice-versa - */ - PFM_SET_WORK_PENDING(task, 0); - - task->thread.pfm_context = NULL; - task->thread.flags &= ~IA64_THREAD_PM_VALID; - - DPRINT(("force cleanupf for [%d]\n", task->pid)); -} - - /* * called only from exit_thread(): task == current @@ -5185,7 +5161,7 @@ pfm_end_notify_user(pfm_context_t *ctx) static void pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs) { - pfm_ovfl_arg_t ovfl_arg; + pfm_ovfl_arg_t *ovfl_arg; unsigned long mask; unsigned long old_val, ovfl_val, new_val; unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL, reset_pmds; @@ -5272,7 +5248,8 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str int j, k, ret = 0; int this_cpu = smp_processor_id(); - pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER; + pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER; + ovfl_arg = &ctx->ctx_ovfl_arg; prefetch(ctx->ctx_smpl_hdr); @@ -5282,15 +5259,15 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str if ((pmd_mask & 0x1) == 0) continue; - ovfl_arg.ovfl_pmd = (unsigned char )i; - ovfl_arg.ovfl_notify = ovfl_notify & mask ? 1 : 0; - ovfl_arg.active_set = 0; - ovfl_arg.ovfl_ctrl.val = 0; /* module must fill in all fields */ - ovfl_arg.smpl_pmds[0] = smpl_pmds = ctx->ctx_pmds[i].smpl_pmds[0]; + ovfl_arg->ovfl_pmd = (unsigned char )i; + ovfl_arg->ovfl_notify = ovfl_notify & mask ? 1 : 0; + ovfl_arg->active_set = 0; + ovfl_arg->ovfl_ctrl.val = 0; /* module must fill in all fields */ + ovfl_arg->smpl_pmds[0] = smpl_pmds = ctx->ctx_pmds[i].smpl_pmds[0]; - ovfl_arg.pmd_value = ctx->ctx_pmds[i].val; - ovfl_arg.pmd_last_reset = ctx->ctx_pmds[i].lval; - ovfl_arg.pmd_eventid = ctx->ctx_pmds[i].eventid; + ovfl_arg->pmd_value = ctx->ctx_pmds[i].val; + ovfl_arg->pmd_last_reset = ctx->ctx_pmds[i].lval; + ovfl_arg->pmd_eventid = ctx->ctx_pmds[i].eventid; /* * copy values of pmds of interest. Sampling format may copy them @@ -5299,8 +5276,8 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str if (smpl_pmds) { for(j=0, k=0; smpl_pmds; j++, smpl_pmds >>=1) { if ((smpl_pmds & 0x1) == 0) continue; - ovfl_arg.smpl_pmds_values[k++] = PMD_IS_COUNTING(j) ? pfm_read_soft_counter(ctx, j) : ia64_get_pmd(j); - DPRINT_ovfl(("smpl_pmd[%d]=pmd%u=0x%lx\n", k-1, j, ovfl_arg.smpl_pmds_values[k-1])); + ovfl_arg->smpl_pmds_values[k++] = PMD_IS_COUNTING(j) ? pfm_read_soft_counter(ctx, j) : ia64_get_pmd(j); + DPRINT_ovfl(("smpl_pmd[%d]=pmd%u=0x%lx\n", k-1, j, ovfl_arg->smpl_pmds_values[k-1])); } } @@ -5311,7 +5288,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str /* * call custom buffer format record (handler) routine */ - ret = (*ctx->ctx_buf_fmt->fmt_handler)(task, ctx->ctx_smpl_hdr, &ovfl_arg, regs, tstamp); + ret = (*ctx->ctx_buf_fmt->fmt_handler)(task, ctx->ctx_smpl_hdr, ovfl_arg, regs, tstamp); end_cycles = ia64_get_itc(); @@ -5319,13 +5296,13 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str * For those controls, we take the union because they have * an all or nothing behavior. */ - ovfl_ctrl.bits.notify_user |= ovfl_arg.ovfl_ctrl.bits.notify_user; - ovfl_ctrl.bits.block_task |= ovfl_arg.ovfl_ctrl.bits.block_task; - ovfl_ctrl.bits.mask_monitoring |= ovfl_arg.ovfl_ctrl.bits.mask_monitoring; + ovfl_ctrl.bits.notify_user |= ovfl_arg->ovfl_ctrl.bits.notify_user; + ovfl_ctrl.bits.block_task |= ovfl_arg->ovfl_ctrl.bits.block_task; + ovfl_ctrl.bits.mask_monitoring |= ovfl_arg->ovfl_ctrl.bits.mask_monitoring; /* * build the bitmask of pmds to reset now */ - if (ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask; + if (ovfl_arg->ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask; pfm_stats[this_cpu].pfm_smpl_handler_cycles += end_cycles - start_cycles; } @@ -5793,6 +5770,32 @@ pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_c } #ifdef CONFIG_SMP + +static void +pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs) +{ + struct task_struct *task = ctx->ctx_task; + + ia64_psr(regs)->up = 0; + ia64_psr(regs)->sp = 1; + + if (GET_PMU_OWNER() == task) { + DPRINT(("cleared ownership for [%d]\n", ctx->ctx_task->pid)); + SET_PMU_OWNER(NULL, NULL); + } + + /* + * disconnect the task from the context and vice-versa + */ + PFM_SET_WORK_PENDING(task, 0); + + task->thread.pfm_context = NULL; + task->thread.flags &= ~IA64_THREAD_PM_VALID; + + DPRINT(("force cleanup for [%d]\n", task->pid)); +} + + /* * in 2.6, interrupts are masked when we come here and the runqueue lock is held */ diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 7455e489478c..f49b98c6d3f3 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -439,6 +439,10 @@ copy_thread (int nr, unsigned long clone_flags, ia32_save_state(p); if (clone_flags & CLONE_SETTLS) retval = ia32_clone_tls(p, child_ptregs); + + /* Copy partially mapped page list */ + if (!retval) + retval = ia32_copy_partial_page_list(p, clone_flags); } #endif @@ -672,6 +676,8 @@ flush_thread (void) /* drop floating-point and debug-register state if it exists: */ current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); ia64_drop_fpu(current); + if (IS_IA32_PROCESS(ia64_task_regs(current))) + ia32_drop_partial_page_list(current); } /* @@ -691,6 +697,8 @@ exit_thread (void) if (current->thread.flags & IA64_THREAD_DBG_VALID) pfm_release_debug_registers(current); #endif + if (IS_IA32_PROCESS(ia64_task_regs(current))) + ia32_drop_partial_page_list(current); } unsigned long diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index e8be97229f00..769d880df580 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -385,9 +385,10 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char } if (write) { - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else { + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else { *addr = *val; if (*nat) *nat_addr |= nat_mask; @@ -432,9 +433,10 @@ unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int return -1; } if (write) - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else *addr = *val; else *val = *addr; @@ -480,9 +482,10 @@ unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, } if (write) - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else *addr = *val; else *val = *addr; @@ -576,9 +579,10 @@ unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int } if (write) { - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else *addr = *val; } else *val = *addr; @@ -596,9 +600,10 @@ unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write) addr = &info->sw->pr; if (write) { - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else *addr = *val; } else *val = *addr; diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 751af133cfcf..b8472d960191 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -154,6 +154,9 @@ static void __init reassign_cpu_only_nodes(void) memcpy(numa_slit, numa_slit_fix, sizeof (numa_slit)); + for (i = nnode; i < numnodes; i++) + node_set_offline(i); + numnodes = nnode; return; diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c index 56e409ec6800..d8abe45944ea 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c @@ -297,7 +297,7 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) unlock_page(page); } else { hugetlb_put_quota(mapping); - free_huge_page(page); + page_cache_release(page); goto out; } } diff --git a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c index 1cb5beae5742..ba9e42c12ac5 100644 --- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c +++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c @@ -741,7 +741,7 @@ pci_bus_to_hcl_cvlink(void) /* Is this PCI bus associated with this moduleid? */ moduleid = NODE_MODULEID( nasid_to_cnodeid(pcibr_soft->bs_nasid)); - if (modules[i]->id == moduleid) { + if (sn_modules[i]->id == moduleid) { struct pcibr_list_s *new_element; new_element = kmalloc(sizeof (struct pcibr_soft_s), GFP_KERNEL); @@ -781,7 +781,7 @@ pci_bus_to_hcl_cvlink(void) /* * We now have a list of all the pci bridges associated with - * the module_id, modules[i]. Call pci_bus_map_create() for + * the module_id, sn_modules[i]. Call pci_bus_map_create() for * each pci bridge */ softlistp = first_in_list; diff --git a/arch/ia64/sn/io/sn2/klgraph.c b/arch/ia64/sn/io/sn2/klgraph.c index ca342b7129b1..4fdffb877485 100644 --- a/arch/ia64/sn/io/sn2/klgraph.c +++ b/arch/ia64/sn/io/sn2/klgraph.c @@ -527,7 +527,7 @@ klhwg_add_all_modules(vertex_hdl_t hwgraph_root) /* Use module as module vertex fastinfo */ memset(buffer, 0, 16); - format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF); + format_module_id(buffer, sn_modules[cm]->id, MODULE_FORMAT_BRIEF); sprintf(name, EDGE_LBL_MODULE "/%s", buffer); rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl); @@ -535,7 +535,7 @@ klhwg_add_all_modules(vertex_hdl_t hwgraph_root) rc = rc; HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, module_vhdl, NULL, "Created module path.\n"); - hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]); + hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) sn_modules[cm]); /* Add system controller */ sprintf(name, diff --git a/arch/ia64/sn/io/sn2/ml_iograph.c b/arch/ia64/sn/io/sn2/ml_iograph.c index d0b0a5b58c66..9bb04c904014 100644 --- a/arch/ia64/sn/io/sn2/ml_iograph.c +++ b/arch/ia64/sn/io/sn2/ml_iograph.c @@ -518,6 +518,14 @@ io_init_node(cnodeid_t cnodeid) ASSERT(hubv != GRAPH_VERTEX_NONE); /* + * attach our hub_provider information to hubv, + * so we can use it as a crosstalk provider "master" + * vertex. + */ + xtalk_provider_register(hubv, &hub_provider); + xtalk_provider_startup(hubv); + + /* * If nothing connected to this hub's xtalk port, we're done. */ early_probe_for_widget(hubv, &hwid); @@ -527,14 +535,6 @@ io_init_node(cnodeid_t cnodeid) /* NOTREACHED */ } - /* - * attach our hub_provider information to hubv, - * so we can use it as a crosstalk provider "master" - * vertex. - */ - xtalk_provider_register(hubv, &hub_provider); - xtalk_provider_startup(hubv); - /* * Create a vertex to represent the crosstalk bus * attached to this hub, and a vertex to be used diff --git a/arch/ia64/sn/io/sn2/module.c b/arch/ia64/sn/io/sn2/module.c index 0bba7843e584..56e3188750c8 100644 --- a/arch/ia64/sn/io/sn2/module.c +++ b/arch/ia64/sn/io/sn2/module.c @@ -33,7 +33,7 @@ #define DPRINTF(x...) #endif -module_t *modules[MODULE_MAX]; +module_t *sn_modules[MODULE_MAX]; int nummodules; #define SN00_SERIAL_FUDGE 0x3b1af409d513c2 @@ -59,9 +59,9 @@ module_lookup(moduleid_t id) int i; for (i = 0; i < nummodules; i++) - if (modules[i]->id == id) { - DPRINTF("module_lookup: found m=0x%p\n", modules[i]); - return modules[i]; + if (sn_modules[i]->id == id) { + DPRINTF("module_lookup: found m=0x%p\n", sn_modules[i]); + return sn_modules[i]; } return NULL; @@ -104,10 +104,10 @@ module_add_node(geoid_t geoid, cnodeid_t cnodeid) /* Insert in sorted order by module number */ - for (i = nummodules; i > 0 && modules[i - 1]->id > moduleid; i--) - modules[i] = modules[i - 1]; + for (i = nummodules; i > 0 && sn_modules[i - 1]->id > moduleid; i--) + sn_modules[i] = sn_modules[i - 1]; - modules[i] = m; + sn_modules[i] = m; nummodules++; } diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 88f0bbaed5d7..8991f9cafa3c 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -41,6 +41,7 @@ static void force_interrupt(int irq); extern void pcibr_force_interrupt(pcibr_intr_t intr); extern int sn_force_interrupt_flag; struct irq_desc * sn_irq_desc(unsigned int irq); +extern cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; struct sn_intr_list_t { struct sn_intr_list_t *next; @@ -71,6 +72,21 @@ sn_enable_irq(unsigned int irq) { } +static inline void move_irq(int irq) +{ + /* note - we hold desc->lock */ + cpumask_t tmp; + irq_desc_t *desc = irq_descp(irq); + + if (!cpus_empty(pending_irq_cpumask[irq])) { + cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); + if (unlikely(!cpus_empty(tmp))) { + desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); + } + cpus_clear(pending_irq_cpumask[irq]); + } +} + static void sn_ack_irq(unsigned int irq) { @@ -94,6 +110,7 @@ sn_ack_irq(unsigned int irq) } HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask ); __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); + move_irq(irq); } static void diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 9644e5805cc4..da099657a9e8 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -226,7 +226,25 @@ sn_check_for_wars(void) shub_1_1_found = 1; } - +/** + * sn_set_error_handling_features - Tell the SN prom how to handle certain + * error types. + */ +static void __init +sn_set_error_handling_features(void) +{ + u64 ret; + u64 sn_ehf_bits[7]; /* see ia64_sn_set_error_handling_features */ + memset(sn_ehf_bits, 0, sizeof(sn_ehf_bits)); +#define EHF(x) __set_bit(SN_SAL_EHF_ ## x, sn_ehf_bits) + EHF(MCA_SLV_TO_OS_INIT_SLV); + EHF(NO_RZ_TLBC); + // Uncomment once Jesse's code goes in - EHF(NO_RZ_IO_READ); +#undef EHF + ret = ia64_sn_set_error_handling_features(sn_ehf_bits); + if (ret) + printk(KERN_ERR "%s: failed, return code %ld\n", __FUNCTION__, ret); +} /** * sn_setup - SN platform setup routine @@ -318,6 +336,9 @@ sn_setup(char **cmdline_p) master_node_bedrock_address); } + /* Tell the prom how to handle certain error types */ + sn_set_error_handling_features(); + /* * we set the default root device to /dev/hda * to make simulation easy diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index 6a8736ecd778..bc79771e8953 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -28,6 +28,8 @@ ifdef CONFIG_SUN3 LDFLAGS_vmlinux = -N endif +CHECK := $(CHECK) -D__mc68000__=1 -I$(shell $(CC) -print-file-name=include) + # without -fno-strength-reduce the 53c7xx.c driver fails ;-( CFLAGS += -pipe -fno-strength-reduce -ffixed-a2 diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S index fc25c5fde554..d32e81c425fe 100644 --- a/arch/m68k/ifpsp060/iskeleton.S +++ b/arch/m68k/ifpsp060/iskeleton.S @@ -196,14 +196,57 @@ _060_real_cas2: | Expected outputs: | d0 = 0 -> success; non-zero -> failure | -| Linux/68k: As long as ints are disabled, no swapping out should -| occur (hopefully...) +| Linux/m68k: Make sure the page is properly paged in, so we use +| plpaw and handle any exception here. The kernel must not be +| preempted until _060_unlock_page(), so that the page stays mapped. | .global _060_real_lock_page _060_real_lock_page: - clr.l %d0 + move.l %d2,-(%sp) + | load sfc/dfc + moveq #5,%d0 + tst.b %d0 + jne 1f + moveq #1,%d0 +1: movec.l %dfc,%d2 + movec.l %d0,%dfc + movec.l %d0,%sfc + + clr.l %d0 + | prefetch address + .chip 68060 + move.l %a0,%a1 +1: plpaw (%a1) + addq.w #1,%a0 + tst.b %d1 + jeq 2f + addq.w #2,%a0 +2: plpaw (%a0) +3: .chip 68k + + | restore sfc/dfc + movec.l %d2,%dfc + movec.l %d2,%sfc + move.l (%sp)+,%d2 rts +.section __ex_table,"a" + .align 4 + .long 1b,11f + .long 2b,21f +.previous +.section .fixup,"ax" + .even +11: move.l #0x020003c0,%d0 + or.l %d2,%d0 + swap %d0 + jra 3b +21: move.l #0x02000bc0,%d0 + or.l %d2,%d0 + swap %d0 + jra 3b +.previous + | | _060_unlock_page(): | @@ -216,8 +259,7 @@ _060_real_lock_page: | d0 = `xxxxxxff -> supervisor; `xxxxxx00 -> user | d1 = `xxxxxxff -> longword; `xxxxxx00 -> word | -| Linux/68k: As we do no special locking operation, also no unlocking -| is needed... +| Linux/m68k: perhaps reenable preemption here... .global _060_real_unlock_page _060_real_unlock_page: diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 0fd62ab0f21c..095383287e01 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -228,8 +228,8 @@ static inline int restore_fpu_state(struct sigcontext *sc) goto out; __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %0,%/fp0-%/fp1\n\t" - "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" + "fmovemx %0,%%fp0-%%fp1\n\t" + "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" ".chip 68k" : /* no outputs */ : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); @@ -258,7 +258,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) if (FPU_IS_EMU) { /* restore fpu control register */ if (__copy_from_user(current->thread.fpcntl, - &uc->uc_mcontext.fpregs.f_pcr, 12)) + uc->uc_mcontext.fpregs.f_fpcntl, 12)) goto out; /* restore all other fpu register */ if (__copy_from_user(current->thread.fp, @@ -298,12 +298,12 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) sizeof(fpregs))) goto out; __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %0,%/fp0-%/fp7\n\t" - "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" + "fmovemx %0,%%fp0-%%fp7\n\t" + "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" ".chip 68k" : /* no outputs */ : "m" (*fpregs.f_fpregs), - "m" (fpregs.f_pcr)); + "m" (*fpregs.f_fpcntl)); } if (context_size && __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1, @@ -586,12 +586,12 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) sc->sc_fpstate[0x38] |= 1 << 3; } __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %/fp0-%/fp1,%0\n\t" - "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" + "fmovemx %%fp0-%%fp1,%0\n\t" + "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" ".chip 68k" - : /* no outputs */ - : "m" (*sc->sc_fpregs), - "m" (*sc->sc_fpcntl) + : "=m" (*sc->sc_fpregs), + "=m" (*sc->sc_fpcntl) + : /* no inputs */ : "memory"); } } @@ -604,7 +604,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) if (FPU_IS_EMU) { /* save fpu control register */ - err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr, + err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl, current->thread.fpcntl, 12); /* save all other fpu register */ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, @@ -631,12 +631,12 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) fpstate[0x38] |= 1 << 3; } __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %/fp0-%/fp7,%0\n\t" - "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" + "fmovemx %%fp0-%%fp7,%0\n\t" + "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" ".chip 68k" - : /* no outputs */ - : "m" (*fpregs.f_fpregs), - "m" (fpregs.f_pcr) + : "=m" (*fpregs.f_fpregs), + "=m" (*fpregs.f_fpcntl) + : /* no inputs */ : "memory"); err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, sizeof(fpregs)); diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index fdf8e0ae998c..9ed31dccdc1d 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -329,7 +329,8 @@ static inline void access_error060 (struct frame *fp) * fault during mem_read/mem_write in ifpsp060/os.S */ send_fault_sig(&fp->ptregs); - } else { + } else if (!(fslw & (MMU060_RE|MMU060_WE)) || + send_fault_sig(&fp->ptregs) > 0) { printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); printk( "68060 access error, fslw=%lx\n", fslw ); trap_c( fp ); @@ -517,7 +518,7 @@ static inline void access_error040(struct frame *fp) if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) fp->un.fmt7.wb2s &= ~WBV_040; } - } else { + } else if (send_fault_sig(&fp->ptregs) > 0) { printk("68040 access error, ssw=%x\n", ssw); trap_c(fp); } @@ -732,7 +733,7 @@ static inline void bus_error030 (struct frame *fp) return; } else if (!(mmusr & MMU_I)) { /* probably a 020 cas fault */ - if (!(ssw & RM)) + if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { printk("invalid %s access at %#lx from pc %#lx\n", diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 59442d0912b2..d889ba80ccdc 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -261,7 +261,7 @@ void __init iop_preinit(void) } else { iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_QUADRA; } - iop_base[IOP_NUM_SCC]->status_ctrl = 0; + iop_base[IOP_NUM_ISM]->status_ctrl = 0; iop_ism_present = 1; } else { iop_base[IOP_NUM_ISM] = NULL; diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index d9616bebb973..411c06f48314 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -54,7 +54,7 @@ void __init init_pointer_table(unsigned long ptable) /* unreserve the page so it's possible to free that page */ PD_PAGE(dp)->flags &= ~(1 << PG_reserved); - atomic_set(&PD_PAGE(dp)->count, 1); + set_page_count(PD_PAGE(dp), 1); return; } diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 920bec8616eb..080eb3c37aba 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -932,11 +932,6 @@ config AU1000_USB_DEVICE depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 default n -config COBALT_LCD - bool - depends on MIPS_COBALT - default y - config MIPS_GT96100 bool depends on MIPS_EV96100 diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig index a653f0297543..fb148427e050 100644 --- a/arch/mips/configs/cobalt_defconfig +++ b/arch/mips/configs/cobalt_defconfig @@ -80,7 +80,6 @@ CONFIG_I8259=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_IRQ_CPU=y CONFIG_MIPS_GT64111=y -CONFIG_COBALT_LCD=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_FB is not set @@ -432,6 +431,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_WATCHDOG is not set CONFIG_RTC=y +CONFIG_COBALT_LCD=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index bbd6215cc611..912beee0c66c 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -583,7 +583,7 @@ CONFIG_WATCHDOG=y CONFIG_INDYDOG=m # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set -CONFIG_SGI_DS1286=y +CONFIG_SGI_DS1286=m # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set diff --git a/arch/mips/defconfig b/arch/mips/defconfig index bbd6215cc611..912beee0c66c 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -583,7 +583,7 @@ CONFIG_WATCHDOG=y CONFIG_INDYDOG=m # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set -CONFIG_SGI_DS1286=y +CONFIG_SGI_DS1286=m # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c index 4fb03a944f72..1a8e1bf630c6 100644 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ b/arch/ppc64/kernel/ppc_ksyms.c @@ -50,7 +50,6 @@ extern int do_signal(sigset_t *, struct pt_regs *); int abs(int); EXPORT_SYMBOL(do_signal); -EXPORT_SYMBOL(sys_ioctl); EXPORT_SYMBOL(isa_io_base); EXPORT_SYMBOL(pci_io_base); diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 5ba86ba1aded..90e7fe6687ba 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -76,4 +76,3 @@ EXPORT_SYMBOL(console_device); EXPORT_SYMBOL_NOVERS(do_call_softirq); EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(cpcmd); -EXPORT_SYMBOL(sys_ioctl); diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index f82adfbf7e00..fb3dff0b2deb 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1751,42 +1751,44 @@ ret_sys_call: ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc sra %o0, 0, %o0 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 - cmp %o0, -ENOIOCTLCMD sllx %g2, 32, %g2 + + /* Check if force_successful_syscall_return() + * was invoked. + */ + ldx [%curptr + TI_FLAGS], %l0 + andcc %l0, _TIF_SYSCALL_SUCCESS, %g0 + be,pt %icc, 1f + andn %l0, _TIF_SYSCALL_SUCCESS, %l0 + ba,pt %xcc, 80f + stx %l0, [%curptr + TI_FLAGS] + +1: + cmp %o0, -ENOIOCTLCMD bgeu,pn %xcc, 1f andcc %l0, _TIF_SYSCALL_TRACE, %l6 80: - andn %g3, %g2, %g3 /* System call success, clear Carry condition code. */ + /* System call success, clear Carry condition code. */ + andn %g3, %g2, %g3 stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 - add %l1, 0x4, %l2 ! npc = npc+4 + add %l1, 0x4, %l2 ! npc = npc+4 stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ba,pt %xcc, rtrap_clr_l6 stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] 1: - /* Really a failure? Check if force_successful_syscall_return() - * was invoked. - */ - ldx [%curptr + TI_FLAGS], %l0 ! Load - andcc %l0, _TIF_SYSCALL_SUCCESS, %g0 - be,pt %icc, 1f - andcc %l0, _TIF_SYSCALL_TRACE, %l6 - andn %l0, _TIF_SYSCALL_SUCCESS, %l0 - ba,pt %xcc, 80b - stx %l0, [%curptr + TI_FLAGS] - /* System call failure, set Carry condition code. * Also, get abs(errno) to return to the process. */ -1: + andcc %l0, _TIF_SYSCALL_TRACE, %l6 sub %g0, %o0, %o0 or %g3, %g2, %g3 stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] mov 1, %l6 stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 - add %l1, 0x4, %l2 !npc = npc+4 + add %l1, 0x4, %l2 ! npc = npc+4 stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] b,pt %xcc, rtrap diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 10c782137d46..909a13aeb1d8 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -327,7 +327,6 @@ EXPORT_SYMBOL(sys_getegid); EXPORT_SYMBOL(sys_getgid); EXPORT_SYMBOL(svr4_getcontext); EXPORT_SYMBOL(svr4_setcontext); -EXPORT_SYMBOL(sys_ioctl); EXPORT_SYMBOL(compat_sys_ioctl); EXPORT_SYMBOL(sparc32_open); EXPORT_SYMBOL(sys_close); diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 2b0d63924000..1fb138482fb7 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -218,4 +218,3 @@ EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL_GPL(flush_tlb_all); #endif -EXPORT_SYMBOL(sys_ioctl); diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 88c103e61ee6..99b633899211 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -1,5 +1,14 @@ menu "Generic Driver Options" +config PREVENT_FIRMWARE_BUILD + bool "Prevent firmware from being built" + default y + help + Say yes to avoid building firmware. Firmware is usually shipped + with the driver, and only when updating the firware a rebuild + should be made. + If unsure say Y here. + config FW_LOADER tristate "Hotplug firmware loading support" depends on HOTPLUG diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 32881024ecfa..6203e02ad5c2 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -817,14 +817,14 @@ EXPORT_SYMBOL(blk_dump_rq_flags); void blk_recount_segments(request_queue_t *q, struct bio *bio) { struct bio_vec *bv, *bvprv = NULL; - int i, nr_phys_segs, nr_hw_segs, seg_size, cluster; + int i, nr_phys_segs, nr_hw_segs, seg_size, hw_seg_size, cluster; int high, highprv = 1; if (unlikely(!bio->bi_io_vec)) return; cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); - seg_size = nr_phys_segs = nr_hw_segs = 0; + hw_seg_size = seg_size = nr_phys_segs = nr_hw_segs = 0; bio_for_each_segment(bv, bio, i) { /* * the trick here is making sure that a high page is never @@ -841,22 +841,35 @@ void blk_recount_segments(request_queue_t *q, struct bio *bio) goto new_segment; if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) goto new_segment; + if (BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) + goto new_hw_segment; seg_size += bv->bv_len; + hw_seg_size += bv->bv_len; bvprv = bv; continue; } new_segment: - if (!BIOVEC_VIRT_MERGEABLE(bvprv, bv)) + if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) && + !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) { + hw_seg_size += bv->bv_len; + } else { new_hw_segment: + if (hw_seg_size > bio->bi_hw_front_size) + bio->bi_hw_front_size = hw_seg_size; + hw_seg_size = BIOVEC_VIRT_START_SIZE(bv) + bv->bv_len; nr_hw_segs++; + } nr_phys_segs++; bvprv = bv; seg_size = bv->bv_len; highprv = high; } - + if (hw_seg_size > bio->bi_hw_back_size) + bio->bi_hw_back_size = hw_seg_size; + if (nr_hw_segs == 1 && hw_seg_size > bio->bi_hw_front_size) + bio->bi_hw_front_size = hw_seg_size; bio->bi_phys_segments = nr_phys_segs; bio->bi_hw_segments = nr_hw_segs; bio->bi_flags |= (1 << BIO_SEG_VALID); @@ -889,22 +902,17 @@ EXPORT_SYMBOL(blk_phys_contig_segment); int blk_hw_contig_segment(request_queue_t *q, struct bio *bio, struct bio *nxt) { - if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER))) - return 0; - - if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt))) + if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) + blk_recount_segments(q, bio); + if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID))) + blk_recount_segments(q, nxt); + if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) || + BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size)) return 0; if (bio->bi_size + nxt->bi_size > q->max_segment_size) return 0; - /* - * bio and nxt are contigous in memory, check if the queue allows - * these two to be merged into one - */ - if (BIO_SEG_BOUNDARY(q, bio, nxt)) - return 1; - - return 0; + return 1; } EXPORT_SYMBOL(blk_hw_contig_segment); @@ -974,7 +982,8 @@ static inline int ll_new_mergeable(request_queue_t *q, if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { req->flags |= REQ_NOMERGE; - q->last_merge = NULL; + if (req == q->last_merge) + q->last_merge = NULL; return 0; } @@ -996,7 +1005,8 @@ static inline int ll_new_hw_segment(request_queue_t *q, if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { req->flags |= REQ_NOMERGE; - q->last_merge = NULL; + if (req == q->last_merge) + q->last_merge = NULL; return 0; } @@ -1012,14 +1022,31 @@ static inline int ll_new_hw_segment(request_queue_t *q, static int ll_back_merge_fn(request_queue_t *q, struct request *req, struct bio *bio) { + int len; + if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) { req->flags |= REQ_NOMERGE; - q->last_merge = NULL; + if (req == q->last_merge) + q->last_merge = NULL; return 0; } - - if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio))) - return ll_new_mergeable(q, req, bio); + if (unlikely(!bio_flagged(req->biotail, BIO_SEG_VALID))) + blk_recount_segments(q, req->biotail); + if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) + blk_recount_segments(q, bio); + len = req->biotail->bi_hw_back_size + bio->bi_hw_front_size; + if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio)) && + !BIOVEC_VIRT_OVERSIZE(len)) { + int mergeable = ll_new_mergeable(q, req, bio); + + if (mergeable) { + if (req->nr_hw_segments == 1) + req->bio->bi_hw_front_size = len; + if (bio->bi_hw_segments == 1) + bio->bi_hw_back_size = len; + } + return mergeable; + } return ll_new_hw_segment(q, req, bio); } @@ -1027,14 +1054,31 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req, static int ll_front_merge_fn(request_queue_t *q, struct request *req, struct bio *bio) { + int len; + if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) { req->flags |= REQ_NOMERGE; - q->last_merge = NULL; + if (req == q->last_merge) + q->last_merge = NULL; return 0; } - - if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio))) - return ll_new_mergeable(q, req, bio); + len = bio->bi_hw_back_size + req->bio->bi_hw_front_size; + if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) + blk_recount_segments(q, bio); + if (unlikely(!bio_flagged(req->bio, BIO_SEG_VALID))) + blk_recount_segments(q, req->bio); + if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)) && + !BIOVEC_VIRT_OVERSIZE(len)) { + int mergeable = ll_new_mergeable(q, req, bio); + + if (mergeable) { + if (bio->bi_hw_segments == 1) + bio->bi_hw_front_size = len; + if (req->nr_hw_segments == 1) + req->biotail->bi_hw_back_size = len; + } + return mergeable; + } return ll_new_hw_segment(q, req, bio); } @@ -1066,8 +1110,17 @@ static int ll_merge_requests_fn(request_queue_t *q, struct request *req, return 0; total_hw_segments = req->nr_hw_segments + next->nr_hw_segments; - if (blk_hw_contig_segment(q, req->biotail, next->bio)) + if (blk_hw_contig_segment(q, req->biotail, next->bio)) { + int len = req->biotail->bi_hw_back_size + next->bio->bi_hw_front_size; + /* + * propagate the combined length to the end of the requests + */ + if (req->nr_hw_segments == 1) + req->bio->bi_hw_front_size = len; + if (next->nr_hw_segments == 1) + next->biotail->bi_hw_back_size = len; total_hw_segments--; + } if (total_hw_segments > q->max_hw_segments) return 0; @@ -2532,7 +2585,7 @@ EXPORT_SYMBOL(process_that_request_first); void blk_recalc_rq_segments(struct request *rq) { - struct bio *bio; + struct bio *bio, *prevbio = NULL; int nr_phys_segs, nr_hw_segs; if (!rq->bio) @@ -2545,6 +2598,13 @@ void blk_recalc_rq_segments(struct request *rq) nr_phys_segs += bio_phys_segments(rq->q, bio); nr_hw_segs += bio_hw_segments(rq->q, bio); + if (prevbio) { + if (blk_phys_contig_segment(rq->q, prevbio, bio)) + nr_phys_segs--; + if (blk_hw_contig_segment(rq->q, prevbio, bio)) + nr_hw_segs--; + } + prevbio = bio; } rq->nr_phys_segments = nr_phys_segs; diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c index 6d66d0b6485b..ff89164bc98a 100644 --- a/drivers/cdrom/isp16.c +++ b/drivers/cdrom/isp16.c @@ -16,6 +16,10 @@ * module_init & module_exit. * Torben Mathiasen <tmm@image.dk> * + * 19 June 2004 -- check_region() converted to request_region() + * and return statement cleanups. + * Jesper Juhl <juhl-lkml@dif.dk> + * * Detect cdrom interface on ISP16 sound card. * Configure cdrom interface. * @@ -118,17 +122,17 @@ int __init isp16_init(void) if (!strcmp(isp16_cdrom_type, "noisp16")) { printk("ISP16: no cdrom interface configured.\n"); - return (0); + return 0; } - if (check_region(ISP16_IO_BASE, ISP16_IO_SIZE)) { + if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) { printk("ISP16: i/o ports already in use.\n"); - return (-EIO); + goto out; } if ((isp16_type = isp16_detect()) < 0) { printk("ISP16: no cdrom interface found.\n"); - return (-EIO); + goto cleanup_out; } printk(KERN_INFO @@ -148,27 +152,32 @@ int __init isp16_init(void) else { printk("ISP16: %s not supported by cdrom interface.\n", isp16_cdrom_type); - return (-EIO); + goto cleanup_out; } if (isp16_cdi_config(isp16_cdrom_base, expected_drive, isp16_cdrom_irq, isp16_cdrom_dma) < 0) { printk ("ISP16: cdrom interface has not been properly configured.\n"); - return (-EIO); + goto cleanup_out; } printk(KERN_INFO "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d," " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq, isp16_cdrom_dma, isp16_cdrom_type); - return (0); + return 0; + +cleanup_out: + release_region(ISP16_IO_BASE, ISP16_IO_SIZE); +out: + return -EIO; } static short __init isp16_detect(void) { if (isp16_c929__detect() >= 0) - return (2); + return 2; else return (isp16_c928__detect()); } @@ -206,7 +215,7 @@ static short __init isp16_c928__detect(void) ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom); } else { /* bits are not the same */ ISP16_OUT(ISP16_CTRL_PORT, ctrl); - return (i); /* -> not detected: possibly incorrect conclusion */ + return i; /* -> not detected: possibly incorrect conclusion */ } } else if (enable_cdrom == 0x20) i = 0; @@ -215,7 +224,7 @@ static short __init isp16_c928__detect(void) ISP16_OUT(ISP16_CTRL_PORT, ctrl); - return (i); + return i; } static short __init isp16_c929__detect(void) @@ -236,12 +245,12 @@ static short __init isp16_c929__detect(void) tmp = ISP16_IN(ISP16_CTRL_PORT); if (tmp != 2) /* isp16 with 82C929 not detected */ - return (-1); + return -1; /* restore ctrl port value */ ISP16_OUT(ISP16_CTRL_PORT, ctrl); - return (2); + return 2; } static short __init @@ -272,7 +281,7 @@ isp16_cdi_config(int base, u_char drive_type, int irq, int dma) printk ("ISP16: base address 0x%03X not supported by cdrom interface.\n", base); - return (-1); + return -1; } switch (irq) { case 0: @@ -303,7 +312,7 @@ isp16_cdi_config(int base, u_char drive_type, int irq, int dma) default: printk("ISP16: irq %d not supported by cdrom interface.\n", irq); - return (-1); + return -1; } switch (dma) { case 0: @@ -312,7 +321,7 @@ isp16_cdi_config(int base, u_char drive_type, int irq, int dma) case 1: printk("ISP16: dma 1 cannot be used by cdrom interface," " due to conflict with the sound card.\n"); - return (-1); + return -1; break; case 3: dma_code = ISP16_DMA_3; @@ -329,7 +338,7 @@ isp16_cdi_config(int base, u_char drive_type, int irq, int dma) default: printk("ISP16: dma %d not supported by cdrom interface.\n", dma); - return (-1); + return -1; } if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 && @@ -339,7 +348,7 @@ isp16_cdi_config(int base, u_char drive_type, int irq, int dma) printk ("ISP16: drive type (code 0x%02X) not supported by cdrom" " interface.\n", drive_type); - return (-1); + return -1; } /* set type of interface */ @@ -354,7 +363,7 @@ isp16_cdi_config(int base, u_char drive_type, int irq, int dma) i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */ ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code); - return (0); + return 0; } void __exit isp16_exit(void) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 2fe8bfab039e..f9b27629baaf 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -753,6 +753,28 @@ config RTC To compile this driver as a module, choose M here: the module will be called rtc. +config SGI_DS1286 + tristate "SGI DS1286 RTC support" + depends on SGI_IP22 + help + If you say Y here and create a character special file /dev/rtc with + major number 10 and minor number 135 using mknod ("man mknod"), you + will get access to the real time clock built into your computer. + Every SGI has such a clock built in. It reports status information + via the file /proc/rtc and its behaviour is set by various ioctls on + /dev/rtc. + +config SGI_IP27_RTC + bool "SGI M48T35 RTC support" + depends on SGI_IP27 + help + If you say Y here and create a character special file /dev/rtc with + major number 10 and minor number 135 using mknod ("man mknod"), you + will get access to the real time clock built into your computer. + Every SGI has such a clock built in. It reports status information + via the file /proc/rtc and its behaviour is set by various ioctls on + /dev/rtc. + config GEN_RTC tristate "Generic /dev/rtc emulation" depends on RTC!=y && !IA64 @@ -782,6 +804,13 @@ config EFI_RTC bool "EFI Real Time Clock Services" depends on IA64 +config COBALT_LCD + bool "Support for Cobalt LCD" + depends on MIPS_COBALT + help + This option enables support for the LCD display and buttons found + on Cobalt systems through a misc device. + config H8 bool "Tadpole ANA H8 Support (OBSOLETE)" depends on OBSOLETE && ALPHA_BOOK1 diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 789890c8c82b..59fd5b583240 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -56,6 +56,8 @@ obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o +obj-$(CONFIG_SGI_DS1286) += ds1286.o +obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o ifeq ($(CONFIG_GENERIC_NVRAM),y) obj-$(CONFIG_NVRAM) += generic_nvram.o else @@ -67,6 +69,7 @@ obj-$(CONFIG_DS1620) += ds1620.o obj-$(CONFIG_HW_RANDOM) += hw_random.o obj-$(CONFIG_QIC02_TAPE) += tpqic02.o obj-$(CONFIG_FTAPE) += ftape/ +obj-$(CONFIG_COBALT_LCD) += lcd.o obj-$(CONFIG_H8) += h8.o obj-$(CONFIG_PPDEV) += ppdev.o obj-$(CONFIG_NWBUTTON) += nwbutton.o diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c new file mode 100644 index 000000000000..bc042fb2d5cd --- /dev/null +++ b/drivers/char/ds1286.c @@ -0,0 +1,578 @@ +/* + * DS1286 Real Time Clock interface for Linux + * + * Copyright (C) 1998, 1999, 2000 Ralf Baechle + * + * Based on code written by Paul Gortmaker. + * + * This driver allows use of the real time clock (built into nearly all + * computers) from user space. It exports the /dev/rtc interface supporting + * various ioctl() and also the /proc/rtc pseudo-file for status + * information. + * + * The ioctls can be used to set the interrupt behaviour and generation rate + * from the RTC via IRQ 8. Then the /dev/rtc interface can be used to make + * use of these timer interrupts, be they interval or alarm based. + * + * The /dev/rtc interface will block on reads until an interrupt has been + * received. If a RTC interrupt has already happened, it will output an + * unsigned long and then block. The output value contains the interrupt + * status in the low byte and the number of interrupts since the last read + * in the remaining high bytes. The /dev/rtc interface can also be used with + * the select(2) call. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/ds1286.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/miscdevice.h> +#include <linux/slab.h> +#include <linux/ioport.h> +#include <linux/fcntl.h> +#include <linux/init.h> +#include <linux/poll.h> +#include <linux/rtc.h> +#include <linux/spinlock.h> +#include <linux/bcd.h> +#include <linux/proc_fs.h> + +#include <asm/uaccess.h> +#include <asm/system.h> + +#define DS1286_VERSION "1.0" + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +static DECLARE_WAIT_QUEUE_HEAD(ds1286_wait); + +static ssize_t ds1286_read(struct file *file, char *buf, + size_t count, loff_t *ppos); + +static int ds1286_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +static unsigned int ds1286_poll(struct file *file, poll_table *wait); + +static void ds1286_get_alm_time (struct rtc_time *alm_tm); +static void ds1286_get_time(struct rtc_time *rtc_tm); +static int ds1286_set_time(struct rtc_time *rtc_tm); + +static inline unsigned char ds1286_is_updating(void); + +static spinlock_t ds1286_lock = SPIN_LOCK_UNLOCKED; + +static int ds1286_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); + +/* + * Bits in rtc_status. (7 bits of room for future expansion) + */ + +#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ +#define RTC_TIMER_ON 0x02 /* missed irq timer active */ + +static unsigned char ds1286_status; /* bitmapped status byte. */ + +static unsigned char days_in_mo[] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +/* + * Now all the various file operations that we export. + */ + +static ssize_t ds1286_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + return -EIO; +} + +static int ds1286_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct rtc_time wtime; + + switch (cmd) { + case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = rtc_read(RTC_CMD); + val |= RTC_TDM; + rtc_write(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_AIE_ON: /* Allow alarm interrupts. */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = rtc_read(RTC_CMD); + val &= ~RTC_TDM; + rtc_write(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_WIE_OFF: /* Mask watchdog int. enab. bit */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = rtc_read(RTC_CMD); + val |= RTC_WAM; + rtc_write(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_WIE_ON: /* Allow watchdog interrupts. */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = rtc_read(RTC_CMD); + val &= ~RTC_WAM; + rtc_write(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_ALM_READ: /* Read the present alarm time */ + { + /* + * This returns a struct rtc_time. Reading >= 0xc0 + * means "don't care" or "match all". Only the tm_hour, + * tm_min, and tm_sec values are filled in. + */ + + memset(&wtime, 0, sizeof(wtime)); + ds1286_get_alm_time(&wtime); + break; + } + case RTC_ALM_SET: /* Store a time into the alarm */ + { + /* + * This expects a struct rtc_time. Writing 0xff means + * "don't care" or "match all". Only the tm_hour, + * tm_min and tm_sec are used. + */ + unsigned char hrs, min, sec; + struct rtc_time alm_tm; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&alm_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + hrs = alm_tm.tm_hour; + min = alm_tm.tm_min; + + if (hrs >= 24) + hrs = 0xff; + + if (min >= 60) + min = 0xff; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + + spin_lock(&ds1286_lock); + rtc_write(hrs, RTC_HOURS_ALARM); + rtc_write(min, RTC_MINUTES_ALARM); + spin_unlock(&ds1286_lock); + + return 0; + } + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + memset(&wtime, 0, sizeof(wtime)); + ds1286_get_time(&wtime); + break; + } + case RTC_SET_TIME: /* Set the RTC */ + { + struct rtc_time rtc_tm; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + return ds1286_set_time(&rtc_tm); + } + default: + return -EINVAL; + } + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int ds1286_open(struct inode *inode, struct file *file) +{ + spin_lock_irq(&ds1286_lock); + + if (ds1286_status & RTC_IS_OPEN) + goto out_busy; + + ds1286_status |= RTC_IS_OPEN; + + spin_unlock_irq(&ds1286_lock); + return 0; + +out_busy: + spin_lock_irq(&ds1286_lock); + return -EBUSY; +} + +static int ds1286_release(struct inode *inode, struct file *file) +{ + ds1286_status &= ~RTC_IS_OPEN; + + return 0; +} + +static unsigned int ds1286_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &ds1286_wait, wait); + + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations ds1286_fops = { + .llseek = no_llseek, + .read = ds1286_read, + .poll = ds1286_poll, + .ioctl = ds1286_ioctl, + .open = ds1286_open, + .release = ds1286_release, +}; + +static struct miscdevice ds1286_dev= +{ + .minor = RTC_MINOR, + .name = "rtc", + .fops = &ds1286_fops, +}; + +static int __init ds1286_init(void) +{ + int err; + + printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION); + + err = misc_register(&ds1286_dev); + if (err) + goto out; + + if (!create_proc_read_entry("driver/rtc", 0, 0, ds1286_read_proc, NULL)) { + err = -ENOMEM; + + goto out_deregister; + } + + return 0; + +out_deregister: + misc_deregister(&ds1286_dev); + +out: + return err; +} + +static void __exit ds1286_exit(void) +{ + remove_proc_entry("driver/rtc", NULL); + misc_deregister(&ds1286_dev); +} + +static char *days[] = { + "***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +/* + * Info exported via "/proc/rtc". + */ +static int ds1286_proc_output(char *buf) +{ + char *p, *s; + struct rtc_time tm; + unsigned char hundredth, month, cmd, amode; + + p = buf; + + ds1286_get_time(&tm); + hundredth = rtc_read(RTC_HUNDREDTH_SECOND); + BCD_TO_BIN(hundredth); + + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d.%02d\n" + "rtc_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, hundredth, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + + /* + * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will + * match any value for that particular field. Values that are + * greater than a valid time, but less than 0xc0 shouldn't appear. + */ + ds1286_get_alm_time(&tm); + p += sprintf(p, "alarm\t\t: %s ", days[tm.tm_wday]); + if (tm.tm_hour <= 24) + p += sprintf(p, "%02d:", tm.tm_hour); + else + p += sprintf(p, "**:"); + + if (tm.tm_min <= 59) + p += sprintf(p, "%02d\n", tm.tm_min); + else + p += sprintf(p, "**\n"); + + month = rtc_read(RTC_MONTH); + p += sprintf(p, + "oscillator\t: %s\n" + "square_wave\t: %s\n", + (month & RTC_EOSC) ? "disabled" : "enabled", + (month & RTC_ESQW) ? "disabled" : "enabled"); + + amode = ((rtc_read(RTC_MINUTES_ALARM) & 0x80) >> 5) | + ((rtc_read(RTC_HOURS_ALARM) & 0x80) >> 6) | + ((rtc_read(RTC_DAY_ALARM) & 0x80) >> 7); + if (amode == 7) s = "each minute"; + else if (amode == 3) s = "minutes match"; + else if (amode == 1) s = "hours and minutes match"; + else if (amode == 0) s = "days, hours and minutes match"; + else s = "invalid"; + p += sprintf(p, "alarm_mode\t: %s\n", s); + + cmd = rtc_read(RTC_CMD); + p += sprintf(p, + "alarm_enable\t: %s\n" + "wdog_alarm\t: %s\n" + "alarm_mask\t: %s\n" + "wdog_alarm_mask\t: %s\n" + "interrupt_mode\t: %s\n" + "INTB_mode\t: %s_active\n" + "interrupt_pins\t: %s\n", + (cmd & RTC_TDF) ? "yes" : "no", + (cmd & RTC_WAF) ? "yes" : "no", + (cmd & RTC_TDM) ? "disabled" : "enabled", + (cmd & RTC_WAM) ? "disabled" : "enabled", + (cmd & RTC_PU_LVL) ? "pulse" : "level", + (cmd & RTC_IBH_LO) ? "low" : "high", + (cmd & RTC_IPSW) ? "unswapped" : "swapped"); + + return p - buf; +} + +static int ds1286_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = ds1286_proc_output (page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) + len = count; + if (len<0) + len = 0; + + return len; +} + +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char ds1286_is_updating(void) +{ + return rtc_read(RTC_CMD) & RTC_TE; +} + + +static void ds1286_get_time(struct rtc_time *rtc_tm) +{ + unsigned char save_control; + unsigned int flags; + unsigned long uip_watchdog = jiffies; + + /* + * read RTC once any update in progress is done. The update + * can take just over 2ms. We wait 10 to 20ms. There is no need to + * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. + * If you need to know *exactly* when a second has started, enable + * periodic update complete interrupts, (via ioctl) and then + * immediately read /dev/rtc which will block until you get the IRQ. + * Once the read clears, read the RTC time (again via ioctl). Easy. + */ + + if (ds1286_is_updating() != 0) + while (jiffies - uip_watchdog < 2*HZ/100) + barrier(); + + /* + * Only the values that we read from the RTC are set. We leave + * tm_wday, tm_yday and tm_isdst untouched. Even though the + * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated + * by the RTC when initially set to a non-zero value. + */ + spin_lock_irqsave(&ds1286_lock, flags); + save_control = rtc_read(RTC_CMD); + rtc_write((save_control|RTC_TE), RTC_CMD); + + rtc_tm->tm_sec = rtc_read(RTC_SECONDS); + rtc_tm->tm_min = rtc_read(RTC_MINUTES); + rtc_tm->tm_hour = rtc_read(RTC_HOURS) & 0x3f; + rtc_tm->tm_mday = rtc_read(RTC_DATE); + rtc_tm->tm_mon = rtc_read(RTC_MONTH) & 0x1f; + rtc_tm->tm_year = rtc_read(RTC_YEAR); + + rtc_write(save_control, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + BCD_TO_BIN(rtc_tm->tm_sec); + BCD_TO_BIN(rtc_tm->tm_min); + BCD_TO_BIN(rtc_tm->tm_hour); + BCD_TO_BIN(rtc_tm->tm_mday); + BCD_TO_BIN(rtc_tm->tm_mon); + BCD_TO_BIN(rtc_tm->tm_year); + + /* + * Account for differences between how the RTC uses the values + * and how they are defined in a struct rtc_time; + */ + if (rtc_tm->tm_year < 45) + rtc_tm->tm_year += 30; + if ((rtc_tm->tm_year += 40) < 70) + rtc_tm->tm_year += 100; + + rtc_tm->tm_mon--; +} + +static int ds1286_set_time(struct rtc_time *rtc_tm) +{ + unsigned char mon, day, hrs, min, sec, leap_yr; + unsigned char save_control; + unsigned int yrs, flags; + + + yrs = rtc_tm->tm_year + 1900; + mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */ + day = rtc_tm->tm_mday; + hrs = rtc_tm->tm_hour; + min = rtc_tm->tm_min; + sec = rtc_tm->tm_sec; + + if (yrs < 1970) + return -EINVAL; + + leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); + + if ((mon > 12) || (day == 0)) + return -EINVAL; + + if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) + return -EINVAL; + + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) + return -EINVAL; + + if ((yrs -= 1940) > 255) /* They are unsigned */ + return -EINVAL; + + if (yrs >= 100) + yrs -= 100; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + BIN_TO_BCD(day); + BIN_TO_BCD(mon); + BIN_TO_BCD(yrs); + + spin_lock_irqsave(&ds1286_lock, flags); + save_control = rtc_read(RTC_CMD); + rtc_write((save_control|RTC_TE), RTC_CMD); + + rtc_write(yrs, RTC_YEAR); + rtc_write(mon, RTC_MONTH); + rtc_write(day, RTC_DATE); + rtc_write(hrs, RTC_HOURS); + rtc_write(min, RTC_MINUTES); + rtc_write(sec, RTC_SECONDS); + rtc_write(0, RTC_HUNDREDTH_SECOND); + + rtc_write(save_control, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; +} + +static void ds1286_get_alm_time(struct rtc_time *alm_tm) +{ + unsigned char cmd; + unsigned int flags; + + /* + * Only the values that we read from the RTC are set. That + * means only tm_wday, tm_hour, tm_min. + */ + spin_lock_irqsave(&ds1286_lock, flags); + alm_tm->tm_min = rtc_read(RTC_MINUTES_ALARM) & 0x7f; + alm_tm->tm_hour = rtc_read(RTC_HOURS_ALARM) & 0x1f; + alm_tm->tm_wday = rtc_read(RTC_DAY_ALARM) & 0x07; + cmd = rtc_read(RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + BCD_TO_BIN(alm_tm->tm_min); + BCD_TO_BIN(alm_tm->tm_hour); + alm_tm->tm_sec = 0; +} + +module_init(ds1286_init); +module_exit(ds1286_exit); + +MODULE_AUTHOR("Ralf Baechle"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(RTC_MINOR); diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c new file mode 100644 index 000000000000..3acdac3c967e --- /dev/null +++ b/drivers/char/ip27-rtc.c @@ -0,0 +1,327 @@ +/* + * Driver for the SGS-Thomson M48T35 Timekeeper RAM chip + * + * Real Time Clock interface for Linux + * + * TODO: Implement periodic interrupts. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Written by Ulf Carlsson (ulfc@engr.sgi.com) + * + * Based on code written by Paul Gortmaker. + * + * This driver allows use of the real time clock (built into + * nearly all computers) from user space. It exports the /dev/rtc + * interface supporting various ioctl() and also the /proc/rtc + * pseudo-file for status information. + * + * 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. + * + */ + +#define RTC_VERSION "1.09b" + +#include <linux/bcd.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/miscdevice.h> +#include <linux/ioport.h> +#include <linux/fcntl.h> +#include <linux/rtc.h> +#include <linux/init.h> +#include <linux/poll.h> +#include <linux/proc_fs.h> +#include <linux/smp_lock.h> + +#include <asm/m48t35.h> +#include <asm/sn/ioc3.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/sn/klconfig.h> +#include <asm/sn/sn0/ip27.h> +#include <asm/sn/sn0/hub.h> +#include <asm/sn/sn_private.h> + +static int rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +static int rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); + +static void get_rtc_time(struct rtc_time *rtc_tm); + +/* + * Bits in rtc_status. (6 bits of room for future expansion) + */ + +#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ +#define RTC_TIMER_ON 0x02 /* missed irq timer active */ + +static unsigned char rtc_status; /* bitmapped status byte. */ +static unsigned long rtc_freq; /* Current periodic IRQ rate */ +static struct m48t35_rtc *rtc; + +/* + * If this driver ever becomes modularised, it will be really nice + * to make the epoch retain its value across module reload... + */ + +static unsigned long epoch = 1970; /* year corresponding to 0x00 */ + +static const unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + + struct rtc_time wtime; + + switch (cmd) { + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + get_rtc_time(&wtime); + break; + } + case RTC_SET_TIME: /* Set the RTC */ + { + struct rtc_time rtc_tm; + unsigned char mon, day, hrs, min, sec, leap_yr; + unsigned int yrs; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + yrs = rtc_tm.tm_year + 1900; + mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ + day = rtc_tm.tm_mday; + hrs = rtc_tm.tm_hour; + min = rtc_tm.tm_min; + sec = rtc_tm.tm_sec; + + if (yrs < 1970) + return -EINVAL; + + leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); + + if ((mon > 12) || (day == 0)) + return -EINVAL; + + if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) + return -EINVAL; + + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) + return -EINVAL; + + if ((yrs -= epoch) > 255) /* They are unsigned */ + return -EINVAL; + + if (yrs > 169) + return -EINVAL; + + if (yrs >= 100) + yrs -= 100; + + sec = BIN2BCD(sec); + min = BIN2BCD(min); + hrs = BIN2BCD(hrs); + day = BIN2BCD(day); + mon = BIN2BCD(mon); + yrs = BIN2BCD(yrs); + + spin_lock_irq(&rtc_lock); + rtc->control |= M48T35_RTC_SET; + rtc->year = yrs; + rtc->month = mon; + rtc->date = day; + rtc->hour = hrs; + rtc->min = min; + rtc->sec = sec; + rtc->control &= ~M48T35_RTC_SET; + spin_unlock_irq(&rtc_lock); + + return 0; + } + default: + return -EINVAL; + } + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int rtc_open(struct inode *inode, struct file *file) +{ + spin_lock_irq(&rtc_lock); + + if (rtc_status & RTC_IS_OPEN) { + spin_unlock_irq(&rtc_lock); + return -EBUSY; + } + + rtc_status |= RTC_IS_OPEN; + spin_unlock_irq(&rtc_lock); + + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + /* + * Turn off all interrupts once the device is no longer + * in use, and clear the data. + */ + + spin_lock_irq(&rtc_lock); + rtc_status &= ~RTC_IS_OPEN; + spin_unlock_irq(&rtc_lock); + + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations rtc_fops = { + .owner = THIS_MODULE, + .ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, +}; + +static struct miscdevice rtc_dev= +{ + RTC_MINOR, + "rtc", + &rtc_fops +}; + +static int __init rtc_init(void) +{ + rtc = (struct m48t35_rtc *) + (KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + IOC3_BYTEBUS_DEV0); + + printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION); + if (misc_register(&rtc_dev)) { + printk(KERN_ERR "rtc: cannot register misc device.\n"); + return -ENODEV; + } + if (!create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL)) { + printk(KERN_ERR "rtc: cannot create /proc/rtc.\n"); + misc_deregister(&rtc_dev); + return -ENOENT; + } + + rtc_freq = 1024; + + return 0; +} + +static void __exit rtc_exit (void) +{ + /* interrupts and timer disabled at this point by rtc_release */ + + remove_proc_entry ("rtc", NULL); + misc_deregister(&rtc_dev); +} + +module_init(rtc_init); +module_exit(rtc_exit); + +/* + * Info exported via "/proc/rtc". + */ + +static int rtc_get_status(char *buf) +{ + char *p; + struct rtc_time tm; + + /* + * Just emulate the standard /proc/rtc + */ + + p = buf; + + get_rtc_time(&tm); + + /* + * There is no way to tell if the luser has the RTC set for local + * time or for Universal Standard Time (GMT). Probably local though. + */ + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04lu\n" + "24hr\t\t: yes\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); + + return p - buf; +} + +static int rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = rtc_get_status(page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + +static void get_rtc_time(struct rtc_time *rtc_tm) +{ + /* + * Do we need to wait for the last update to finish? + */ + + /* + * Only the values that we read from the RTC are set. We leave + * tm_wday, tm_yday and tm_isdst untouched. Even though the + * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated + * by the RTC when initially set to a non-zero value. + */ + spin_lock_irq(&rtc_lock); + rtc->control |= M48T35_RTC_READ; + rtc_tm->tm_sec = rtc->sec; + rtc_tm->tm_min = rtc->min; + rtc_tm->tm_hour = rtc->hour; + rtc_tm->tm_mday = rtc->date; + rtc_tm->tm_mon = rtc->month; + rtc_tm->tm_year = rtc->year; + rtc->control &= ~M48T35_RTC_READ; + spin_unlock_irq(&rtc_lock); + + rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec); + rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min); + rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour); + rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday); + rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon); + rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year); + + /* + * Account for differences between how the RTC uses the values + * and how they are defined in a struct rtc_time; + */ + if ((rtc_tm->tm_year += (epoch - 1900)) <= 69) + rtc_tm->tm_year += 100; + + rtc_tm->tm_mon--; +} diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c index 41f2d4e41751..64837783d180 100644 --- a/drivers/char/lcd.c +++ b/drivers/char/lcd.c @@ -12,7 +12,7 @@ * */ -#define RTC_IO_EXTENT 0x10 /*Only really two ports, but... */ +#define RTC_IO_EXTENT 0x10 /*Only really two ports, but... */ #include <linux/config.h> #include <linux/types.h> @@ -32,8 +32,8 @@ #include "lcd.h" -static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg); +static int lcd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); static int lcd_present = 1; @@ -57,8 +57,8 @@ int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie) } #endif -static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static int lcd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { struct lcd_display button_display; unsigned long address, a; @@ -69,7 +69,7 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, udelay(150); BusyCheck(); LCDWriteInst(0x0F); - break; + break; case LCD_Off: udelay(150); @@ -95,7 +95,7 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case LCD_Clear: udelay(150); BusyCheck(); - LCDWriteInst(0x01); + LCDWriteInst(0x01); break; case LCD_Cursor_Left: @@ -108,86 +108,95 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, udelay(150); BusyCheck(); LCDWriteInst(0x14); - break; + break; case LCD_Cursor_Off: udelay(150); - BusyCheck(); - LCDWriteInst(0x0C); - break; - - case LCD_Cursor_On: - udelay(150); - BusyCheck(); - LCDWriteInst(0x0F); - break; - - case LCD_Blink_Off: - udelay(150); - BusyCheck(); - LCDWriteInst(0x0E); - break; - - case LCD_Get_Cursor_Pos:{ - struct lcd_display display; + BusyCheck(); + LCDWriteInst(0x0C); + break; + case LCD_Cursor_On: udelay(150); - BusyCheck(); - display.cursor_address = ( LCDReadInst ); - display.cursor_address = ( display.cursor_address & 0x07F ); - if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display))) - return -EFAULT; + BusyCheck(); + LCDWriteInst(0x0F); + break; + case LCD_Blink_Off: + udelay(150); + BusyCheck(); + LCDWriteInst(0x0E); break; + + case LCD_Get_Cursor_Pos:{ + struct lcd_display display; + + udelay(150); + BusyCheck(); + display.cursor_address = (LCDReadInst); + display.cursor_address = + (display.cursor_address & 0x07F); + if (copy_to_user + ((struct lcd_display *) arg, &display, + sizeof(struct lcd_display))) + return -EFAULT; + + break; } - case LCD_Set_Cursor_Pos: { - struct lcd_display display; + case LCD_Set_Cursor_Pos:{ + struct lcd_display display; - if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) - return -EFAULT; + if (copy_from_user + (&display, (struct lcd_display *) arg, + sizeof(struct lcd_display))) + return -EFAULT; - a = (display.cursor_address | kLCD_Addr ); + a = (display.cursor_address | kLCD_Addr); - udelay(150); - BusyCheck(); - LCDWriteInst( a ); + udelay(150); + BusyCheck(); + LCDWriteInst(a); - break; + break; } - - case LCD_Get_Cursor: { - struct lcd_display display; - udelay(150); - BusyCheck(); - display.character = LCDReadData; + case LCD_Get_Cursor:{ + struct lcd_display display; - if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display))) - return -EFAULT; - udelay(150); - BusyCheck(); - LCDWriteInst(0x10); + udelay(150); + BusyCheck(); + display.character = LCDReadData; - break; + if (copy_to_user + ((struct lcd_display *) arg, &display, + sizeof(struct lcd_display))) + return -EFAULT; + udelay(150); + BusyCheck(); + LCDWriteInst(0x10); + + break; } case LCD_Set_Cursor:{ - struct lcd_display display; - - if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) - return -EFAULT; + struct lcd_display display; - udelay(150); - BusyCheck(); - LCDWriteData( display.character ); - udelay(150); - BusyCheck(); - LCDWriteInst(0x10); + if (copy_from_user + (&display, (struct lcd_display *) arg, + sizeof(struct lcd_display))) + return -EFAULT; - break; - } + udelay(150); + BusyCheck(); + LCDWriteData(display.character); + udelay(150); + BusyCheck(); + LCDWriteInst(0x10); + + break; + } case LCD_Disp_Left: @@ -208,294 +217,330 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, LCDWriteInst(0x02); break; - case LCD_Write: { - struct lcd_display display; - + case LCD_Write:{ + struct lcd_display display; + + + if (copy_from_user + (&display, (struct lcd_display *) arg, + sizeof(struct lcd_display))) + return -EFAULT; - if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) - return -EFAULT; - - udelay(150); - BusyCheck(); - LCDWriteInst(0x80); - udelay(150); - BusyCheck(); - - for (index = 0; index < (display.size1); index++) { udelay(150); - BusyCheck(); - LCDWriteData( display.line1[index]); - BusyCheck(); - } - - udelay(150); - BusyCheck(); - LCDWriteInst(0xC0); - udelay(150); - BusyCheck(); - for (index = 0; index < (display.size2); index++) { - udelay(150); - BusyCheck(); - LCDWriteData( display.line2[index]); - } - - break; - } - - case LCD_Read: { - struct lcd_display display; + BusyCheck(); + LCDWriteInst(0x80); + udelay(150); + BusyCheck(); - BusyCheck(); - for (address = kDD_R00; address <= kDD_R01; address++) { - a = (address | kLCD_Addr ); + for (index = 0; index < (display.size1); index++) { + udelay(150); + BusyCheck(); + LCDWriteData(display.line1[index]); + BusyCheck(); + } udelay(150); BusyCheck(); - LCDWriteInst( a ); + LCDWriteInst(0xC0); udelay(150); BusyCheck(); - display.line1[address] = LCDReadData; + for (index = 0; index < (display.size2); index++) { + udelay(150); + BusyCheck(); + LCDWriteData(display.line2[index]); + } + + break; } - display.line1[ 0x27 ] = '\0'; - - for (address = kDD_R10; address <= kDD_R11; address++) { - a = (address | kLCD_Addr ); - - udelay(150); - BusyCheck(); - LCDWriteInst( a ); - - udelay(150); - BusyCheck(); - display.line2[address - 0x40 ] = LCDReadData; - } - - display.line2[ 0x27 ] = '\0'; - - if(copy_to_user((struct lcd_display*)arg, &display, - sizeof(struct lcd_display))) - return -EFAULT; - break; - } + case LCD_Read:{ + struct lcd_display display; -// set all GPIO leds to led_display.leds + BusyCheck(); + for (address = kDD_R00; address <= kDD_R01; + address++) { + a = (address | kLCD_Addr); + + udelay(150); + BusyCheck(); + LCDWriteInst(a); + udelay(150); + BusyCheck(); + display.line1[address] = LCDReadData; + } - case LED_Set: { - struct lcd_display led_display; - + display.line1[0x27] = '\0'; - if(copy_from_user(&led_display, (struct lcd_display*)arg, - sizeof(struct lcd_display))) - return -EFAULT; + for (address = kDD_R10; address <= kDD_R11; + address++) { + a = (address | kLCD_Addr); - led_state = led_display.leds; - LEDSet(led_state); + udelay(150); + BusyCheck(); + LCDWriteInst(a); + + udelay(150); + BusyCheck(); + display.line2[address - 0x40] = + LCDReadData; + } + + display.line2[0x27] = '\0'; + + if (copy_to_user + ((struct lcd_display *) arg, &display, + sizeof(struct lcd_display))) + return -EFAULT; + break; + } + +// set all GPIO leds to led_display.leds + + case LED_Set:{ + struct lcd_display led_display; - break; - } + + if (copy_from_user + (&led_display, (struct lcd_display *) arg, + sizeof(struct lcd_display))) + return -EFAULT; + + led_state = led_display.leds; + LEDSet(led_state); + + break; + } // set only bit led_display.leds - case LED_Bit_Set: { - int i; - int bit=1; - struct lcd_display led_display; + case LED_Bit_Set:{ + int i; + int bit = 1; + struct lcd_display led_display; - if(copy_from_user(&led_display, (struct lcd_display*)arg, - sizeof(struct lcd_display))) - return -EFAULT; + if (copy_from_user + (&led_display, (struct lcd_display *) arg, + sizeof(struct lcd_display))) + return -EFAULT; - for (i=0;i<(int)led_display.leds;i++) - { - bit = 2*bit; + for (i = 0; i < (int) led_display.leds; i++) { + bit = 2 * bit; } - led_state = led_state | bit; - LEDSet(led_state); - break; - } + led_state = led_state | bit; + LEDSet(led_state); + break; + } // clear only bit led_display.leds - case LED_Bit_Clear: { - int i; - int bit=1; - struct lcd_display led_display; + case LED_Bit_Clear:{ + int i; + int bit = 1; + struct lcd_display led_display; - if(copy_from_user(&led_display, (struct lcd_display*)arg, - sizeof(struct lcd_display))) - return -EFAULT; + if (copy_from_user + (&led_display, (struct lcd_display *) arg, + sizeof(struct lcd_display))) + return -EFAULT; - for (i=0;i<(int)led_display.leds;i++) - { - bit = 2*bit; - } + for (i = 0; i < (int) led_display.leds; i++) { + bit = 2 * bit; + } - led_state = led_state & ~bit; - LEDSet(led_state); - break; - } + led_state = led_state & ~bit; + LEDSet(led_state); + break; + } - case BUTTON_Read: { - button_display.buttons = GPIRead; - if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) - return -EFAULT; - break; - } + case BUTTON_Read:{ + button_display.buttons = GPIRead; + if (copy_to_user + ((struct lcd_display *) arg, &button_display, + sizeof(struct lcd_display))) + return -EFAULT; + break; + } - case LINK_Check: { - button_display.buttons = *((volatile unsigned long *) (0xB0100060) ); - if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) - return -EFAULT; - break; - } - - case LINK_Check_2: { - int iface_num; - - /* panel-utils should pass in the desired interface status is wanted for - * in "buttons" of the structure. We will set this to non-zero if the - * link is in fact up for the requested interface. --DaveM - */ - if(copy_from_user(&button_display, (struct lcd_display *)arg, sizeof(button_display))) - return -EFAULT; - iface_num = button_display.buttons; -#if defined(CONFIG_TULIP) && 0 - if (iface_num >= 0 && - iface_num < MAX_INTERFACES && - linkcheck_callbacks[iface_num] != NULL) { + case LINK_Check:{ button_display.buttons = - linkcheck_callbacks[iface_num](linkcheck_cookies[iface_num]); - } else + *((volatile unsigned long *) (0xB0100060)); + if (copy_to_user + ((struct lcd_display *) arg, &button_display, + sizeof(struct lcd_display))) + return -EFAULT; + break; + } + + case LINK_Check_2:{ + int iface_num; + + /* panel-utils should pass in the desired interface status is wanted for + * in "buttons" of the structure. We will set this to non-zero if the + * link is in fact up for the requested interface. --DaveM + */ + if (copy_from_user + (&button_display, (struct lcd_display *) arg, + sizeof(button_display))) + return -EFAULT; + iface_num = button_display.buttons; +#if defined(CONFIG_TULIP) && 0 + if (iface_num >= 0 && + iface_num < MAX_INTERFACES && + linkcheck_callbacks[iface_num] != NULL) { + button_display.buttons = + linkcheck_callbacks[iface_num] + (linkcheck_cookies[iface_num]); + } else #endif - button_display.buttons = 0; + button_display.buttons = 0; - if(__copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) - return -EFAULT; - break; - } + if (__copy_to_user + ((struct lcd_display *) arg, &button_display, + sizeof(struct lcd_display))) + return -EFAULT; + break; + } // Erase the flash - case FLASH_Erase: { + case FLASH_Erase:{ - int ctr=0; + int ctr = 0; - // Chip Erase Sequence - WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); - WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); - WRITE_FLASH( kFlash_Addr1, kFlash_Erase3 ); - WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); - WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); - WRITE_FLASH( kFlash_Addr1, kFlash_Erase6 ); + // Chip Erase Sequence + WRITE_FLASH(kFlash_Addr1, kFlash_Data1); + WRITE_FLASH(kFlash_Addr2, kFlash_Data2); + WRITE_FLASH(kFlash_Addr1, kFlash_Erase3); + WRITE_FLASH(kFlash_Addr1, kFlash_Data1); + WRITE_FLASH(kFlash_Addr2, kFlash_Data2); + WRITE_FLASH(kFlash_Addr1, kFlash_Erase6); - printk( "Erasing Flash.\n"); + printk("Erasing Flash.\n"); - while ( (!dqpoll(0x00000000,0xFF)) && (!timeout(0x00000000)) ) { - ctr++; - } + while ((!dqpoll(0x00000000, 0xFF)) + && (!timeout(0x00000000))) { + ctr++; + } - printk("\n"); - printk("\n"); - printk("\n"); + printk("\n"); + printk("\n"); + printk("\n"); - if (READ_FLASH(0x07FFF0)==0xFF) { printk("Erase Successful\r\n"); } - else if (timeout) { printk("Erase Timed Out\r\n"); } + if (READ_FLASH(0x07FFF0) == 0xFF) { + printk("Erase Successful\r\n"); + } else if (timeout) { + printk("Erase Timed Out\r\n"); + } - break; - } + break; + } -// burn the flash - - case FLASH_Burn: { - - volatile unsigned long burn_addr; - unsigned long flags; - int i; - unsigned char *rom; - - - struct lcd_display display; - - if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) - return -EFAULT; - rom = (unsigned char *) kmalloc((128),GFP_ATOMIC); - if ( rom == NULL ) { - printk ("broken\n"); - return 1; - } - - printk("Churning and Burning -"); - save_flags(flags); - for (i=0; i<FLASH_SIZE; i=i+128) { - - if(copy_from_user(rom, display.RomImage + i, 128)) - return -EFAULT; - burn_addr = kFlashBase + i; - cli(); - for ( index = 0; index < ( 128 ) ; index++ ) - { - - WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); - WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); - WRITE_FLASH( kFlash_Addr1, kFlash_Prog ); - *((volatile unsigned char *)burn_addr) = (volatile unsigned char) rom[index]; - - while ( (!dqpoll(burn_addr,(volatile unsigned char) rom[index])) && (!timeout(burn_addr)) ) { - } - burn_addr++; - } - restore_flags(flags); - if ( *((volatile unsigned char *)(burn_addr-1)) == (volatile unsigned char) rom[index-1] ) { - } else if (timeout) { - printk("Program timed out\r\n"); - } +// burn the flash + case FLASH_Burn:{ - } - kfree(rom); + volatile unsigned long burn_addr; + unsigned long flags; + int i; + unsigned char *rom; - break; - } -// read the flash all at once - - case FLASH_Read: { + struct lcd_display display; - unsigned char *user_bytes; - volatile unsigned long read_addr; - int i; + if (copy_from_user + (&display, (struct lcd_display *) arg, + sizeof(struct lcd_display))) + return -EFAULT; + rom = (unsigned char *) kmalloc((128), GFP_ATOMIC); + if (rom == NULL) { + printk("broken\n"); + return 1; + } - user_bytes = &(((struct lcd_display *)arg)->RomImage[0]); + printk("Churning and Burning -"); + save_flags(flags); + for (i = 0; i < FLASH_SIZE; i = i + 128) { + + if (copy_from_user + (rom, display.RomImage + i, 128)) + return -EFAULT; + burn_addr = kFlashBase + i; + cli(); + for (index = 0; index < (128); index++) { + + WRITE_FLASH(kFlash_Addr1, + kFlash_Data1); + WRITE_FLASH(kFlash_Addr2, + kFlash_Data2); + WRITE_FLASH(kFlash_Addr1, + kFlash_Prog); + *((volatile unsigned char *) + burn_addr) = + (volatile unsigned char) rom[index]; + + while ((!dqpoll + (burn_addr, + (volatile unsigned char) + rom[index])) + && (!timeout(burn_addr))) { + } + burn_addr++; + } + restore_flags(flags); + if (* + ((volatile unsigned char *) (burn_addr + - 1)) == + (volatile unsigned char) rom[index - + 1]) { + } else if (timeout) { + printk("Program timed out\r\n"); + } - if(!access_ok(VERIFY_WRITE, user_bytes, FLASH_SIZE)) - return -EFAULT; - printk("Reading Flash"); - for (i=0; i<FLASH_SIZE; i++) { - unsigned char tmp_byte; - read_addr = kFlashBase + i; - tmp_byte = *((volatile unsigned char *)read_addr); - if(__put_user (tmp_byte, &user_bytes[i])) - return -EFAULT; + } + kfree(rom); + + break; } +// read the flash all at once - break; - } + case FLASH_Read:{ + unsigned char *user_bytes; + volatile unsigned long read_addr; + int i; + user_bytes = + &(((struct lcd_display *) arg)->RomImage[0]); + if (!access_ok + (VERIFY_WRITE, user_bytes, FLASH_SIZE)) + return -EFAULT; + printk("Reading Flash"); + for (i = 0; i < FLASH_SIZE; i++) { + unsigned char tmp_byte; + read_addr = kFlashBase + i; + tmp_byte = + *((volatile unsigned char *) + read_addr); + if (__put_user(tmp_byte, &user_bytes[i])) + return -EFAULT; + } + + + break; + } default: return 0; - break; + break; } @@ -517,7 +562,8 @@ static inline int button_pressed(void) { unsigned long buttons = GPIRead; - if ( (buttons == BUTTON_Next) || (buttons == BUTTON_Next_B) || (buttons == BUTTON_Reset_B) ) + if ((buttons == BUTTON_Next) || (buttons == BUTTON_Next_B) + || (buttons == BUTTON_Reset_B)) return buttons; return 0; } @@ -526,22 +572,23 @@ static inline int button_pressed(void) static int lcd_waiters = 0; -static long lcd_read(struct inode *inode, struct file *file, char *buf, unsigned long count) +static long lcd_read(struct inode *inode, struct file *file, char *buf, + unsigned long count) { long buttons_now; - if(lcd_waiters > 0) + if (lcd_waiters > 0) return -EINVAL; lcd_waiters++; - while(((buttons_now = (long)button_pressed()) == 0) && - !(signal_pending(current))) { + while (((buttons_now = (long) button_pressed()) == 0) && + !(signal_pending(current))) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(2 * HZ); } lcd_waiters--; - if(signal_pending(current)) + if (signal_pending(current)) return -ERESTARTSYS; return buttons_now; } @@ -551,21 +598,20 @@ static long lcd_read(struct inode *inode, struct file *file, char *buf, unsigned */ static struct file_operations lcd_fops = { - .read = lcd_read, - .ioctl = lcd_ioctl, - .open = lcd_open, + .read = lcd_read, + .ioctl = lcd_ioctl, + .open = lcd_open, }; -static struct miscdevice lcd_dev= -{ - LCD_MINOR, +static struct miscdevice lcd_dev = { + MISC_DYNAMIC_MINOR, "lcd", &lcd_fops }; -int lcd_init(void) +static int lcd_init(void) { -unsigned long data; + unsigned long data; printk("%s\n", LCD_DRIVER); misc_register(&lcd_dev); @@ -575,19 +621,22 @@ unsigned long data; udelay(150); data = LCDReadData; - if ( (data & 0x000000FF) == (0x00) ) { + if ((data & 0x000000FF) == (0x00)) { lcd_present = 0; printk("LCD Not Present\n"); - } - else { + } else { lcd_present = 1; - WRITE_GAL( kGal_DevBank2PReg, kGal_DevBank2Cfg ); - WRITE_GAL( kGal_DevBank3PReg, kGal_DevBank3Cfg ); - } + WRITE_GAL(kGal_DevBank2PReg, kGal_DevBank2Cfg); + WRITE_GAL(kGal_DevBank3PReg, kGal_DevBank3Cfg); + } return 0; } +static void __exit lcd_exit(void) +{ + misc_deregister(&lcd_dev); +} // // Function: dqpoll @@ -600,17 +649,15 @@ unsigned long data; // // -int dqpoll( volatile unsigned long address, volatile unsigned char data ) { - -volatile unsigned char dq7; - -dq7 = data & 0x80; +static int dqpoll(volatile unsigned long address, volatile unsigned char data) +{ + volatile unsigned char dq7; -return ( (READ_FLASH(address) & 0x80) == dq7 ); + dq7 = data & 0x80; + return ((READ_FLASH(address) & 0x80) == dq7); } - // // Function: timeout // @@ -622,12 +669,13 @@ return ( (READ_FLASH(address) & 0x80) == dq7 ); // // Out: 0 = not timed out, 1 = timed out -int timeout( volatile unsigned long address ) { - - -return ( (READ_FLASH(address) & 0x20) == 0x20 ); - +static int timeout(volatile unsigned long address) +{ + return (READ_FLASH(address) & 0x20) == 0x20; } +module_init(lcd_init); +module_exit(lcd_exit); - +MODULE_AUTHOR("Andrew Bose"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h new file mode 100644 index 000000000000..8aed49850573 --- /dev/null +++ b/drivers/char/lcd.h @@ -0,0 +1,184 @@ +/* + * LED, LCD and Button panel driver for Cobalt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997 by Andrew Bose + * + * Linux kernel version history: + * March 2001: Ported from 2.0.34 by Liam Davies + * + */ + +// function headers + +static int dqpoll(volatile unsigned long, volatile unsigned char ); +static int timeout(volatile unsigned long); + +#define LCD_CHARS_PER_LINE 40 +#define FLASH_SIZE 524288 +#define MAX_IDLE_TIME 120 + +struct lcd_display { + unsigned long buttons; + int size1; + int size2; + unsigned char line1[LCD_CHARS_PER_LINE]; + unsigned char line2[LCD_CHARS_PER_LINE]; + unsigned char cursor_address; + unsigned char character; + unsigned char leds; + unsigned char *RomImage; +}; + + + +#define LCD_DRIVER "Cobalt LCD Driver v2.10" + +#define kLCD_IR 0x0F000000 +#define kLCD_DR 0x0F000010 +#define kGPI 0x0D000000 +#define kLED 0x0C000000 + +#define kDD_R00 0x00 +#define kDD_R01 0x27 +#define kDD_R10 0x40 +#define kDD_R11 0x67 + +#define kLCD_Addr 0x00000080 + +#define LCDTimeoutValue 0xfff + + +// Flash definitions AMD 29F040 +#define kFlashBase 0x0FC00000 + +#define kFlash_Addr1 0x5555 +#define kFlash_Addr2 0x2AAA +#define kFlash_Data1 0xAA +#define kFlash_Data2 0x55 +#define kFlash_Prog 0xA0 +#define kFlash_Erase3 0x80 +#define kFlash_Erase6 0x10 +#define kFlash_Read 0xF0 + +#define kFlash_ID 0x90 +#define kFlash_VenAddr 0x00 +#define kFlash_DevAddr 0x01 +#define kFlash_VenID 0x01 +#define kFlash_DevID 0xA4 // 29F040 +//#define kFlash_DevID 0xAD // 29F016 + + +// Macros + +#define LCDWriteData(x) outl((x << 24), kLCD_DR) +#define LCDWriteInst(x) outl((x << 24), kLCD_IR) + +#define LCDReadData (inl(kLCD_DR) >> 24) +#define LCDReadInst (inl(kLCD_IR) >> 24) + +#define GPIRead (inl(kGPI) >> 24) + +#define LEDSet(x) outb((char)x, kLED) + +#define WRITE_GAL(x,y) outl(y, 0x04000000 | (x)) +#define BusyCheck() while ((LCDReadInst & 0x80) == 0x80) + +#define WRITE_FLASH(x,y) outb((char)y, kFlashBase | (x)) +#define READ_FLASH(x) (inb(kFlashBase | (x))) + + + +/* + * Function command codes for io_ctl. + */ +#define LCD_On 1 +#define LCD_Off 2 +#define LCD_Clear 3 +#define LCD_Reset 4 +#define LCD_Cursor_Left 5 +#define LCD_Cursor_Right 6 +#define LCD_Disp_Left 7 +#define LCD_Disp_Right 8 +#define LCD_Get_Cursor 9 +#define LCD_Set_Cursor 10 +#define LCD_Home 11 +#define LCD_Read 12 +#define LCD_Write 13 +#define LCD_Cursor_Off 14 +#define LCD_Cursor_On 15 +#define LCD_Get_Cursor_Pos 16 +#define LCD_Set_Cursor_Pos 17 +#define LCD_Blink_Off 18 + +#define LED_Set 40 +#define LED_Bit_Set 41 +#define LED_Bit_Clear 42 + + +// Button defs +#define BUTTON_Read 50 + +// Flash command codes +#define FLASH_Erase 60 +#define FLASH_Burn 61 +#define FLASH_Read 62 + + +// Ethernet LINK check hackaroo +#define LINK_Check 90 +#define LINK_Check_2 91 + +// Button patterns _B - single layer lcd boards + +#define BUTTON_NONE 0x3F +#define BUTTON_NONE_B 0xFE + +#define BUTTON_Left 0x3B +#define BUTTON_Left_B 0xFA + +#define BUTTON_Right 0x37 +#define BUTTON_Right_B 0xDE + +#define BUTTON_Up 0x2F +#define BUTTON_Up_B 0xF6 + +#define BUTTON_Down 0x1F +#define BUTTON_Down_B 0xEE + +#define BUTTON_Next 0x3D +#define BUTTON_Next_B 0x7E + +#define BUTTON_Enter 0x3E +#define BUTTON_Enter_B 0xBE + +#define BUTTON_Reset_B 0xFC + + +// debounce constants + +#define BUTTON_SENSE 160000 +#define BUTTON_DEBOUNCE 5000 + + +// Galileo register stuff + +#define kGal_DevBank2Cfg 0x1466DB33 +#define kGal_DevBank2PReg 0x464 +#define kGal_DevBank3Cfg 0x146FDFFB +#define kGal_DevBank3PReg 0x468 + +// Network + +#define kIPADDR 1 +#define kNETMASK 2 +#define kGATEWAY 3 +#define kDNS 4 + +#define kClassA 5 +#define kClassB 6 +#define kClassC 7 + diff --git a/drivers/char/misc.c b/drivers/char/misc.c index a878d99f89bd..13b11270a9f2 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -63,13 +63,8 @@ static DECLARE_MUTEX(misc_sem); #define DYNAMIC_MINORS 64 /* like dynamic majors */ static unsigned char misc_minors[DYNAMIC_MINORS / 8]; -#ifdef CONFIG_SGI_NEWPORT_GFX -extern void gfx_register(void); -#endif -extern void streamable_init(void); extern int rtc_DP8570A_init(void); extern int rtc_MK48T08_init(void); -extern int ds1286_init(void); extern int pmu_device_init(void); extern int tosh_init(void); extern int i8k_init(void); @@ -318,21 +313,9 @@ static int __init misc_init(void) #ifdef CONFIG_BVME6000 rtc_DP8570A_init(); #endif -#ifdef CONFIG_SGI_DS1286 - ds1286_init(); -#endif #ifdef CONFIG_PMAC_PBOOK pmu_device_init(); #endif -#ifdef CONFIG_SGI_NEWPORT_GFX - gfx_register (); -#endif -#ifdef CONFIG_SGI_IP22 - streamable_init (); -#endif -#ifdef CONFIG_SGI_NEWPORT_GFX - gfx_register (); -#endif #ifdef CONFIG_TOSHIBA tosh_init(); #endif diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c index 192eacb0c848..ca204da3257d 100644 --- a/drivers/isdn/sc/message.c +++ b/drivers/isdn/sc/message.c @@ -30,7 +30,6 @@ extern unsigned int cinst; */ extern int indicate_status(int,ulong,char*); extern int scm_command(isdn_ctrl *); -extern void *memcpy_fromshmem(int, void *, const void *, size_t); /* diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c index 4190851fe802..8e3fac3ba1a1 100644 --- a/drivers/isdn/sc/packet.c +++ b/drivers/isdn/sc/packet.c @@ -25,8 +25,8 @@ extern unsigned int cinst; extern int get_card_from_id(int); extern int indicate_status(int, int,ulong, char*); -extern void *memcpy_toshmem(int, void *, const void *, size_t); -extern void *memcpy_fromshmem(int, void *, const void *, size_t); +extern void memcpy_toshmem(int, void *, const void *, size_t); +extern void memcpy_fromshmem(int, void *, const void *, size_t); extern int sendmessage(int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int *); diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c index 55493e0ec26f..7bc2dfad0775 100644 --- a/drivers/isdn/sc/shmem.c +++ b/drivers/isdn/sc/shmem.c @@ -30,19 +30,18 @@ extern int cinst; /* * */ -void *memcpy_toshmem(int card, void *dest, const void *src, size_t n) +void memcpy_toshmem(int card, void *dest, const void *src, size_t n) { unsigned long flags; - void *ret; unsigned char ch; if(!IS_VALID_CARD(card)) { pr_debug("Invalid param: %d is not a valid card id\n", card); - return NULL; + return; } if(n > SRAM_PAGESIZE) { - return NULL; + return; } /* @@ -57,7 +56,7 @@ void *memcpy_toshmem(int card, void *dest, const void *src, size_t n) outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); - ret = memcpy_toio(sc_adapter[card]->rambase + + memcpy_toio(sc_adapter[card]->rambase + ((unsigned long) dest % 0x4000), src, n); spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, @@ -66,26 +65,23 @@ void *memcpy_toshmem(int card, void *dest, const void *src, size_t n) sc_adapter[card]->devicename, n, (unsigned long) src, sc_adapter[card]->rambase + ((unsigned long) dest %0x4000)); - - return ret; } /* * Reverse of above */ -void *memcpy_fromshmem(int card, void *dest, const void *src, size_t n) +void memcpy_fromshmem(int card, void *dest, const void *src, size_t n) { unsigned long flags; - void *ret; unsigned char ch; if(!IS_VALID_CARD(card)) { pr_debug("Invalid param: %d is not a valid card id\n", card); - return NULL; + return; } if(n > SRAM_PAGESIZE) { - return NULL; + return; } /* @@ -102,7 +98,7 @@ void *memcpy_fromshmem(int card, void *dest, const void *src, size_t n) outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); - ret = memcpy_fromio(dest,(void *)(sc_adapter[card]->rambase + + memcpy_fromio(dest,(void *)(sc_adapter[card]->rambase + ((unsigned long) src % 0x4000)), n); spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, @@ -110,23 +106,20 @@ void *memcpy_fromshmem(int card, void *dest, const void *src, size_t n) /* pr_debug("%s: copying %d bytes from %#x to %#x\n", sc_adapter[card]->devicename, n, sc_adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */ - - return ret; } -void *memset_shmem(int card, void *dest, int c, size_t n) +void memset_shmem(int card, void *dest, int c, size_t n) { unsigned long flags; unsigned char ch; - void *ret; if(!IS_VALID_CARD(card)) { pr_debug("Invalid param: %d is not a valid card id\n", card); - return NULL; + return; } if(n > SRAM_PAGESIZE) { - return NULL; + return; } /* @@ -142,11 +135,9 @@ void *memset_shmem(int card, void *dest, int c, size_t n) outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); - ret = memset_io(sc_adapter[card]->rambase + + memset_io(sc_adapter[card]->rambase + ((unsigned long) dest % 0x4000), c, n); pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); - - return ret; } diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 7e92160519e2..2c007571a03e 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c @@ -75,6 +75,8 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [ 0x35 ] = KEY_PLAY, // play [ 0x36 ] = KEY_STOP, // stop [ 0x37 ] = KEY_RECORD, // recording + [ 0x3c ] = KEY_TEXT, // teletext submode (Japan: 12) + [ 0x3d ] = KEY_SUSPEND, // system standby #if 0 /* FIXME */ [ 0x0a ] = KEY_RESERVED, // 1/2/3 digits (japan: 10) @@ -106,8 +108,6 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [ 0x39 ] = KEY_RESERVED, // external 2 [ 0x3a ] = KEY_RESERVED, // PIP display mode [ 0x3b ] = KEY_RESERVED, // view data mode / advance - [ 0x3c ] = KEY_RESERVED, // teletext submode (Japan: 12) - [ 0x3d ] = KEY_RESERVED, // system standby [ 0x3e ] = KEY_RESERVED, // crispener on/off [ 0x3f ] = KEY_RESERVED, // system select #endif diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 70a3ee406503..8bc9075b281a 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -273,7 +273,7 @@ static int zol_do_ioctl(struct inode *inode, struct file *file, case VIDIOCGAUDIO: { struct video_audio *v = arg; - memset(&v, 0, sizeof(*v)); + memset(v, 0, sizeof(*v)); v->flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; v->mode |= zol_is_stereo(zol) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 90249af1efca..5c484f27a475 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -295,5 +295,16 @@ config VIDEO_CX88 To compile this driver as a module, choose M here: the module will be called cx8800 +config VIDEO_OVCAMCHIP + tristate "OmniVision Camera Chip support" + depends on VIDEO_DEV && I2C + ---help--- + Support for the OmniVision OV6xxx and OV7xxx series of camera chips. + This driver is intended to be used with the ov511 and w9968cf USB + camera drivers. + + To compile this driver as a module, choose M here: the + module will be called ovcamchip + endmenu diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 56f2e7c4a3f4..6a14ce96f190 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ +obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index fbc748e5f3ab..857d3043859c 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -71,6 +71,9 @@ static void gvc1100_muxsel(struct bttv *btv, unsigned int input); static void PXC200_muxsel(struct bttv *btv, unsigned int input); +static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input); +static void picolo_tetra_init(struct bttv *btv); + static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); static int tea5757_write(struct bttv *btv, int value); @@ -181,6 +184,7 @@ static struct CARD { { 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" }, { 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, + { 0x263710b4, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, { 0x3060121a, BTTV_STB2, "3Dfx VoodooTV 100/ STB OEM" }, { 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" }, @@ -260,12 +264,15 @@ static struct CARD { { 0x41424344, BTTV_GRANDTEC, "GrandTec Multi Capture" }, { 0x01020304, BTTV_XGUARD, "Grandtec Grand X-Guard" }, - { 0x010115cb, BTTV_GMV1, "AG GMV1" }, - { 0x010114c7, BTTV_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, { 0x18501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, { 0x18511851, BTTV_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" }, { 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" }, { 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, + { 0x18501f7f, BTTV_FLYVIDEO_98, "Lifeview Flyvideo 98" }, + + { 0x010115cb, BTTV_GMV1, "AG GMV1" }, + { 0x010114c7, BTTV_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, + { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, { 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, { 0xfff6f6ff, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, @@ -280,14 +287,21 @@ static struct CARD { { 0x40111554, BTTV_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, { 0x17de0a01, BTTV_KWORLD, "Mecer TV/FM/Video Tuner" }, + { 0x01051805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" }, + { 0x01061805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" }, + { 0x01071805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" }, + { 0x01081805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" }, + // likely broken, vendor id doesn't match the other magic views ... //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, // DVB cards (using pci function .1 for mpeg data xfer) { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, + { 0x07611461, BTTV_NEBULA_DIGITV, "AverMedia AverTV DVB-T" }, { 0x002611bd, BTTV_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB-T" }, { 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, + { 0x07711461, BTTV_AVDVBT_771, "AVermedia DVB-T 771" }, { 0, -1, NULL } }; @@ -835,7 +849,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 1}, - .audiomux = { 2, 0, 0, 0, 1}, + .audiomux = { 2, 0xd0001, 0, 0, 1}, .needs_tvaudio = 0, .pll = PLL_28, .tuner_type = -1, @@ -1646,6 +1660,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 3, 0, 1, 2}, .needs_tvaudio = 0, .pll = PLL_28, + .no_gpioirq = 1, },{ .name = "Formac ProTV II (bt878)", .video_inputs = 4, @@ -2012,6 +2027,57 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL, .has_remote = 1, .has_radio = 1, +},{ + /*Eric DEBIEF <debief@telemsa.com>*/ + /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/ + /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_PICOLO_TETRA_CHIP*/ + /*0x79 in bttv.h*/ + .name = "Euresys Picolo Tetra", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/ + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .pll = PLL_28, + .needs_tvaudio = 0, + .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ +},{ + /* Spirit TV Tuner from http://spiritmodems.com.au */ + /* Stafford Goodsell <surge@goliath.homeunix.org> */ + .name = "Spirit TV Tuner", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x0000000f, + .muxsel = { 2, 1, 1 }, + .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00}, + .tuner_type = TUNER_TEMIC_PAL, + .no_msp34xx = 1, + .no_tda9875 = 1, +},{ + /* Wolfram Joost <wojo@frokaschwei.de> */ + .name = "AVerMedia AVerTV DVB-T 771", + .video_inputs = 2, + .svhs = 1, + .tuner = -1, + .tuner_type = TUNER_ABSENT, + .muxsel = { 3 , 3 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .has_dvb = 1, + .no_gpioirq = 1, +#if 0 /* untested */ + .has_remote = 1, +#endif }}; const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -2381,6 +2447,7 @@ void __devinit bttv_init_card1(struct bttv *btv) pvr_boot(btv); break; case BTTV_TWINHAN_DST: + case BTTV_AVDVBT_771: btv->use_i2c_hw = 1; break; } @@ -2432,6 +2499,9 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_PXC200: init_PXC200(btv); break; + case BTTV_PICOLO_TETRA_CHIP: + picolo_tetra_init(btv); + break; case BTTV_VHX: btv->has_radio = 1; btv->has_matchbox = 1; @@ -2668,6 +2738,10 @@ static void modtec_eeprom(struct bttv *btv) btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I; printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", btv->c.nr,&eeprom_data[0x1e]); + } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { + btv->tuner_type=TUNER_PHILIPS_NTSC; + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); } else { printk("bttv%d: Modtec: Unknown TunerString: %s\n", btv->c.nr,&eeprom_data[0x1e]); @@ -3786,6 +3860,21 @@ static void xguard_muxsel(struct bttv *btv, unsigned int input) }; gpio_write(masks[input%16]); } +static void picolo_tetra_init(struct bttv *btv) +{ + /*This is the video input redirection fonctionality : I DID NOT USED IT. */ + btwrite (0x08<<16,BT848_GPIO_DATA);/*GPIO[19] [==> 4053 B+C] set to 1 */ + btwrite (0x04<<16,BT848_GPIO_DATA);/*GPIO[18] [==> 4053 A] set to 1*/ +} +static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input) +{ + + dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel => input = %d\n",btv->c.nr,input); + /*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/ + /*GPIO[20]&GPIO[21] used to choose the right input*/ + btwrite (input<<20,BT848_GPIO_DATA); + +} /* * ivc120_muxsel [Added by Alan Garfield <alan@fromorbit.com>] diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 9e6e537b7673..affe68732cea 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1334,7 +1334,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, spin_lock_irqsave(&btv->s_lock,flags); old = btv->screen; btv->screen = new; - bttv_set_dma(btv, 0x03, 1); + btv->curr.irqflags |= 1; + bttv_set_dma(btv, 0x03, btv->curr.irqflags); spin_unlock_irqrestore(&btv->s_lock,flags); if (NULL == new) free_btres(btv,fh,RESOURCE_OVERLAY); @@ -1441,7 +1442,8 @@ buffer_queue(struct file *file, struct videobuf_buffer *vb) buf->vb.state = STATE_QUEUED; list_add_tail(&buf->vb.queue,&fh->btv->capture); - bttv_set_dma(fh->btv, 0x03, 1); + fh->btv->curr.irqflags |= 1; + bttv_set_dma(fh->btv, 0x03, fh->btv->curr.irqflags); } static void buffer_release(struct file *file, struct videobuf_buffer *vb) @@ -3203,8 +3205,8 @@ static void bttv_print_riscaddr(struct bttv *btv) printk(" main: %08Lx\n", (unsigned long long)btv->main.dma); printk(" vbi : o=%08Lx e=%08Lx\n", - btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0, - btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0); + btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, + btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0); printk(" cap : o=%08Lx e=%08Lx\n", btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); @@ -3224,7 +3226,7 @@ static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc) if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) { printk("bttv%d: Oh, there (temporarely?) is no input signal. " - "Ok, then this is harmless, don't worry ;)", + "Ok, then this is harmless, don't worry ;)\n", btv->c.nr); return; } @@ -3236,18 +3238,12 @@ static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc) } static int -bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set) +bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set) { struct bttv_buffer *item; memset(set,0,sizeof(*set)); - /* vbi request ? */ - if (!list_empty(&btv->vcapture)) { - set->irqflags = 1; - set->vbi = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); - } - /* capture request ? */ if (!list_empty(&btv->capture)) { set->irqflags = 1; @@ -3295,27 +3291,20 @@ bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set) } } - dprintk("bttv%d: next set: top=%p bottom=%p vbi=%p " - "[screen=%p,irq=%d,%d]\n", - btv->c.nr,set->top, set->bottom, set->vbi, + dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n", + btv->c.nr,set->top, set->bottom, btv->screen,set->irqflags,set->topirq); return 0; } static void -bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup, - struct bttv_buffer_set *curr, unsigned int state) +bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup, + struct bttv_buffer_set *curr, unsigned int state) { struct timeval ts; do_gettimeofday(&ts); - if (NULL != wakeup->vbi) { - wakeup->vbi->vb.ts = ts; - wakeup->vbi->vb.field_count = btv->field_count; - wakeup->vbi->vb.state = state; - wake_up(&wakeup->vbi->vb.done); - } if (wakeup->top == wakeup->bottom) { if (NULL != wakeup->top && curr->top != wakeup->top) { if (irq_debug > 1) @@ -3345,10 +3334,27 @@ bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup, } } +static void +bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup, + unsigned int state) +{ + struct timeval ts; + + if (NULL == wakeup) + return; + + do_gettimeofday(&ts); + wakeup->vb.ts = ts; + wakeup->vb.field_count = btv->field_count; + wakeup->vb.state = state; + wake_up(&wakeup->vb.done); +} + static void bttv_irq_timeout(unsigned long data) { struct bttv *btv = (struct bttv *)data; struct bttv_buffer_set old,new; + struct bttv_buffer *ovbi; struct bttv_buffer *item; unsigned long flags; @@ -3364,13 +3370,17 @@ static void bttv_irq_timeout(unsigned long data) /* deactivate stuff */ memset(&new,0,sizeof(new)); - old = btv->curr; + old = btv->curr; + ovbi = btv->cvbi; btv->curr = new; - bttv_buffer_set_activate(btv, &new); + btv->cvbi = NULL; + bttv_buffer_activate_video(btv, &new); + bttv_buffer_activate_vbi(btv, NULL); bttv_set_dma(btv, 0, 0); /* wake up */ - bttv_irq_wakeup_set(btv, &old, &new, STATE_ERROR); + bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR); + bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR); /* cancel all outstanding capture / vbi requests */ while (!list_empty(&btv->capture)) { @@ -3410,8 +3420,17 @@ bttv_irq_wakeup_top(struct bttv *btv) spin_unlock(&btv->s_lock); } +static inline int is_active(struct btcx_riscmem *risc, u32 rc) +{ + if (rc < risc->dma) + return 0; + if (rc > risc->dma + risc->size) + return 0; + return 1; +} + static void -bttv_irq_switch_fields(struct bttv *btv) +bttv_irq_switch_video(struct bttv *btv) { struct bttv_buffer_set new; struct bttv_buffer_set old; @@ -3420,9 +3439,10 @@ bttv_irq_switch_fields(struct bttv *btv) spin_lock(&btv->s_lock); /* new buffer set */ - bttv_irq_next_set(btv, &new); + bttv_irq_next_video(btv, &new); rc = btread(BT848_RISC_COUNT); - if (rc < btv->main.dma || rc > btv->main.dma + 0x100) { + if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) || + (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) { btv->framedrop++; if (debug_latency) bttv_irq_debug_low_latency(btv, rc); @@ -3433,7 +3453,7 @@ bttv_irq_switch_fields(struct bttv *btv) /* switch over */ old = btv->curr; btv->curr = new; - bttv_buffer_set_activate(btv, &new); + bttv_buffer_activate_video(btv, &new); bttv_set_dma(btv, 0, new.irqflags); /* switch input */ @@ -3443,7 +3463,39 @@ bttv_irq_switch_fields(struct bttv *btv) } /* wake up finished buffers */ - bttv_irq_wakeup_set(btv, &old, &new, STATE_DONE); + bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE); + spin_unlock(&btv->s_lock); +} + +static void +bttv_irq_switch_vbi(struct bttv *btv) +{ + struct bttv_buffer *new = NULL; + struct bttv_buffer *old; + u32 rc; + + spin_lock(&btv->s_lock); + + if (!list_empty(&btv->vcapture)) + new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); + old = btv->cvbi; + + rc = btread(BT848_RISC_COUNT); + if (NULL != old && (is_active(&old->top, rc) || + is_active(&old->bottom, rc))) { + btv->framedrop++; + if (debug_latency) + bttv_irq_debug_low_latency(btv, rc); + spin_unlock(&btv->s_lock); + return; + } + + /* switch */ + btv->cvbi = new; + bttv_buffer_activate_vbi(btv, new); + bttv_set_dma(btv, 0, btv->curr.irqflags); + + bttv_irq_wakeup_vbi(btv, old, STATE_DONE); spin_unlock(&btv->s_lock); } @@ -3500,11 +3552,14 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) wake_up(&btv->i2c_queue); } + if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) + bttv_irq_switch_vbi(btv); + if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) bttv_irq_wakeup_top(btv); if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) - bttv_irq_switch_fields(btv); + bttv_irq_switch_video(btv); if ((astat & BT848_INT_HLOCK) && btv->opt_automute) audio_mux(btv, -1); @@ -3872,9 +3927,11 @@ static int bttv_suspend(struct pci_dev *pci_dev, u32 state) /* stop dma + irqs */ spin_lock_irqsave(&btv->s_lock,flags); memset(&idle, 0, sizeof(idle)); - btv->state.set = btv->curr; + btv->state.video = btv->curr; + btv->state.vbi = btv->cvbi; btv->curr = idle; - bttv_buffer_set_activate(btv, &idle); + bttv_buffer_activate_video(btv, &idle); + bttv_buffer_activate_vbi(btv, NULL); bttv_set_dma(btv, 0, 0); btwrite(0, BT848_INT_MASK); spin_unlock_irqrestore(&btv->s_lock,flags); @@ -3914,8 +3971,10 @@ static int bttv_resume(struct pci_dev *pci_dev) /* restart dma */ spin_lock_irqsave(&btv->s_lock,flags); - btv->curr = btv->state.set; - bttv_buffer_set_activate(btv, &btv->curr); + btv->curr = btv->state.video; + btv->cvbi = btv->state.vbi; + bttv_buffer_activate_video(btv, &btv->curr); + bttv_buffer_activate_vbi(btv, btv->cvbi); bttv_set_dma(btv, 0, btv->curr.irqflags); spin_unlock_irqrestore(&btv->s_lock,flags); return 0; diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index c512416a014f..769c7e3653d9 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -379,7 +379,7 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags) btv->cap_ctl = 0; if (NULL != btv->curr.top) btv->cap_ctl |= 0x02; if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01; - if (NULL != btv->curr.vbi) btv->cap_ctl |= 0x0c; + if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c; capctl = 0; capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */ @@ -389,9 +389,9 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags) d2printk(KERN_DEBUG "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", btv->c.nr,capctl,irqflags, - btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0, + btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, - btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0, + btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0, btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); cmd = BT848_RISC_JUMP; @@ -399,6 +399,8 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags) cmd |= BT848_RISC_IRQ; cmd |= (irqflags & 0x0f) << 16; cmd |= (~irqflags & 0x0f) << 20; + } + if (irqflags || btv->cvbi) { mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT); } else { del_timer(&btv->timeout); @@ -501,20 +503,26 @@ bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf) } int -bttv_buffer_set_activate(struct bttv *btv, - struct bttv_buffer_set *set) +bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi) { /* vbi capture */ - if (set->vbi) { - set->vbi->vb.state = STATE_ACTIVE; - list_del(&set->vbi->vb.queue); - bttv_risc_hook(btv, RISC_SLOT_O_VBI, &set->vbi->top, 0); - bttv_risc_hook(btv, RISC_SLOT_E_VBI, &set->vbi->bottom, 0); + if (vbi) { + vbi->vb.state = STATE_ACTIVE; + list_del(&vbi->vb.queue); + bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0); + bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4); } else { bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0); bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0); } + return 0; +} +int +bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set) +{ /* video capture */ if (NULL != set->top && NULL != set->bottom) { if (set->top == set->bottom) { diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c index f3d12cde02e5..ad655c8aa13f 100644 --- a/drivers/media/video/bttv-vbi.c +++ b/drivers/media/video/bttv-vbi.c @@ -114,7 +114,10 @@ vbi_buffer_queue(struct file *file, struct videobuf_buffer *vb) dprintk("queue %p\n",vb); buf->vb.state = STATE_QUEUED; list_add_tail(&buf->vb.queue,&btv->vcapture); - bttv_set_dma(btv,0x0c,1); + if (NULL == btv->cvbi) { + fh->btv->curr.irqflags |= 4; + bttv_set_dma(btv,0x0c,fh->btv->curr.irqflags); + } } static void vbi_buffer_release(struct file *file, struct videobuf_buffer *vb) diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 99df391fb1ae..33d56aa9d871 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -124,6 +124,8 @@ #define BTTV_SIMUS_GVC1100 0x74 #define BTTV_NGSTV_PLUS 0x75 #define BTTV_LMLBT4 0x76 +#define BTTV_PICOLO_TETRA_CHIP 0x79 +#define BTTV_AVDVBT_771 0x7b /* i2c address list */ #define I2C_TSA5522 0xc2 diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 2257381fdfff..fae428ea4be6 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -25,7 +25,7 @@ #define _BTTVP_H_ #include <linux/version.h> -#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,14) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15) #include <linux/types.h> #include <linux/wait.h> @@ -127,7 +127,6 @@ struct bttv_buffer { struct bttv_buffer_set { struct bttv_buffer *top; /* top field buffer */ struct bttv_buffer *bottom; /* bottom field buffer */ - struct bttv_buffer *vbi; /* vbi buffer */ unsigned int irqflags; unsigned int topirq; }; @@ -197,8 +196,10 @@ int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, /* capture buffer handling */ int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); -int bttv_buffer_set_activate(struct bttv *btv, - struct bttv_buffer_set *set); +int bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set); +int bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi); void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf); /* overlay handling */ @@ -279,7 +280,8 @@ struct bttv_suspend_state { u32 gpio_enable; u32 gpio_data; int disabled; - struct bttv_buffer_set set; + struct bttv_buffer_set video; + struct bttv_buffer *vbi; }; struct bttv { @@ -377,6 +379,7 @@ struct bttv { struct list_head capture; /* video capture queue */ struct list_head vcapture; /* vbi capture queue */ struct bttv_buffer_set curr; /* active buffers */ + struct bttv_buffer *cvbi; /* active vbi buffer */ int new_input; unsigned long cap_ctl; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 3807ef98b217..1e183aae05e7 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -99,6 +99,10 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, + .gpio0 = 0x000003ff, + .gpio1 = 0x000000ff, + .gpio2 = 0x000000ff, + .gpio3 = 0x00000000, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, @@ -111,6 +115,7 @@ struct cx88_board cx88_boards[] = { [CX88_BOARD_WINFAST2000XP] = { .name = "Leadtek Winfast 2000XP Expert", .tuner_type = 44, + .needs_tda9887 = 1, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -149,22 +154,33 @@ struct cx88_board cx88_boards[] = { .vmux = 0, }}, }, - [CX88_BOARD_MSI_TVANYWHERE] = { + [CX88_BOARD_MSI_TVANYWHERE_MASTER] = { + //added gpio values thanks to Torsten Seeboth + //values for PAL from DScaler .name = "MSI TV-@nywhere Master", .tuner_type = 33, + .needs_tda9887 = 1, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, + .gpio0 = 0x000040bf, + .gpio1 = 0x000080c0, + .gpio2 = 0x0000ff40, + .gpio3 = 0x00000000, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - },{ - // temporarly for testing ... - .type = CX88_VMUX_COMPOSITE2, - .vmux = 2, + .gpio0 = 0x000040bf, + .gpio1 = 0x000080c0, + .gpio2 = 0x0000ff40, + .gpio3 = 0x00000000, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, + .gpio0 = 0x000040bf, + .gpio1 = 0x000080c0, + .gpio2 = 0x0000ff40, + .gpio3 = 0x00000000, }}, .radio = { .type = CX88_RADIO, @@ -199,8 +215,97 @@ struct cx88_board cx88_boards[] = { .type = CX88_RADIO, }, }, - - + [CX88_BOARD_IODATA_GVVCP3PCI] = { + .name = "IODATA GV-VCP3/PCI", + .tuner_type = TUNER_ABSENT, + .needs_tda9887 = 0, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE2, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + }, + [CX88_BOARD_PROLINK_PLAYTVPVR] = { + .name = "Prolink PlayTV PVR", + .tuner_type = 43, + .needs_tda9887 = 1, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0xff00, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0xff03, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0xff03, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0xff00, + }, + }, + [CX88_BOARD_ASUS_PVR_416] = { + .name = "ASUS PVR-416", + .tuner_type = 43, + .needs_tda9887 = 1, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0000fde6, + .gpio1 = 0x00000000, // possibly for mpeg data + .gpio2 = 0x000000e9, + .gpio3 = 0x00000000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? + .gpio1 = 0x00000000, // possibly for mpeg data + .gpio2 = 0x000000e9, + .gpio3 = 0x00000000, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x0000fde2, + .gpio1 = 0x00000000, + .gpio2 = 0x000000e9, + .gpio3 = 0x00000000, + }, + }, + [CX88_BOARD_MSI_TVANYWHERE] = { + .name = "MSI TV-@nywhere", + .tuner_type = 33, + .needs_tda9887 = 1, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00000fbf, + .gpio1 = 0x000000c0, + .gpio2 = 0x0000fc08, + .gpio3 = 0x00000000, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00000fbf, + .gpio1 = 0x000000c0, + .gpio2 = 0x0000fc68, + .gpio3 = 0x00000000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00000fbf, + .gpio1 = 0x000000c0, + .gpio2 = 0x0000fc68, + .gpio3 = 0x00000000, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -242,6 +347,10 @@ struct cx88_subid cx88_subids[] = { .card = CX88_BOARD_WINFAST_DV2000, },{ .subvendor = 0x107d, + .subdevice = 0x663b, + .card = CX88_BOARD_LEADTEK_PVR2000, + },{ + .subvendor = 0x107d, .subdevice = 0x663C, .card = CX88_BOARD_LEADTEK_PVR2000, },{ @@ -251,12 +360,19 @@ struct cx88_subid cx88_subids[] = { },{ .subvendor = 0x1462, .subdevice = 0x8606, - .card = CX88_BOARD_MSI_TVANYWHERE, - } + .card = CX88_BOARD_MSI_TVANYWHERE_MASTER, + },{ + .subvendor = 0x10fc, + .subdevice = 0xd003, + .card = CX88_BOARD_IODATA_GVVCP3PCI, + },{ + .subvendor = 0x1043, + .subdevice = 0x4823, /* with mpeg encoder */ + .card = CX88_BOARD_ASUS_PVR_416, + } }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); - /* ----------------------------------------------------------------------- */ /* some leadtek specific stuff */ @@ -386,20 +502,22 @@ static struct { [ 0x02 ] = { .id = TUNER_ABSENT, .name = "PAL_B" }, [ 0x03 ] = { .id = TUNER_ABSENT, - .name = "BAL_I" }, + .name = "PAL_I" }, [ 0x04 ] = { .id = TUNER_ABSENT, .name = "PAL_D" }, [ 0x05 ] = { .id = TUNER_ABSENT, .name = "SECAM" }, - [ 0x10 ] = { .id = TUNER_ABSENT, .fm = 1, + [ 0x10 ] = { .id = TUNER_ABSENT, + .fm = 1, .name = "TEMIC_4049" }, [ 0x11 ] = { .id = TUNER_TEMIC_4136FY5, .name = "TEMIC_4136" }, [ 0x12 ] = { .id = TUNER_ABSENT, .name = "TEMIC_4146" }, - [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME, .fm = 1, + [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME, + .fm = 1, .name = "PHILIPS_FQ1216_MK3" }, [ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1, .name = "PHILIPS_FQ1236_MK3" }, @@ -454,7 +572,33 @@ i2c_eeprom(struct i2c_client *c, unsigned char *eedata, int len) return 0; } -void __devinit cx88_card_setup(struct cx8800_dev *dev) +void cx88_card_list(struct cx8800_dev *dev) +{ + int i; + + if (0 == dev->pci->subsystem_vendor && + 0 == dev->pci->subsystem_device) { + printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n" + "%s: be autodetected. Please pass card=<n> insmod option to\n" + "%s: workaround that. Redirect complaints to the vendor of\n" + "%s: the TV card. Best regards,\n" + "%s: -- tux\n", + dev->name,dev->name,dev->name,dev->name,dev->name); + } else { + printk("%s: Your board isn't known (yet) to the driver. You can\n" + "%s: try to pick one of the existing card configs via\n" + "%s: card=<n> insmod option. Updating to the latest\n" + "%s: version might help as well.\n", + dev->name,dev->name,dev->name,dev->name); + } + printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n", + dev->name); + for (i = 0; i < cx88_bcount; i++) + printk("%s: card=%d -> %s\n", + dev->name, i, cx88_boards[i].name); +} + +void cx88_card_setup(struct cx8800_dev *dev) { static u8 eeprom[128]; @@ -474,6 +618,9 @@ void __devinit cx88_card_setup(struct cx8800_dev *dev) i2c_eeprom(&dev->i2c_client,eeprom,sizeof(eeprom)); leadtek_eeprom(dev,eeprom); break; + case CX88_BOARD_ASUS_PVR_416: + dev->has_radio = 1; + break; } } @@ -483,6 +630,7 @@ EXPORT_SYMBOL(cx88_boards); EXPORT_SYMBOL(cx88_bcount); EXPORT_SYMBOL(cx88_subids); EXPORT_SYMBOL(cx88_idcount); +EXPORT_SYMBOL(cx88_card_list); EXPORT_SYMBOL(cx88_card_setup); /* diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 9396ec27c193..a04aad36ccec 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -22,8 +22,6 @@ */ -#define __NO_VERSION__ 1 - #include <linux/module.h> #include <linux/init.h> diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h index 4ecce88a85d4..a80b7519e7f7 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/video/cx88/cx88-reg.h @@ -599,10 +599,20 @@ #define EN_I2SIN_STR2DAC 0x00004000 #define EN_I2SIN_ENABLE 0x00008000 +#if 0 +/* old */ #define EN_DMTRX_SUMDIFF 0x00000800 #define EN_DMTRX_SUMR 0x00000880 #define EN_DMTRX_LR 0x00000900 #define EN_DMTRX_MONO 0x00000980 +#else +/* dscaler cvs */ +#define EN_DMTRX_SUMDIFF (0 << 7) +#define EN_DMTRX_SUMR (1 << 7) +#define EN_DMTRX_LR (2 << 7) +#define EN_DMTRX_MONO (3 << 7) +#define EN_DMTRX_BYPASS (1 << 11) +#endif // Video #define VID_CAPTURE_CONTROL 0x310180 diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 6b57e451857e..f6def3df9460 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -48,6 +48,7 @@ #include <linux/interrupt.h> #include <linux/vmalloc.h> #include <linux/init.h> +#include <linux/smp_lock.h> #include "cx88.h" @@ -60,6 +61,33 @@ MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]"); /* ----------------------------------------------------------- */ +static char *aud_ctl_names[64] = +{ + [ EN_BTSC_FORCE_MONO ] = "BTSC_FORCE_MONO", + [ EN_BTSC_FORCE_STEREO ] = "BTSC_FORCE_STEREO", + [ EN_BTSC_FORCE_SAP ] = "BTSC_FORCE_SAP", + [ EN_BTSC_AUTO_STEREO ] = "BTSC_AUTO_STEREO", + [ EN_BTSC_AUTO_SAP ] = "BTSC_AUTO_SAP", + [ EN_A2_FORCE_MONO1 ] = "A2_FORCE_MONO1", + [ EN_A2_FORCE_MONO2 ] = "A2_FORCE_MONO2", + [ EN_A2_FORCE_STEREO ] = "A2_FORCE_STEREO", + [ EN_A2_AUTO_MONO2 ] = "A2_AUTO_MONO2", + [ EN_A2_AUTO_STEREO ] = "A2_AUTO_STEREO", + [ EN_EIAJ_FORCE_MONO1 ] = "EIAJ_FORCE_MONO1", + [ EN_EIAJ_FORCE_MONO2 ] = "EIAJ_FORCE_MONO2", + [ EN_EIAJ_FORCE_STEREO ] = "EIAJ_FORCE_STEREO", + [ EN_EIAJ_AUTO_MONO2 ] = "EIAJ_AUTO_MONO2", + [ EN_EIAJ_AUTO_STEREO ] = "EIAJ_AUTO_STEREO", + [ EN_NICAM_FORCE_MONO1 ] = "NICAM_FORCE_MONO1", + [ EN_NICAM_FORCE_MONO2 ] = "NICAM_FORCE_MONO2", + [ EN_NICAM_FORCE_STEREO ] = "NICAM_FORCE_STEREO", + [ EN_NICAM_AUTO_MONO2 ] = "NICAM_AUTO_MONO2", + [ EN_NICAM_AUTO_STEREO ] = "NICAM_AUTO_STEREO", + [ EN_FMRADIO_FORCE_MONO ] = "FMRADIO_FORCE_MONO", + [ EN_FMRADIO_FORCE_STEREO ] = "FMRADIO_FORCE_STEREO", + [ EN_FMRADIO_AUTO_STEREO ] = "FMRADIO_AUTO_STEREO", +}; + struct rlist { u32 reg; u32 val; @@ -125,26 +153,116 @@ static void set_audio_finish(struct cx8800_dev *dev) static void set_audio_standard_BTSC(struct cx8800_dev *dev, unsigned int sap) { static const struct rlist btsc[] = { - /* Magic stuff from leadtek driver + datasheet.*/ - { AUD_DBX_IN_GAIN, 0x4734 }, - { AUD_DBX_WBE_GAIN, 0x4640 }, - { AUD_DBX_SE_GAIN, 0x8D31 }, - { AUD_DEEMPH0_G0, 0x1604 }, - { AUD_PHASE_FIX_CTL, 0x0020 }, - + /* from dscaler */ + { AUD_OUT1_SEL, 0x00000013 }, + { AUD_OUT1_SHIFT, 0x00000000 }, + { AUD_POLY0_DDS_CONSTANT, 0x0012010c }, + { AUD_DMD_RA_DDS, 0x00c3e7aa }, + { AUD_DBX_IN_GAIN, 0x00004734 }, + { AUD_DBX_WBE_GAIN, 0x00004640 }, + { AUD_DBX_SE_GAIN, 0x00008d31 }, + { AUD_DCOC_0_SRC, 0x0000001a }, + { AUD_IIR1_4_SEL, 0x00000021 }, + { AUD_DCOC_PASS_IN, 0x00000003 }, + { AUD_DCOC_0_SHIFT_IN0, 0x0000000a }, + { AUD_DCOC_0_SHIFT_IN1, 0x00000008 }, + { AUD_DCOC_1_SHIFT_IN0, 0x0000000a }, + { AUD_DCOC_1_SHIFT_IN1, 0x00000008 }, + { AUD_DN0_FREQ, 0x0000283b }, + { AUD_DN2_SRC_SEL, 0x00000008 }, + { AUD_DN2_FREQ, 0x00003000 }, + { AUD_DN2_AFC, 0x00000002 }, + { AUD_DN2_SHFT, 0x00000000 }, + { AUD_IIR2_2_SEL, 0x00000020 }, + { AUD_IIR2_2_SHIFT, 0x00000000 }, + { AUD_IIR2_3_SEL, 0x0000001f }, + { AUD_IIR2_3_SHIFT, 0x00000000 }, + { AUD_CRDC1_SRC_SEL, 0x000003ce }, + { AUD_CRDC1_SHIFT, 0x00000000 }, + { AUD_CORDIC_SHIFT_1, 0x00000007 }, + { AUD_DCOC_1_SRC, 0x0000001b }, + { AUD_DCOC1_SHIFT, 0x00000000 }, + { AUD_RDSI_SEL, 0x00000008 }, + { AUD_RDSQ_SEL, 0x00000008 }, + { AUD_RDSI_SHIFT, 0x00000000 }, + { AUD_RDSQ_SHIFT, 0x00000000 }, + { AUD_POLYPH80SCALEFAC, 0x00000003 }, + { /* end of list */ }, + }; + static const struct rlist btsc_sap[] = { + { AUD_DBX_IN_GAIN, 0x00007200 }, + { AUD_DBX_WBE_GAIN, 0x00006200 }, + { AUD_DBX_SE_GAIN, 0x00006200 }, + { AUD_IIR1_1_SEL, 0x00000000 }, + { AUD_IIR1_3_SEL, 0x00000001 }, + { AUD_DN1_SRC_SEL, 0x00000007 }, + { AUD_IIR1_4_SHIFT, 0x00000006 }, + { AUD_IIR2_1_SHIFT, 0x00000000 }, + { AUD_IIR2_2_SHIFT, 0x00000000 }, + { AUD_IIR3_0_SHIFT, 0x00000000 }, + { AUD_IIR3_1_SHIFT, 0x00000000 }, + { AUD_IIR3_0_SEL, 0x0000000d }, + { AUD_IIR3_1_SEL, 0x0000000e }, + { AUD_DEEMPH1_SRC_SEL, 0x00000014 }, + { AUD_DEEMPH1_SHIFT, 0x00000000 }, + { AUD_DEEMPH1_G0, 0x00004000 }, + { AUD_DEEMPH1_A0, 0x00000000 }, + { AUD_DEEMPH1_B0, 0x00000000 }, + { AUD_DEEMPH1_A1, 0x00000000 }, + { AUD_DEEMPH1_B1, 0x00000000 }, + { AUD_OUT0_SEL, 0x0000003f }, + { AUD_OUT1_SEL, 0x0000003f }, + { AUD_DN1_AFC, 0x00000002 }, + { AUD_DCOC_0_SHIFT_IN0, 0x0000000a }, + { AUD_DCOC_0_SHIFT_IN1, 0x00000008 }, + { AUD_DCOC_1_SHIFT_IN0, 0x0000000a }, + { AUD_DCOC_1_SHIFT_IN1, 0x00000008 }, + { AUD_IIR1_0_SEL, 0x0000001d }, + { AUD_IIR1_2_SEL, 0x0000001e }, + { AUD_IIR2_1_SEL, 0x00000002 }, + { AUD_IIR2_2_SEL, 0x00000004 }, + { AUD_IIR3_2_SEL, 0x0000000f }, + { AUD_DCOC2_SHIFT, 0x00000001 }, + { AUD_IIR3_2_SHIFT, 0x00000001 }, + { AUD_DEEMPH0_SRC_SEL, 0x00000014 }, + { AUD_CORDIC_SHIFT_1, 0x00000006 }, + { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 }, + { AUD_DMD_RA_DDS, 0x00f696e6 }, + { AUD_IIR2_3_SEL, 0x00000025 }, + { AUD_IIR1_4_SEL, 0x00000021 }, + { AUD_DN1_FREQ, 0x0000c965 }, + { AUD_DCOC_PASS_IN, 0x00000003 }, + { AUD_DCOC_0_SRC, 0x0000001a }, + { AUD_DCOC_1_SRC, 0x0000001b }, + { AUD_DCOC1_SHIFT, 0x00000000 }, + { AUD_RDSI_SEL, 0x00000009 }, + { AUD_RDSQ_SEL, 0x00000009 }, + { AUD_RDSI_SHIFT, 0x00000000 }, + { AUD_RDSQ_SHIFT, 0x00000000 }, + { AUD_POLYPH80SCALEFAC, 0x00000003 }, { /* end of list */ }, }; - dprintk("%s (status: unknown)\n",__FUNCTION__); - set_audio_start(dev, 0x0001, - EN_BTSC_AUTO_STEREO); - set_audio_registers(dev, btsc); + // dscaler: exactly taken from driver, + // dscaler: don't know why to set EN_FMRADIO_EN_RDS + if (sap) { + dprintk("%s SAP (status: unknown)\n",__FUNCTION__); + set_audio_start(dev, 0x0001, + EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP); + set_audio_registers(dev, btsc_sap); + } else { + dprintk("%s (status: known-good)\n",__FUNCTION__); + set_audio_start(dev, 0x0001, + EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO); + set_audio_registers(dev, btsc); + } set_audio_finish(dev); } static void set_audio_standard_NICAM(struct cx8800_dev *dev) { - static const struct rlist nicam[] = { + static const struct rlist nicam_common[] = { + /* from dscaler */ { AUD_RATE_ADJ1, 0x00000010 }, { AUD_RATE_ADJ2, 0x00000040 }, { AUD_RATE_ADJ3, 0x00000100 }, @@ -152,21 +270,64 @@ static void set_audio_standard_NICAM(struct cx8800_dev *dev) { AUD_RATE_ADJ5, 0x00001000 }, // { AUD_DMD_RA_DDS, 0x00c0d5ce }, + // Deemphasis 1: + { AUD_DEEMPHGAIN_R, 0x000023c2 }, + { AUD_DEEMPHNUMER1_R, 0x0002a7bc }, + { AUD_DEEMPHNUMER2_R, 0x0003023e }, + { AUD_DEEMPHDENOM1_R, 0x0000f3d0 }, + { AUD_DEEMPHDENOM2_R, 0x00000000 }, + +#if 0 + // Deemphasis 2: (other tv norm?) + { AUD_DEEMPHGAIN_R, 0x0000c600 }, + { AUD_DEEMPHNUMER1_R, 0x00066738 }, + { AUD_DEEMPHNUMER2_R, 0x00066739 }, + { AUD_DEEMPHDENOM1_R, 0x0001e88c }, + { AUD_DEEMPHDENOM2_R, 0x0001e88c }, +#endif + + { AUD_DEEMPHDENOM2_R, 0x00000000 }, + { AUD_ERRLOGPERIOD_R, 0x00000fff }, + { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff }, + { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff }, + { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f }, + { AUD_POLYPH80SCALEFAC, 0x00000003 }, + // setup QAM registers { AUD_PDF_DDS_CNST_BYTE2, 0x06 }, { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, { AUD_PDF_DDS_CNST_BYTE0, 0x16 }, { AUD_QAM_MODE, 0x05 }, + + { /* end of list */ }, + }; + static const struct rlist nicam_pal_i[] = { + { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, + { AUD_PHACC_FREQ_8MSB, 0x3a }, + { AUD_PHACC_FREQ_8LSB, 0x93 }, + + { /* end of list */ }, + }; + static const struct rlist nicam_default[] = { + { AUD_PDF_DDS_CNST_BYTE0, 0x16 }, { AUD_PHACC_FREQ_8MSB, 0x34 }, { AUD_PHACC_FREQ_8LSB, 0x4c }, { /* end of list */ }, - }; + }; - dprintk("%s (status: unknown)\n",__FUNCTION__); set_audio_start(dev, 0x0010, - EN_DMTRX_LR | EN_NICAM_FORCE_STEREO); - set_audio_registers(dev, nicam); + EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO); + set_audio_registers(dev, nicam_common); + switch (dev->tvaudio) { + case WW_NICAM_I: + dprintk("%s PAL-I NICAM (status: unknown)\n",__FUNCTION__); + set_audio_registers(dev, nicam_pal_i); + case WW_NICAM_BGDKL: + dprintk("%s PAL NICAM (status: unknown)\n",__FUNCTION__); + set_audio_registers(dev, nicam_default); + break; + }; set_audio_finish(dev); } @@ -297,7 +458,7 @@ static void set_audio_standard_NICAM_L(struct cx8800_dev *dev) static void set_audio_standard_A2(struct cx8800_dev *dev) { /* from dscaler cvs */ - static const struct rlist a2[] = { + static const struct rlist a2_common[] = { { AUD_PDF_DDS_CNST_BYTE2, 0x06 }, { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, @@ -347,16 +508,20 @@ static void set_audio_standard_A2(struct cx8800_dev *dev) { AUD_RDSQ_SHIFT, 0x00000000 }, { AUD_POLYPH80SCALEFAC, 0x00000001 }, - // Table 1 + { /* end of list */ }, + }; + + static const struct rlist a2_table1[] = { + // PAL-BG { AUD_DMD_RA_DDS, 0x002a73bd }, { AUD_C1_UP_THR, 0x00007000 }, { AUD_C1_LO_THR, 0x00005400 }, { AUD_C2_UP_THR, 0x00005400 }, { AUD_C2_LO_THR, 0x00003000 }, - -#if 0 - // found this in WDM-driver for A2, must country spec. - // Table 2 + { /* end of list */ }, + }; + static const struct rlist a2_table2[] = { + // PAL-DK { AUD_DMD_RA_DDS, 0x002a73bd }, { AUD_C1_UP_THR, 0x00007000 }, { AUD_C1_LO_THR, 0x00005400 }, @@ -364,8 +529,10 @@ static void set_audio_standard_A2(struct cx8800_dev *dev) { AUD_C2_LO_THR, 0x00003000 }, { AUD_DN0_FREQ, 0x00003a1c }, { AUD_DN2_FREQ, 0x0000d2e0 }, - - // Table 3 + { /* end of list */ }, + }; + static const struct rlist a2_table3[] = { + // unknown, probably NTSC-M { AUD_DMD_RA_DDS, 0x002a2873 }, { AUD_C1_UP_THR, 0x00003c00 }, { AUD_C1_LO_THR, 0x00003000 }, @@ -375,140 +542,26 @@ static void set_audio_standard_A2(struct cx8800_dev *dev) { AUD_DN1_FREQ, 0x00003418 }, { AUD_DN2_FREQ, 0x000029c7 }, { AUD_POLY0_DDS_CONSTANT, 0x000a7540 }, -#endif - { /* end of list */ }, }; - static const struct rlist a2_old[] = { - { AUD_DN0_FREQ, 0x0000312b }, - { AUD_POLY0_DDS_CONSTANT, 0x000a62b4 }, - { AUD_IIR1_0_SEL, 0x00000000 }, - { AUD_IIR1_1_SEL, 0x00000001 }, - { AUD_IIR1_2_SEL, 0x0000001f }, - { AUD_IIR1_3_SEL, 0x00000020 }, - { AUD_IIR1_4_SEL, 0x00000023 }, - { AUD_IIR1_5_SEL, 0x00000007 }, - { AUD_IIR1_0_SHIFT, 0x00000000 }, - { AUD_IIR1_1_SHIFT, 0x00000000 }, - { AUD_IIR1_2_SHIFT, 0x00000007 }, - { AUD_IIR1_3_SHIFT, 0x00000007 }, - { AUD_IIR1_4_SHIFT, 0x00000007 }, - { AUD_IIR1_5_SHIFT, 0x00000000 }, - { AUD_IIR2_0_SEL, 0x00000002 }, - { AUD_IIR2_1_SEL, 0x00000003 }, - { AUD_IIR2_2_SEL, 0x00000004 }, - { AUD_IIR2_3_SEL, 0x00000005 }, - { AUD_IIR3_0_SEL, 0x00000021 }, - { AUD_IIR3_1_SEL, 0x00000023 }, - { AUD_IIR3_2_SEL, 0x00000016 }, - { AUD_IIR3_0_SHIFT, 0x00000000 }, - { AUD_IIR3_1_SHIFT, 0x00000000 }, - { AUD_IIR3_2_SHIFT, 0x00000000 }, - { AUD_IIR4_0_SEL, 0x0000001d }, - { AUD_IIR4_1_SEL, 0x00000019 }, - { AUD_IIR4_2_SEL, 0x00000008 }, - { AUD_IIR4_0_SHIFT, 0x00000000 }, - { AUD_IIR4_1_SHIFT, 0x00000000 }, - { AUD_IIR4_2_SHIFT, 0x00000001 }, - { AUD_IIR4_0_CA0, 0x0003e57e }, - { AUD_IIR4_0_CA1, 0x00005e11 }, - { AUD_IIR4_0_CA2, 0x0003a7cf }, - { AUD_IIR4_0_CB0, 0x00002368 }, - { AUD_IIR4_0_CB1, 0x0003bf1b }, - { AUD_IIR4_1_CA0, 0x00006349 }, - { AUD_IIR4_1_CA1, 0x00006f27 }, - { AUD_IIR4_1_CA2, 0x0000e7a3 }, - { AUD_IIR4_1_CB0, 0x00005653 }, - { AUD_IIR4_1_CB1, 0x0000cf97 }, - { AUD_IIR4_2_CA0, 0x00006349 }, - { AUD_IIR4_2_CA1, 0x00006f27 }, - { AUD_IIR4_2_CA2, 0x0000e7a3 }, - { AUD_IIR4_2_CB0, 0x00005653 }, - { AUD_IIR4_2_CB1, 0x0000cf97 }, - { AUD_HP_MD_IIR4_1, 0x00000001 }, - { AUD_HP_PROG_IIR4_1, 0x00000017 }, - { AUD_DN1_FREQ, 0x00003618 }, - { AUD_DN1_SRC_SEL, 0x00000017 }, - { AUD_DN1_SHFT, 0x00000007 }, - { AUD_DN1_AFC, 0x00000000 }, - { AUD_DN1_FREQ_SHIFT, 0x00000000 }, - { AUD_DN2_SRC_SEL, 0x00000040 }, - { AUD_DN2_SHFT, 0x00000000 }, - { AUD_DN2_AFC, 0x00000002 }, - { AUD_DN2_FREQ, 0x0000caaf }, - { AUD_DN2_FREQ_SHIFT, 0x00000000 }, - { AUD_PDET_SRC, 0x00000014 }, - { AUD_PDET_SHIFT, 0x00000000 }, - { AUD_DEEMPH0_SRC_SEL, 0x00000011 }, - { AUD_DEEMPH1_SRC_SEL, 0x00000013 }, - { AUD_DEEMPH0_SHIFT, 0x00000000 }, - { AUD_DEEMPH1_SHIFT, 0x00000000 }, - { AUD_DEEMPH0_G0, 0x000004da }, - { AUD_DEEMPH0_A0, 0x0000777a }, - { AUD_DEEMPH0_B0, 0x00000000 }, - { AUD_DEEMPH0_A1, 0x0003f062 }, - { AUD_DEEMPH0_B1, 0x00000000 }, - { AUD_DEEMPH1_G0, 0x000004da }, - { AUD_DEEMPH1_A0, 0x0000777a }, - { AUD_DEEMPH1_B0, 0x00000000 }, - { AUD_DEEMPH1_A1, 0x0003f062 }, - { AUD_DEEMPH1_B1, 0x00000000 }, - { AUD_PLL_EN, 0x00000000 }, - { AUD_DMD_RA_DDS, 0x002a4efb }, - { AUD_RATE_ADJ1, 0x00001000 }, - { AUD_RATE_ADJ2, 0x00002000 }, - { AUD_RATE_ADJ3, 0x00003000 }, - { AUD_RATE_ADJ4, 0x00004000 }, - { AUD_RATE_ADJ5, 0x00005000 }, - { AUD_C2_UP_THR, 0x0000ffff }, - { AUD_C2_LO_THR, 0x0000e800 }, - { AUD_C1_UP_THR, 0x00008c00 }, - { AUD_C1_LO_THR, 0x00006c00 }, - - // ; Completely ditch AFC feedback - { AUD_DCOC_0_SRC, 0x00000021 }, - { AUD_DCOC_1_SRC, 0x0000001a }, - { AUD_DCOC1_SHIFT, 0x00000000 }, - { AUD_DCOC_1_SHIFT_IN0, 0x0000000a }, - { AUD_DCOC_1_SHIFT_IN1, 0x00000008 }, - { AUD_DCOC_PASS_IN, 0x00000000 }, - { AUD_IIR4_0_SEL, 0x00000023 }, - - // ; Completely ditc FM-2 AFC feedback - { AUD_DN1_AFC, 0x00000000 }, - { AUD_DCOC_2_SRC, 0x0000001b }, - { AUD_IIR4_1_SEL, 0x00000025 }, - - // ; WARNING!!! THIS CHANGE WAS NOT EXPECTED!!! - // ; Swap I & Q inputs into second rotator - // ; to reverse frequency and therefor invert - // ; phase from the cordic FM demodulator - // ; (frequency rotation must also be reversed - { AUD_DN2_SRC_SEL, 0x00000001 }, - { AUD_DN2_FREQ, 0x00003551 }, - - // setup Audio PLL - { AUD_PLL_PRESCALE, 0x00000002 }, - { AUD_PLL_INT, 0x0000001f }, - - { /* end of list */ }, + set_audio_start(dev, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO); + set_audio_registers(dev, a2_common); + switch (dev->tvaudio) { + case WW_A2_BG: + dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__); + set_audio_registers(dev, a2_table1); + break; + case WW_A2_DK: + dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__); + set_audio_registers(dev, a2_table2); + break; + case WW_A2_M: + dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__); + set_audio_registers(dev, a2_table3); + break; }; - - - dprintk("%s (status: WorksForMe[tm])\n",__FUNCTION__); - - if (0) { - /* old code */ - set_audio_start(dev, 0x0004, EN_DMTRX_SUMR | EN_A2_AUTO_STEREO); - set_audio_registers(dev, a2_old); - set_audio_finish(dev); - } else { - /* new code */ - set_audio_start(dev, 0x0004, EN_DMTRX_LR | EN_A2_AUTO_STEREO); - set_audio_registers(dev, a2); - set_audio_finish(dev); - } + set_audio_finish(dev); } static void set_audio_standard_EIAJ(struct cx8800_dev *dev) @@ -617,9 +670,9 @@ void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t) reg = cx_read(AUD_STATUS); mode = reg & 0x03; pilot = (reg >> 2) & 0x03; - dprintk("AUD_STATUS: %s / %s [status=0x%x,ctl=0x%x,vol=0x%x]\n", - m[mode], p[pilot], reg, - cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL)); + dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n", + reg, m[mode], p[pilot], + aud_ctl_names[cx_read(AUD_CTL) & 63]); t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; @@ -628,6 +681,8 @@ void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t) switch (dev->tvaudio) { case WW_A2_BG: + case WW_A2_DK: + case WW_A2_M: if (1 == pilot) { /* stereo */ t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; @@ -659,6 +714,8 @@ void cx88_set_stereo(struct cx8800_dev *dev, u32 mode) switch (dev->tvaudio) { case WW_A2_BG: + case WW_A2_DK: + case WW_A2_M: switch (mode) { case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_LANG1: @@ -717,6 +774,32 @@ void cx88_set_stereo(struct cx8800_dev *dev, u32 mode) return; } +/* just monitor the audio status for now ... */ +int cx88_audio_thread(void *data) +{ + struct cx8800_dev *dev = data; + struct v4l2_tuner t; + + daemonize("msp3400"); + allow_signal(SIGTERM); + dprintk("cx88: tvaudio thread started\n"); + + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ*3); + if (signal_pending(current)) + break; + if (dev->shutdown) + break; + + memset(&t,0,sizeof(t)); + cx88_get_stereo(dev,&t); + } + + dprintk("cx88: tvaudio thread exiting\n"); + complete_and_exit(&dev->texit, 0); +} + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index 5379e237332f..3c3806ebc779 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -28,17 +28,14 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f) f->fmt.vbi.count[0] = VBI_LINE_COUNT; f->fmt.vbi.count[1] = VBI_LINE_COUNT; - switch (dev->tvnorm->id) { - case V4L2_STD_NTSC_M: - case V4L2_STD_NTSC_M_JP: + if (dev->tvnorm->id & V4L2_STD_525_60) { + /* ntsc */ f->fmt.vbi.sampling_rate = 28636363; f->fmt.vbi.start[0] = 10 -1; f->fmt.vbi.start[1] = 273 -1; - break; - case V4L2_STD_PAL_BG: - case V4L2_STD_PAL_DK: - case V4L2_STD_PAL_I: - case V4L2_STD_SECAM: + + } else if (V4L2_STD_625_50) { + /* pal */ f->fmt.vbi.sampling_rate = 35468950; f->fmt.vbi.start[0] = 7 -1; f->fmt.vbi.start[1] = 319 -1; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index b1e5ddc6881b..91fdc67789b8 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -2,7 +2,7 @@ * device driver for Conexant 2388x based TV cards * video4linux video interface * - * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] + * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] * * 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 @@ -19,8 +19,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_VERSION__ 1 - #include <linux/init.h> #include <linux/list.h> #include <linux/module.h> @@ -32,6 +30,8 @@ #include "cx88.h" +#define V4L2_I2C_CLIENTS 1 + MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -194,8 +194,13 @@ static struct cx8800_tvnorm tvnorms[] = { .cxiformat = VideoFormatPAL60, .cxoformat = 0x181f0008, },{ - .name = "SECAM", - .id = V4L2_STD_SECAM, + .name = "SECAM-L", + .id = V4L2_STD_SECAM_L, + .cxiformat = VideoFormatSECAM, + .cxoformat = 0x181f0008, + },{ + .name = "SECAM-DK", + .id = V4L2_STD_SECAM_DK, .cxiformat = VideoFormatSECAM, .cxoformat = 0x181f0008, } @@ -483,35 +488,38 @@ static int set_tvaudio(struct cx8800_dev *dev) if (CX88_VMUX_TELEVISION != INPUT(dev->input)->type) return 0; - switch (dev->tvnorm->id) { - case V4L2_STD_PAL_BG: + if (V4L2_STD_PAL_BG & dev->tvnorm->id) { dev->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG; - break; - case V4L2_STD_PAL_DK: + + } else if (V4L2_STD_PAL_DK & dev->tvnorm->id) { dev->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK; - break; - case V4L2_STD_PAL_I: + + } else if (V4L2_STD_PAL_I & dev->tvnorm->id) { dev->tvaudio = WW_NICAM_I; - break; - case V4L2_STD_SECAM: - dev->tvaudio = WW_SYSTEM_L_AM; /* FIXME: fr != ru */ - break; - case V4L2_STD_NTSC_M: + + } else if (V4L2_STD_SECAM_L & dev->tvnorm->id) { + dev->tvaudio = WW_SYSTEM_L_AM; + + } else if (V4L2_STD_SECAM_DK & dev->tvnorm->id) { + dev->tvaudio = WW_A2_DK; + + } else if ((V4L2_STD_NTSC_M & dev->tvnorm->id) || + (V4L2_STD_PAL_M & dev->tvnorm->id)) { dev->tvaudio = WW_BTSC; - break; - case V4L2_STD_NTSC_M_JP: + + } else if (V4L2_STD_NTSC_M_JP & dev->tvnorm->id) { dev->tvaudio = WW_EIAJ; - break; - default: - dprintk(1,"tvaudio support needs work for this tv norm [%s], sorry\n", - dev->tvnorm->name); + + } else { + printk("%s: tvaudio support needs work for this tv norm [%s], sorry\n", + dev->name, dev->tvnorm->name); dev->tvaudio = 0; return 0; } cx_andor(MO_AFECFG_IO, 0x1f, 0x0); cx88_set_tvaudio(dev); - cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); + // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); cx_write(MO_AUDD_LNGTH, 128/8); /* fifo size */ cx_write(MO_AUDR_LNGTH, 128/8); /* fifo size */ @@ -526,7 +534,6 @@ static int set_tvnorm(struct cx8800_dev *dev, struct cx8800_tvnorm *norm) u32 vdec_clock; u64 tmp64; u32 bdelay,agcdelay,htotal; - struct video_channel c; dev->tvnorm = norm; fsc8 = norm_fsc8(norm); @@ -592,30 +599,43 @@ static int set_tvnorm(struct cx8800_dev *dev, struct cx8800_tvnorm *norm) set_tvaudio(dev); // tell i2c chips - memset(&c,0,sizeof(c)); - c.channel = dev->input; - c.norm = VIDEO_MODE_PAL; - if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP))) - c.norm = VIDEO_MODE_NTSC; - if (norm->id & V4L2_STD_SECAM) - c.norm = VIDEO_MODE_SECAM; - cx8800_call_i2c_clients(dev,VIDIOCSCHAN,&c); +#ifdef V4L2_I2C_CLIENTS + cx8800_call_i2c_clients(dev,VIDIOC_S_STD,&norm->id); +#else + { + struct video_channel c; + memset(&c,0,sizeof(c)); + c.channel = dev->input; + c.norm = VIDEO_MODE_PAL; + if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP))) + c.norm = VIDEO_MODE_NTSC; + if (norm->id & V4L2_STD_SECAM) + c.norm = VIDEO_MODE_SECAM; + cx8800_call_i2c_clients(dev,VIDIOCSCHAN,&c); + } +#endif // done return 0; } static int set_scale(struct cx8800_dev *dev, unsigned int width, unsigned int height, - int interlaced) + enum v4l2_field field) { unsigned int swidth = norm_swidth(dev->tvnorm); unsigned int sheight = norm_maxh(dev->tvnorm); u32 value; - dprintk(1,"set_scale: %dx%d [%s]\n", width, height, dev->tvnorm->name); + dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height, + V4L2_FIELD_HAS_TOP(field) ? "T" : "", + V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "", + dev->tvnorm->name); + if (!V4L2_FIELD_HAS_BOTH(field)) + height *= 2; // recalc H delay and scale registers value = (width * norm_hdelay(dev->tvnorm)) / swidth; + value &= 0x3fe; cx_write(MO_HDELAY_EVEN, value); cx_write(MO_HDELAY_ODD, value); dprintk(1,"set_scale: hdelay 0x%04x\n", value); @@ -646,7 +666,7 @@ static int set_scale(struct cx8800_dev *dev, unsigned int width, unsigned int he // setup filters value = 0; value |= (1 << 19); // CFILT (default) - if (interlaced) + if (V4L2_FIELD_INTERLACED == field) value |= (1 << 3); // VINT (interlaced vertical scaling) if (width < 385) value |= (1 << 0); // 3-tap interpolation @@ -675,10 +695,12 @@ static int video_mux(struct cx8800_dev *dev, unsigned int input) switch (INPUT(input)->type) { case CX88_VMUX_SVIDEO: - cx_andor(MO_AFECFG_IO, 0x01, 0x01); + cx_set(MO_AFECFG_IO, 0x00000001); + cx_set(MO_INPUT_FORMAT, 0x00010010); break; default: - cx_andor(MO_AFECFG_IO, 0x01, 0x00); + cx_clear(MO_AFECFG_IO, 0x00000001); + cx_clear(MO_INPUT_FORMAT, 0x00010010); break; } return 0; @@ -693,7 +715,7 @@ static int start_video_dma(struct cx8800_dev *dev, /* setup fifo + format */ cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH21], buf->bpl, buf->risc.dma); - set_scale(dev, buf->vb.width, buf->vb.height, 1); + set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field); cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma); /* reset counter */ @@ -1350,6 +1372,9 @@ static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) case V4L2_CID_AUDIO_BALANCE: ctl->value = (value & 0x40) ? (value & 0x3f) : (0x40 - (value & 0x3f)); break; + case V4L2_CID_AUDIO_VOLUME: + ctl->value = 0x3f - (value & 0x3f); + break; default: ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift; break; @@ -1378,6 +1403,9 @@ static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) case V4L2_CID_AUDIO_BALANCE: value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value; break; + case V4L2_CID_AUDIO_VOLUME: + value = 0x3f - (ctl->value & 0x3f); + break; case V4L2_CID_SATURATION: /* special v_sat handling */ v_sat_value = ctl->value - (0x7f - 0x5a); @@ -1409,7 +1437,7 @@ static void init_controls(struct cx8800_dev *dev) }; static struct v4l2_control volume = { .id = V4L2_CID_AUDIO_VOLUME, - .value = 0, + .value = 0x3f, }; set_control(dev,&mute); @@ -1459,15 +1487,12 @@ static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, maxw = norm_maxw(dev->tvnorm); maxh = norm_maxh(dev->tvnorm); -#if 0 if (V4L2_FIELD_ANY == field) { field = (f->fmt.pix.height > maxh/2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; } -#else - field = V4L2_FIELD_INTERLACED; -#endif + switch (field) { case V4L2_FIELD_TOP: case V4L2_FIELD_BOTTOM: @@ -1480,14 +1505,15 @@ static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, } f->fmt.pix.field = field; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; if (f->fmt.pix.height < 32) f->fmt.pix.height = 32; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; if (f->fmt.pix.height > maxh) f->fmt.pix.height = maxh; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + f->fmt.pix.width &= ~0x03; f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = @@ -1783,7 +1809,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; down(&dev->lock); dev->freq = f->frequency; +#ifdef V4L2_I2C_CLIENTS + cx8800_call_i2c_clients(dev,VIDIOC_S_FREQUENCY,f); +#else cx8800_call_i2c_clients(dev,VIDIOCSFREQ,&dev->freq); +#endif up(&dev->lock); return 0; } @@ -1885,7 +1915,6 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_TUNER: { struct v4l2_tuner *t = arg; - struct video_tuner vt; if (t->index > 0) return -EINVAL; @@ -1895,9 +1924,16 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, t->rangelow = (int)(65*16); t->rangehigh = (int)(108*16); - memset(&vt,0,sizeof(vt)); - cx8800_call_i2c_clients(dev,VIDIOCGTUNER,&vt); - t->signal = vt.signal; +#ifdef V4L2_I2C_CLIENTS + cx8800_call_i2c_clients(dev,VIDIOC_G_TUNER,t); +#else + { + struct video_tuner vt; + memset(&vt,0,sizeof(vt)); + cx8800_call_i2c_clients(dev,VIDIOCGTUNER,&vt); + t->signal = vt.signal; + } +#endif return 0; } case VIDIOC_ENUMINPUT: @@ -2281,11 +2317,6 @@ static void cx8800_unregister_video(struct cx8800_dev *dev) } } -/* debug that damn oops ... */ -static unsigned int oops = 0; -MODULE_PARM(oops,"i"); -#define OOPS(msg) if (oops) printk("%s: %s\n",__FUNCTION__,msg); - static int __devinit cx8800_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { @@ -2299,7 +2330,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, memset(dev,0,sizeof(*dev)); /* pci init */ - OOPS("pci init"); dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { err = -EIO; @@ -2308,7 +2338,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, sprintf(dev->name,"cx%x[%d]",pci_dev->device,cx8800_devcount); /* pci quirks */ - OOPS("pci quirks"); cx88_pci_quirks(dev->name, dev->pci, &latency); if (UNSET != latency) { printk(KERN_INFO "%s: setting pci latency timer to %d\n", @@ -2317,7 +2346,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, } /* print pci info */ - OOPS("pci info"); pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " @@ -2333,14 +2361,15 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, } /* board config */ - OOPS("board config"); dev->board = card[cx8800_devcount]; for (i = 0; UNSET == dev->board && i < cx88_idcount; i++) if (pci_dev->subsystem_vendor == cx88_subids[i].subvendor && pci_dev->subsystem_device == cx88_subids[i].subdevice) dev->board = cx88_subids[i].card; - if (UNSET == dev->board) + if (UNSET == dev->board) { dev->board = CX88_BOARD_UNKNOWN; + cx88_card_list(dev); + } printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", dev->name,pci_dev->subsystem_vendor, pci_dev->subsystem_device,cx88_boards[dev->board].name, @@ -2352,7 +2381,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, dev->tuner_type = cx88_boards[dev->board].tuner_type; /* get mmio */ - OOPS("get mmio"); if (!request_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0), dev->name)) { @@ -2366,7 +2394,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, dev->bmmio = (u8*)dev->lmmio; /* initialize driver struct */ - OOPS("init structs"); init_MUTEX(&dev->lock); dev->slock = SPIN_LOCK_UNLOCKED; dev->tvnorm = tvnorms; @@ -2390,11 +2417,9 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, MO_VID_DMACNTRL,0x88,0x00); /* initialize hardware */ - OOPS("reset hardware"); cx8800_reset(dev); /* get irq */ - OOPS("install irq handler"); err = request_irq(pci_dev->irq, cx8800_irq, SA_SHIRQ | SA_INTERRUPT, dev->name, dev); if (err < 0) { @@ -2404,13 +2429,10 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, } /* register i2c bus + load i2c helpers */ - OOPS("i2c setup"); cx8800_i2c_init(dev); - OOPS("card setup"); cx88_card_setup(dev); /* load and configure helper modules */ - OOPS("configure i2c clients"); if (TUNER_ABSENT != dev->tuner_type) request_module("tuner"); if (cx88_boards[dev->board].needs_tda9887) @@ -2419,7 +2441,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, cx8800_call_i2c_clients(dev,TUNER_SET_TYPE,&dev->tuner_type); /* register v4l devices */ - OOPS("register video"); dev->video_dev = vdev_init(dev,&cx8800_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, video_nr[cx8800_devcount]); @@ -2431,7 +2452,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, printk(KERN_INFO "%s: registered device video%d [v4l2]\n", dev->name,dev->video_dev->minor & 0x1f); - OOPS("register vbi"); dev->vbi_dev = vdev_init(dev,&cx8800_vbi_template,"vbi"); err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, vbi_nr[cx8800_devcount]); @@ -2444,7 +2464,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, dev->name,dev->vbi_dev->minor & 0x1f); if (dev->has_radio) { - OOPS("register radio"); dev->radio_dev = vdev_init(dev,&cx8800_radio_template,"radio"); err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, radio_nr[cx8800_devcount]); @@ -2458,32 +2477,31 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, } /* everything worked */ - OOPS("finalize"); list_add_tail(&dev->devlist,&cx8800_devlist); pci_set_drvdata(pci_dev,dev); cx8800_devcount++; /* initial device configuration */ - OOPS("init device"); down(&dev->lock); init_controls(dev); set_tvnorm(dev,tvnorms); video_mux(dev,0); up(&dev->lock); + + /* start tvaudio thread */ + init_completion(&dev->texit); + dev->tpid = kernel_thread(cx88_audio_thread, dev, 0); return 0; fail3: - OOPS("fail3"); cx8800_unregister_video(dev); if (0 == dev->i2c_rc) i2c_bit_del_bus(&dev->i2c_adap); free_irq(pci_dev->irq, dev); fail2: - OOPS("fail2"); release_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0)); fail1: - OOPS("fail1"); kfree(dev); return err; } @@ -2492,6 +2510,11 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) { struct cx8800_dev *dev = pci_get_drvdata(pci_dev); + /* stop thread */ + dev->shutdown = 1; + if (dev->tpid >= 0) + wait_for_completion(&dev->texit); + cx8800_shutdown(dev); pci_disable_device(pci_dev); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index cf77b6d9b11e..f7e6f0b7e15c 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -32,7 +32,7 @@ #include "cx88-reg.h" #include <linux/version.h> -#define CX88_VERSION_CODE KERNEL_VERSION(0,0,3) +#define CX88_VERSION_CODE KERNEL_VERSION(0,0,4) #ifndef TRUE # define TRUE (1==1) @@ -114,17 +114,20 @@ extern struct sram_channel cx88_sram_channels[]; /* card configuration */ #define CX88_BOARD_NOAUTO UNSET -#define CX88_BOARD_UNKNOWN 0 -#define CX88_BOARD_HAUPPAUGE 1 -#define CX88_BOARD_GDI 2 -#define CX88_BOARD_PIXELVIEW 3 -#define CX88_BOARD_ATI_WONDER_PRO 4 -#define CX88_BOARD_WINFAST2000XP 5 -#define CX88_BOARD_AVERTV_303 6 -#define CX88_BOARD_MSI_TVANYWHERE 7 -#define CX88_BOARD_WINFAST_DV2000 8 -#define CX88_BOARD_LEADTEK_PVR2000 9 - +#define CX88_BOARD_UNKNOWN 0 +#define CX88_BOARD_HAUPPAUGE 1 +#define CX88_BOARD_GDI 2 +#define CX88_BOARD_PIXELVIEW 3 +#define CX88_BOARD_ATI_WONDER_PRO 4 +#define CX88_BOARD_WINFAST2000XP 5 +#define CX88_BOARD_AVERTV_303 6 +#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7 +#define CX88_BOARD_WINFAST_DV2000 8 +#define CX88_BOARD_LEADTEK_PVR2000 9 +#define CX88_BOARD_IODATA_GVVCP3PCI 10 +#define CX88_BOARD_PROLINK_PLAYTVPVR 11 +#define CX88_BOARD_ASUS_PVR_416 12 +#define CX88_BOARD_MSI_TVANYWHERE 13 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -263,6 +266,9 @@ struct cx8800_dev { /* other global state info */ u32 shadow[SHADOW_MAX]; + int shutdown; + pid_t tpid; + struct completion texit; struct cx8800_suspend_state state; }; @@ -351,7 +357,8 @@ extern const unsigned int cx88_bcount; extern struct cx88_subid cx88_subids[]; extern const unsigned int cx88_idcount; -extern void __devinit cx88_card_setup(struct cx8800_dev *dev); +extern void cx88_card_list(struct cx8800_dev *dev); +extern void cx88_card_setup(struct cx8800_dev *dev); /* ----------------------------------------------------------- */ /* cx88-tvaudio.c */ @@ -372,6 +379,7 @@ extern void __devinit cx88_card_setup(struct cx8800_dev *dev); void cx88_set_tvaudio(struct cx8800_dev *dev); void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t); void cx88_set_stereo(struct cx8800_dev *dev, u32 mode); +int cx88_audio_thread(void *data); /* * Local variables: diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index 0298392e7c93..30cce6bec7b1 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c @@ -1,3 +1,4 @@ + /* * Copyright (c) 2003 Gerd Knorr * Copyright (c) 2003 Pavel Machek @@ -32,47 +33,45 @@ /* ---------------------------------------------------------------------- */ static IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { - [ 17 ] = KEY_KP0, - [ 20 ] = KEY_KP1, - [ 12 ] = KEY_KP2, - [ 28 ] = KEY_KP3, - [ 18 ] = KEY_KP4, - [ 10 ] = KEY_KP5, - [ 26 ] = KEY_KP6, - [ 22 ] = KEY_KP7, - [ 14 ] = KEY_KP8, - [ 30 ] = KEY_KP9, - - [ 24 ] = KEY_EJECTCD, // Unmarked on my controller + [ 34 ] = KEY_KP0, + [ 40 ] = KEY_KP1, + [ 24 ] = KEY_KP2, + [ 56 ] = KEY_KP3, + [ 36 ] = KEY_KP4, + [ 20 ] = KEY_KP5, + [ 52 ] = KEY_KP6, + [ 44 ] = KEY_KP7, + [ 28 ] = KEY_KP8, + [ 60 ] = KEY_KP9, + + [ 48 ] = KEY_EJECTCD, // Unmarked on my controller [ 0 ] = KEY_POWER, - [ 9 ] = BTN_LEFT, // DISPLAY/L - [ 25 ] = BTN_RIGHT, // LOOP/R - [ 5 ] = KEY_MUTE, - [ 19 ] = KEY_RECORD, - [ 11 ] = KEY_PAUSE, - [ 27 ] = KEY_STOP, - [ 15 ] = KEY_VOLUMEDOWN, - [ 31 ] = KEY_VOLUMEUP, - - [ 16 ] = KEY_TUNER, // TV/FM - [ 8 ] = KEY_CD, - [ 4 ] = KEY_VIDEO, - [ 2 ] = KEY_AUDIO, - [ 6 ] = KEY_ZOOM, // full screen - [ 1 ] = KEY_INFO, // preview - [ 21 ] = KEY_SEARCH, // autoscan - [ 13 ] = KEY_STOP, // freeze - [ 29 ] = KEY_RECORD, // capture - [ 3 ] = KEY_PLAY, // unmarked - [ 23 ] = KEY_RED, // unmarked - [ 7 ] = KEY_GREEN, // unmarked - -#if 0 - [ 16 ] = KEY_YELLOW, // unmarked - [ 8 ] = KEY_CHANNELDOWN, - [ 24 ] = KEY_CHANNELUP, - [ 0 ] = KEY_BLUE, // unmarked -#endif + [ 18 ] = BTN_LEFT, // DISPLAY/L + [ 50 ] = BTN_RIGHT, // LOOP/R + [ 10 ] = KEY_MUTE, + [ 38 ] = KEY_RECORD, + [ 22 ] = KEY_PAUSE, + [ 54 ] = KEY_STOP, + [ 30 ] = KEY_VOLUMEDOWN, + [ 62 ] = KEY_VOLUMEUP, + + [ 32 ] = KEY_TUNER, // TV/FM + [ 16 ] = KEY_CD, + [ 8 ] = KEY_VIDEO, + [ 4 ] = KEY_AUDIO, + [ 12 ] = KEY_ZOOM, // full screen + [ 2 ] = KEY_INFO, // preview + [ 42 ] = KEY_SEARCH, // autoscan + [ 26 ] = KEY_STOP, // freeze + [ 58 ] = KEY_RECORD, // capture + [ 6 ] = KEY_PLAY, // unmarked + [ 46 ] = KEY_RED, // unmarked + [ 14 ] = KEY_GREEN, // unmarked + + [ 33 ] = KEY_YELLOW, // unmarked + [ 17 ] = KEY_CHANNELDOWN, + [ 49 ] = KEY_CHANNELUP, + [ 1 ] = KEY_BLUE, // unmarked }; static IR_KEYTAB_TYPE winfast_codes[IR_KEYTAB_SIZE] = { @@ -280,8 +279,9 @@ static int ir_probe(struct device *dev) case BTTV_AVPHONE98: case BTTV_AVERMEDIA98: ir_codes = ir_codes_avermedia; - ir->mask_keycode = 0xf80000; + ir->mask_keycode = 0xf88000; ir->mask_keydown = 0x010000; + ir->polling = 50; // ms break; case BTTV_PXELVWPLTVPAK: @@ -300,7 +300,7 @@ static int ir_probe(struct device *dev) case BTTV_WINFAST2000: ir_codes = winfast_codes; - ir->mask_keycode = 0x8f8; + ir->mask_keycode = 0x1f8; break; case BTTV_MAGICTVIEW061: case BTTV_MAGICTVIEW063: diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 8b4f0f5f22d7..95890637355e 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -77,6 +77,56 @@ static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { [ 15 ] = KEY_SELECT, // SOURCE [ 10 ] = KEY_KPPLUS, // +100 [ 20 ] = KEY_KPEQUAL, // SYNC + [ 28 ] = KEY_MEDIA, // PC/TV +}; + +static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { + [ 0x3 ] = KEY_POWER, + [ 0x6f ] = KEY_MUTE, + [ 0x10 ] = KEY_BACKSPACE, // Recall + + [ 0x11 ] = KEY_KP0, + [ 0x4 ] = KEY_KP1, + [ 0x5 ] = KEY_KP2, + [ 0x6 ] = KEY_KP3, + [ 0x8 ] = KEY_KP4, + [ 0x9 ] = KEY_KP5, + [ 0xa ] = KEY_KP6, + [ 0xc ] = KEY_KP7, + [ 0xd ] = KEY_KP8, + [ 0xe ] = KEY_KP9, + [ 0x12 ] = KEY_KPDOT, // 100+ + + [ 0x7 ] = KEY_VOLUMEUP, + [ 0xb ] = KEY_VOLUMEDOWN, + [ 0x1a ] = KEY_KPPLUS, + [ 0x18 ] = KEY_KPMINUS, + [ 0x15 ] = KEY_UP, + [ 0x1d ] = KEY_DOWN, + [ 0xf ] = KEY_CHANNELUP, + [ 0x13 ] = KEY_CHANNELDOWN, + [ 0x48 ] = KEY_ZOOM, + + [ 0x1b ] = KEY_VIDEO, // Video source +#if 0 + [ 0x1f ] = KEY_S, // Snapshot +#endif + [ 0x49 ] = KEY_LANGUAGE, // MTS Select + [ 0x19 ] = KEY_SEARCH, // Auto Scan + + [ 0x4b ] = KEY_RECORD, + [ 0x46 ] = KEY_PLAY, + [ 0x45 ] = KEY_PAUSE, // Pause + [ 0x44 ] = KEY_STOP, +#if 0 + [ 0x43 ] = KEY_T, // Time Shift + [ 0x47 ] = KEY_Y, // Time Shift OFF + [ 0x4a ] = KEY_O, // TOP + [ 0x17 ] = KEY_F, // SURF CH +#endif + [ 0x40 ] = KEY_FORWARD, // Forward ? + [ 0x42 ] = KEY_REWIND, // Backward ? + }; struct IR; @@ -202,11 +252,33 @@ static int get_key_knc1(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } +static int get_key_purpletv(struct IR *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char b; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c,&b,1)) { + dprintk(1,"read error\n"); + return -EIO; + } + + /* no button press */ + if (b==0) + return 0; + + /* repeating */ + if (b & 0x80) + return 1; + + *ir_key = b; + *ir_raw = b; + return 1; +} /* ----------------------------------------------------------------------- */ static void ir_key_poll(struct IR *ir) { - u32 ir_key, ir_raw; + static u32 ir_key, ir_raw; int rc; dprintk(2,"ir_poll_key\n"); @@ -300,6 +372,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_type = IR_TYPE_OTHER; ir_codes = ir_codes_empty; break; + case 0x7a: + name = "Purple TV"; + ir->get_key = get_key_purpletv; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_purpletv; + break; default: /* shouldn't happen */ printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr); @@ -320,7 +398,8 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->input.name = ir->c.name; ir->input.phys = ir->phys; input_register_device(&ir->input); - printk(DEVNAME ": %s detected at %s\n",ir->input.name,ir->input.phys); + printk(DEVNAME ": %s detected at %s [%s]\n", + ir->input.name,ir->input.phys,adap->name); /* start polling via eventd */ INIT_WORK(&ir->work, ir_work, ir); @@ -361,22 +440,33 @@ static int ir_probe(struct i2c_adapter *adap) That's why we probe 0x1a (~0x34) first. CB */ - static const int probe[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; + static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; + static const int probe_saa7134[] = { 0x7a, -1}; + const int *probe = NULL; struct i2c_client c; char buf; int i,rc; - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) { - memset(&c,0,sizeof(c)); - c.adapter = adap; - for (i = 0; -1 != probe[i]; i++) { - c.addr = probe[i]; - rc = i2c_master_recv(&c,&buf,1); - dprintk(1,"probe 0x%02x @ %s: %s\n", - probe[i], adap->name, - (1 == rc) ? "yes" : "no"); - if (1 == rc) { - ir_attach(adap,probe[i],0,0); - break; - } + switch (adap->id) { + case I2C_ALGO_BIT | I2C_HW_B_BT848: + probe = probe_bttv; + break; + case I2C_ALGO_SAA7134: + probe = probe_saa7134; + break; + } + if (NULL == probe) + return 0; + + memset(&c,0,sizeof(c)); + c.adapter = adap; + for (i = 0; -1 != probe[i]; i++) { + c.addr = probe[i]; + rc = i2c_master_recv(&c,&buf,1); + dprintk(1,"probe 0x%02x @ %s: %s\n", + probe[i], adap->name, + (1 == rc) ? "yes" : "no"); + if (1 == rc) { + ir_attach(adap,probe[i],0,0); + break; } } return 0; diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index e2ecf212ccfc..41adfef5c715 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -51,6 +51,7 @@ #include <asm/pgtable.h> #include <media/audiochip.h> +#include <media/id.h> #include "msp3400.h" /* insmod parameters */ @@ -80,7 +81,7 @@ struct msp3400c { int input; int muted; - int left, right; /* volume */ + int volume, balance; int bass, treble; /* shadow register set */ @@ -378,26 +379,24 @@ static void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2) } static void msp3400c_setvolume(struct i2c_client *client, - int muted, int left, int right) + int muted, int volume, int balance) { - int vol = 0,val = 0,balance = 0; + int val = 0, bal = 0; if (!muted) { - vol = (left > right) ? left : right; - val = (vol * 0x73 / 65535) << 8; + val = (volume * 0x73 / 65535) << 8; } - if (vol > 0) { - balance = ((right-left) * 127) / vol; + if (val) { + bal = (balance / 256) - 128; } - dprintk(KERN_DEBUG "msp34xx: setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n", - muted ? "on" : "off", left, right, val>>8, balance); + muted ? "on" : "off", volume, balance, val>>8, bal); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */ /* scart - on/off only */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007, val ? 0x4000 : 0); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0001, balance << 8); + msp3400c_write(client,I2C_MSP3400C_DFP, 0x0001, bal << 8); } static void msp3400c_setbass(struct i2c_client *client, int bass) @@ -815,7 +814,7 @@ static int msp3400c_thread(void *data) /* no carrier scan, just unmute */ printk("msp3400: thread: no carrier scan\n"); msp3400c_setvolume(client, msp->muted, - msp->left, msp->right); + msp->volume, msp->balance); continue; } msp->restart = 0; @@ -960,7 +959,8 @@ static int msp3400c_thread(void *data) } /* unmute + restore dfp registers */ - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); + msp3400c_setvolume(client, msp->muted, + msp->volume, msp->balance); msp3400c_restore_dfp(client); if (msp->watch_stereo) @@ -1042,7 +1042,7 @@ static int msp3410d_thread(void *data) /* no carrier scan needed, just unmute */ dprintk(KERN_DEBUG "msp3410: thread: no carrier scan\n"); msp3400c_setvolume(client, msp->muted, - msp->left, msp->right); + msp->volume, msp->balance); continue; } msp->restart = 0; @@ -1194,7 +1194,8 @@ static int msp3410d_thread(void *data) /* unmute + restore dfp registers */ msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); + msp3400c_setvolume(client, msp->muted, + msp->volume, msp->balance); msp3400c_restore_dfp(client); if (msp->watch_stereo) @@ -1257,8 +1258,8 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) } memset(msp,0,sizeof(struct msp3400c)); - msp->left = 65535; - msp->right = 65535; + msp->volume = 65535; + msp->balance = 32768; msp->bass = 32768; msp->treble = 32768; msp->input = -1; @@ -1290,7 +1291,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) /* this will turn on a 1kHz beep - might be useful for debugging... */ msp3400c_write(c,I2C_MSP3400C_DFP, 0x0014, 0x1040); #endif - msp3400c_setvolume(c,msp->muted,msp->left,msp->right); + msp3400c_setvolume(c, msp->muted, msp->volume, msp->balance); snprintf(c->name, sizeof(c->name), "MSP34%02d%c-%c%d", (msp->rev2>>8)&0xff, (msp->rev1&0xff)+'@', @@ -1440,8 +1441,10 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } else { /* set msp3400 to FM radio mode */ msp3400c_setmode(client,MSP_MODE_FM_RADIO); - msp3400c_setcarrier(client, MSP_CARRIER(10.7),MSP_CARRIER(10.7)); - msp3400c_setvolume(client,msp->muted,msp->left,msp->right); + msp3400c_setcarrier(client, MSP_CARRIER(10.7), + MSP_CARRIER(10.7)); + msp3400c_setvolume(client, msp->muted, + msp->volume, msp->balance); } if (msp->active) msp->restart = 1; @@ -1488,16 +1491,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) VIDEO_AUDIO_MUTABLE; if (msp->muted) va->flags |= VIDEO_AUDIO_MUTE; - va->volume=max(msp->left,msp->right); - if (0 == va->volume) { - va->balance = 32768; - } else { - va->balance = (32768 * min(msp->left,msp->right)) - / va->volume; - va->balance = (msp->left<msp->right) ? - (65535 - va->balance) : va->balance; - } + va->volume = msp->volume; + va->balance = (va->volume) ? msp->balance : 32768; va->bass = msp->bass; va->treble = msp->treble; @@ -1513,13 +1509,13 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk(KERN_DEBUG "msp34xx: VIDIOCSAUDIO\n"); msp->muted = (va->flags & VIDEO_AUDIO_MUTE); - msp->left = (min(65536 - va->balance,32768) * - va->volume) / 32768; - msp->right = (min(va->balance,(__u16)32768) * - va->volume) / 32768; + msp->volume = va->volume; + msp->balance = va->balance; msp->bass = va->bass; msp->treble = va->treble; - msp3400c_setvolume(client,msp->muted,msp->left,msp->right); + + msp3400c_setvolume(client, msp->muted, + msp->volume, msp->balance); msp3400c_setbass(client,msp->bass); msp3400c_settreble(client,msp->treble); diff --git a/drivers/media/video/ovcamchip/Makefile b/drivers/media/video/ovcamchip/Makefile new file mode 100644 index 000000000000..bca41ad93de8 --- /dev/null +++ b/drivers/media/video/ovcamchip/Makefile @@ -0,0 +1,4 @@ +ovcamchip-objs := ovcamchip_core.o ov6x20.o ov6x30.o ov7x10.o ov7x20.o \ + ov76be.o + +obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip.o diff --git a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c new file mode 100644 index 000000000000..3433619ad93f --- /dev/null +++ b/drivers/media/video/ovcamchip/ov6x20.c @@ -0,0 +1,415 @@ +/* OmniVision OV6620/OV6120 Camera Chip Support Code + * + * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> + * http://alpha.dyndns.org/ov511/ + * + * 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. NO WARRANTY OF ANY KIND is expressed or implied. + */ + +#define DEBUG + +#include <linux/slab.h> +#include "ovcamchip_priv.h" + +/* Registers */ +#define REG_GAIN 0x00 /* gain [5:0] */ +#define REG_BLUE 0x01 /* blue gain */ +#define REG_RED 0x02 /* red gain */ +#define REG_SAT 0x03 /* saturation */ +#define REG_CNT 0x05 /* Y contrast */ +#define REG_BRT 0x06 /* Y brightness */ +#define REG_WB_BLUE 0x0C /* WB blue ratio [5:0] */ +#define REG_WB_RED 0x0D /* WB red ratio [5:0] */ +#define REG_EXP 0x10 /* exposure */ + +/* Window parameters */ +#define HWSBASE 0x38 +#define HWEBASE 0x3A +#define VWSBASE 0x05 +#define VWEBASE 0x06 + +struct ov6x20 { + int auto_brt; + int auto_exp; + int backlight; + int bandfilt; + int mirror; +}; + +/* Initial values for use with OV511/OV511+ cameras */ +static struct ovcamchip_regvals regvals_init_6x20_511[] = { + { 0x12, 0x80 }, /* reset */ + { 0x11, 0x01 }, + { 0x03, 0x60 }, + { 0x05, 0x7f }, /* For when autoadjust is off */ + { 0x07, 0xa8 }, + { 0x0c, 0x24 }, + { 0x0d, 0x24 }, + { 0x0f, 0x15 }, /* COMS */ + { 0x10, 0x75 }, /* AEC Exposure time */ + { 0x12, 0x24 }, /* Enable AGC and AWB */ + { 0x14, 0x04 }, + { 0x16, 0x03 }, + { 0x26, 0xb2 }, /* BLC enable */ + /* 0x28: 0x05 Selects RGB format if RGB on */ + { 0x28, 0x05 }, + { 0x2a, 0x04 }, /* Disable framerate adjust */ + { 0x2d, 0x99 }, + { 0x33, 0xa0 }, /* Color Processing Parameter */ + { 0x34, 0xd2 }, /* Max A/D range */ + { 0x38, 0x8b }, + { 0x39, 0x40 }, + + { 0x3c, 0x39 }, /* Enable AEC mode changing */ + { 0x3c, 0x3c }, /* Change AEC mode */ + { 0x3c, 0x24 }, /* Disable AEC mode changing */ + + { 0x3d, 0x80 }, + /* These next two registers (0x4a, 0x4b) are undocumented. They + * control the color balance */ + { 0x4a, 0x80 }, + { 0x4b, 0x80 }, + { 0x4d, 0xd2 }, /* This reduces noise a bit */ + { 0x4e, 0xc1 }, + { 0x4f, 0x04 }, + { 0xff, 0xff }, /* END MARKER */ +}; + +/* Initial values for use with OV518 cameras */ +static struct ovcamchip_regvals regvals_init_6x20_518[] = { + { 0x12, 0x80 }, /* Do a reset */ + { 0x03, 0xc0 }, /* Saturation */ + { 0x05, 0x8a }, /* Contrast */ + { 0x0c, 0x24 }, /* AWB blue */ + { 0x0d, 0x24 }, /* AWB red */ + { 0x0e, 0x8d }, /* Additional 2x gain */ + { 0x0f, 0x25 }, /* Black expanding level = 1.3V */ + { 0x11, 0x01 }, /* Clock div. */ + { 0x12, 0x24 }, /* Enable AGC and AWB */ + { 0x13, 0x01 }, /* (default) */ + { 0x14, 0x80 }, /* Set reserved bit 7 */ + { 0x15, 0x01 }, /* (default) */ + { 0x16, 0x03 }, /* (default) */ + { 0x17, 0x38 }, /* (default) */ + { 0x18, 0xea }, /* (default) */ + { 0x19, 0x04 }, + { 0x1a, 0x93 }, + { 0x1b, 0x00 }, /* (default) */ + { 0x1e, 0xc4 }, /* (default) */ + { 0x1f, 0x04 }, /* (default) */ + { 0x20, 0x20 }, /* Enable 1st stage aperture correction */ + { 0x21, 0x10 }, /* Y offset */ + { 0x22, 0x88 }, /* U offset */ + { 0x23, 0xc0 }, /* Set XTAL power level */ + { 0x24, 0x53 }, /* AEC bright ratio */ + { 0x25, 0x7a }, /* AEC black ratio */ + { 0x26, 0xb2 }, /* BLC enable */ + { 0x27, 0xa2 }, /* Full output range */ + { 0x28, 0x01 }, /* (default) */ + { 0x29, 0x00 }, /* (default) */ + { 0x2a, 0x84 }, /* (default) */ + { 0x2b, 0xa8 }, /* Set custom frame rate */ + { 0x2c, 0xa0 }, /* (reserved) */ + { 0x2d, 0x95 }, /* Enable banding filter */ + { 0x2e, 0x88 }, /* V offset */ + { 0x33, 0x22 }, /* Luminance gamma on */ + { 0x34, 0xc7 }, /* A/D bias */ + { 0x36, 0x12 }, /* (reserved) */ + { 0x37, 0x63 }, /* (reserved) */ + { 0x38, 0x8b }, /* Quick AEC/AEB */ + { 0x39, 0x00 }, /* (default) */ + { 0x3a, 0x0f }, /* (default) */ + { 0x3b, 0x3c }, /* (default) */ + { 0x3c, 0x5c }, /* AEC controls */ + { 0x3d, 0x80 }, /* Drop 1 (bad) frame when AEC change */ + { 0x3e, 0x80 }, /* (default) */ + { 0x3f, 0x02 }, /* (default) */ + { 0x40, 0x10 }, /* (reserved) */ + { 0x41, 0x10 }, /* (reserved) */ + { 0x42, 0x00 }, /* (reserved) */ + { 0x43, 0x7f }, /* (reserved) */ + { 0x44, 0x80 }, /* (reserved) */ + { 0x45, 0x1c }, /* (reserved) */ + { 0x46, 0x1c }, /* (reserved) */ + { 0x47, 0x80 }, /* (reserved) */ + { 0x48, 0x5f }, /* (reserved) */ + { 0x49, 0x00 }, /* (reserved) */ + { 0x4a, 0x00 }, /* Color balance (undocumented) */ + { 0x4b, 0x80 }, /* Color balance (undocumented) */ + { 0x4c, 0x58 }, /* (reserved) */ + { 0x4d, 0xd2 }, /* U *= .938, V *= .838 */ + { 0x4e, 0xa0 }, /* (default) */ + { 0x4f, 0x04 }, /* UV 3-point average */ + { 0x50, 0xff }, /* (reserved) */ + { 0x51, 0x58 }, /* (reserved) */ + { 0x52, 0xc0 }, /* (reserved) */ + { 0x53, 0x42 }, /* (reserved) */ + { 0x27, 0xa6 }, /* Enable manual offset adj. (reg 21 & 22) */ + { 0x12, 0x20 }, + { 0x12, 0x24 }, + + { 0xff, 0xff }, /* END MARKER */ +}; + +/* This initializes the OV6x20 camera chip and relevant variables. */ +static int ov6x20_init(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov6x20 *s; + int rc; + + DDEBUG(4, &c->dev, "entered"); + + switch (c->adapter->id) { + case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511: + rc = ov_write_regvals(c, regvals_init_6x20_511); + break; + case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518: + rc = ov_write_regvals(c, regvals_init_6x20_518); + break; + default: + dev_err(&c->dev, "ov6x20: Unsupported adapter\n"); + rc = -ENODEV; + } + + if (rc < 0) + return rc; + + ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL); + if (!s) + return -ENOMEM; + memset(s, 0, sizeof *s); + + s->auto_brt = 1; + s->auto_exp = 1; + + return rc; +} + +static int ov6x20_free(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + + kfree(ov->spriv); + return 0; +} + +static int ov6x20_set_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov6x20 *s = ov->spriv; + int rc; + int v = ctl->value; + + switch (ctl->id) { + case OVCAMCHIP_CID_CONT: + rc = ov_write(c, REG_CNT, v >> 8); + break; + case OVCAMCHIP_CID_BRIGHT: + rc = ov_write(c, REG_BRT, v >> 8); + break; + case OVCAMCHIP_CID_SAT: + rc = ov_write(c, REG_SAT, v >> 8); + break; + case OVCAMCHIP_CID_HUE: + rc = ov_write(c, REG_RED, 0xFF - (v >> 8)); + if (rc < 0) + goto out; + + rc = ov_write(c, REG_BLUE, v >> 8); + break; + case OVCAMCHIP_CID_EXP: + rc = ov_write(c, REG_EXP, v); + break; + case OVCAMCHIP_CID_FREQ: + { + int sixty = (v == 60); + + rc = ov_write(c, 0x2b, sixty?0xa8:0x28); + if (rc < 0) + goto out; + + rc = ov_write(c, 0x2a, sixty?0x84:0xa4); + break; + } + case OVCAMCHIP_CID_BANDFILT: + rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); + s->bandfilt = v; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); + s->auto_brt = v; + break; + case OVCAMCHIP_CID_AUTOEXP: + rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01); + s->auto_exp = v; + break; + case OVCAMCHIP_CID_BACKLIGHT: + { + rc = ov_write_mask(c, 0x4e, v?0xe0:0xc0, 0xe0); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x0e, v?0x80:0x00, 0x80); + s->backlight = v; + break; + } + case OVCAMCHIP_CID_MIRROR: + rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); + s->mirror = v; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + +out: + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); + return rc; +} + +static int ov6x20_get_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov6x20 *s = ov->spriv; + int rc = 0; + unsigned char val = 0; + + switch (ctl->id) { + case OVCAMCHIP_CID_CONT: + rc = ov_read(c, REG_CNT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_BRIGHT: + rc = ov_read(c, REG_BRT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_SAT: + rc = ov_read(c, REG_SAT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_HUE: + rc = ov_read(c, REG_BLUE, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_EXP: + rc = ov_read(c, REG_EXP, &val); + ctl->value = val; + break; + case OVCAMCHIP_CID_BANDFILT: + ctl->value = s->bandfilt; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + ctl->value = s->auto_brt; + break; + case OVCAMCHIP_CID_AUTOEXP: + ctl->value = s->auto_exp; + break; + case OVCAMCHIP_CID_BACKLIGHT: + ctl->value = s->backlight; + break; + case OVCAMCHIP_CID_MIRROR: + ctl->value = s->mirror; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); + return rc; +} + +static int ov6x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win) +{ + /******** QCIF-specific regs ********/ + + ov_write(c, 0x14, win->quarter?0x24:0x04); + + /******** Palette-specific regs ********/ + + /* OV518 needs 8 bit multiplexed in color mode, and 16 bit in B&W */ + if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) { + if (win->format == VIDEO_PALETTE_GREY) + ov_write_mask(c, 0x13, 0x00, 0x20); + else + ov_write_mask(c, 0x13, 0x20, 0x20); + } else { + if (win->format == VIDEO_PALETTE_GREY) + ov_write_mask(c, 0x13, 0x20, 0x20); + else + ov_write_mask(c, 0x13, 0x00, 0x20); + } + + /******** Clock programming ********/ + + /* The OV6620 needs special handling. This prevents the + * severe banding that normally occurs */ + + /* Clock down */ + ov_write(c, 0x2a, 0x04); + + ov_write(c, 0x11, win->clockdiv); + + ov_write(c, 0x2a, 0x84); + /* This next setting is critical. It seems to improve + * the gain or the contrast. The "reserved" bits seem + * to have some effect in this case. */ + ov_write(c, 0x2d, 0x85); /* FIXME: This messes up banding filter */ + + return 0; +} + +static int ov6x20_set_window(struct i2c_client *c, struct ovcamchip_window *win) +{ + int ret, hwscale, vwscale; + + ret = ov6x20_mode_init(c, win); + if (ret < 0) + return ret; + + if (win->quarter) { + hwscale = 0; + vwscale = 0; + } else { + hwscale = 1; + vwscale = 1; /* The datasheet says 0; it's wrong */ + } + + ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); + ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); + ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); + ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); + + return 0; +} + +static int ov6x20_command(struct i2c_client *c, unsigned int cmd, void *arg) +{ + switch (cmd) { + case OVCAMCHIP_CMD_S_CTRL: + return ov6x20_set_control(c, arg); + case OVCAMCHIP_CMD_G_CTRL: + return ov6x20_get_control(c, arg); + case OVCAMCHIP_CMD_S_MODE: + return ov6x20_set_window(c, arg); + default: + DDEBUG(2, &c->dev, "command not supported: %d", cmd); + return -ENOIOCTLCMD; + } +} + +struct ovcamchip_ops ov6x20_ops = { + .init = ov6x20_init, + .free = ov6x20_free, + .command = ov6x20_command, +}; diff --git a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c new file mode 100644 index 000000000000..44a842379b45 --- /dev/null +++ b/drivers/media/video/ovcamchip/ov6x30.c @@ -0,0 +1,374 @@ +/* OmniVision OV6630/OV6130 Camera Chip Support Code + * + * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> + * http://alpha.dyndns.org/ov511/ + * + * 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. NO WARRANTY OF ANY KIND is expressed or implied. + */ + +#define DEBUG + +#include <linux/slab.h> +#include "ovcamchip_priv.h" + +/* Registers */ +#define REG_GAIN 0x00 /* gain [5:0] */ +#define REG_BLUE 0x01 /* blue gain */ +#define REG_RED 0x02 /* red gain */ +#define REG_SAT 0x03 /* saturation [7:3] */ +#define REG_CNT 0x05 /* Y contrast [3:0] */ +#define REG_BRT 0x06 /* Y brightness */ +#define REG_SHARP 0x07 /* sharpness */ +#define REG_WB_BLUE 0x0C /* WB blue ratio [5:0] */ +#define REG_WB_RED 0x0D /* WB red ratio [5:0] */ +#define REG_EXP 0x10 /* exposure */ + +/* Window parameters */ +#define HWSBASE 0x38 +#define HWEBASE 0x3A +#define VWSBASE 0x05 +#define VWEBASE 0x06 + +struct ov6x30 { + int auto_brt; + int auto_exp; + int backlight; + int bandfilt; + int mirror; +}; + +static struct ovcamchip_regvals regvals_init_6x30[] = { + { 0x12, 0x80 }, /* reset */ + { 0x00, 0x1f }, /* Gain */ + { 0x01, 0x99 }, /* Blue gain */ + { 0x02, 0x7c }, /* Red gain */ + { 0x03, 0xc0 }, /* Saturation */ + { 0x05, 0x0a }, /* Contrast */ + { 0x06, 0x95 }, /* Brightness */ + { 0x07, 0x2d }, /* Sharpness */ + { 0x0c, 0x20 }, + { 0x0d, 0x20 }, + { 0x0e, 0x20 }, + { 0x0f, 0x05 }, + { 0x10, 0x9a }, /* "exposure check" */ + { 0x11, 0x00 }, /* Pixel clock = fastest */ + { 0x12, 0x24 }, /* Enable AGC and AWB */ + { 0x13, 0x21 }, + { 0x14, 0x80 }, + { 0x15, 0x01 }, + { 0x16, 0x03 }, + { 0x17, 0x38 }, + { 0x18, 0xea }, + { 0x19, 0x04 }, + { 0x1a, 0x93 }, + { 0x1b, 0x00 }, + { 0x1e, 0xc4 }, + { 0x1f, 0x04 }, + { 0x20, 0x20 }, + { 0x21, 0x10 }, + { 0x22, 0x88 }, + { 0x23, 0xc0 }, /* Crystal circuit power level */ + { 0x25, 0x9a }, /* Increase AEC black pixel ratio */ + { 0x26, 0xb2 }, /* BLC enable */ + { 0x27, 0xa2 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x84 }, /* (keep) */ + { 0x2b, 0xa8 }, /* (keep) */ + { 0x2c, 0xa0 }, + { 0x2d, 0x95 }, /* Enable auto-brightness */ + { 0x2e, 0x88 }, + { 0x33, 0x26 }, + { 0x34, 0x03 }, + { 0x36, 0x8f }, + { 0x37, 0x80 }, + { 0x38, 0x83 }, + { 0x39, 0x80 }, + { 0x3a, 0x0f }, + { 0x3b, 0x3c }, + { 0x3c, 0x1a }, + { 0x3d, 0x80 }, + { 0x3e, 0x80 }, + { 0x3f, 0x0e }, + { 0x40, 0x00 }, /* White bal */ + { 0x41, 0x00 }, /* White bal */ + { 0x42, 0x80 }, + { 0x43, 0x3f }, /* White bal */ + { 0x44, 0x80 }, + { 0x45, 0x20 }, + { 0x46, 0x20 }, + { 0x47, 0x80 }, + { 0x48, 0x7f }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x80 }, + { 0x4c, 0xd0 }, + { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ + { 0x4e, 0x40 }, + { 0x4f, 0x07 }, /* UV average mode, color killer: strongest */ + { 0x50, 0xff }, + { 0x54, 0x23 }, /* Max AGC gain: 18dB */ + { 0x55, 0xff }, + { 0x56, 0x12 }, + { 0x57, 0x81 }, /* (default) */ + { 0x58, 0x75 }, + { 0x59, 0x01 }, /* AGC dark current compensation: +1 */ + { 0x5a, 0x2c }, + { 0x5b, 0x0f }, /* AWB chrominance levels */ + { 0x5c, 0x10 }, + { 0x3d, 0x80 }, + { 0x27, 0xa6 }, + /* Toggle AWB off and on */ + { 0x12, 0x20 }, + { 0x12, 0x24 }, + + { 0xff, 0xff }, /* END MARKER */ +}; + +/* This initializes the OV6x30 camera chip and relevant variables. */ +static int ov6x30_init(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov6x30 *s; + int rc; + + DDEBUG(4, &c->dev, "entered"); + + rc = ov_write_regvals(c, regvals_init_6x30); + if (rc < 0) + return rc; + + ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL); + if (!s) + return -ENOMEM; + memset(s, 0, sizeof *s); + + s->auto_brt = 1; + s->auto_exp = 1; + + return rc; +} + +static int ov6x30_free(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + + kfree(ov->spriv); + return 0; +} + +static int ov6x30_set_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov6x30 *s = ov->spriv; + int rc; + int v = ctl->value; + + switch (ctl->id) { + case OVCAMCHIP_CID_CONT: + rc = ov_write_mask(c, REG_CNT, v >> 12, 0x0f); + break; + case OVCAMCHIP_CID_BRIGHT: + rc = ov_write(c, REG_BRT, v >> 8); + break; + case OVCAMCHIP_CID_SAT: + rc = ov_write(c, REG_SAT, v >> 8); + break; + case OVCAMCHIP_CID_HUE: + rc = ov_write(c, REG_RED, 0xFF - (v >> 8)); + if (rc < 0) + goto out; + + rc = ov_write(c, REG_BLUE, v >> 8); + break; + case OVCAMCHIP_CID_EXP: + rc = ov_write(c, REG_EXP, v); + break; + case OVCAMCHIP_CID_FREQ: + { + int sixty = (v == 60); + + rc = ov_write(c, 0x2b, sixty?0xa8:0x28); + if (rc < 0) + goto out; + + rc = ov_write(c, 0x2a, sixty?0x84:0xa4); + break; + } + case OVCAMCHIP_CID_BANDFILT: + rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); + s->bandfilt = v; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); + s->auto_brt = v; + break; + case OVCAMCHIP_CID_AUTOEXP: + rc = ov_write_mask(c, 0x28, v?0x00:0x10, 0x10); + s->auto_exp = v; + break; + case OVCAMCHIP_CID_BACKLIGHT: + { + rc = ov_write_mask(c, 0x4e, v?0x80:0x60, 0xe0); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x28, v?0x02:0x00, 0x02); + s->backlight = v; + break; + } + case OVCAMCHIP_CID_MIRROR: + rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); + s->mirror = v; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + +out: + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); + return rc; +} + +static int ov6x30_get_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov6x30 *s = ov->spriv; + int rc = 0; + unsigned char val = 0; + + switch (ctl->id) { + case OVCAMCHIP_CID_CONT: + rc = ov_read(c, REG_CNT, &val); + ctl->value = (val & 0x0f) << 12; + break; + case OVCAMCHIP_CID_BRIGHT: + rc = ov_read(c, REG_BRT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_SAT: + rc = ov_read(c, REG_SAT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_HUE: + rc = ov_read(c, REG_BLUE, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_EXP: + rc = ov_read(c, REG_EXP, &val); + ctl->value = val; + break; + case OVCAMCHIP_CID_BANDFILT: + ctl->value = s->bandfilt; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + ctl->value = s->auto_brt; + break; + case OVCAMCHIP_CID_AUTOEXP: + ctl->value = s->auto_exp; + break; + case OVCAMCHIP_CID_BACKLIGHT: + ctl->value = s->backlight; + break; + case OVCAMCHIP_CID_MIRROR: + ctl->value = s->mirror; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); + return rc; +} + +static int ov6x30_mode_init(struct i2c_client *c, struct ovcamchip_window *win) +{ + /******** QCIF-specific regs ********/ + + ov_write_mask(c, 0x14, win->quarter?0x20:0x00, 0x20); + + /******** Palette-specific regs ********/ + + if (win->format == VIDEO_PALETTE_GREY) { + if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) { + /* Do nothing - we're already in 8-bit mode */ + } else { + ov_write_mask(c, 0x13, 0x20, 0x20); + } + } else { + /* The OV518 needs special treatment. Although both the OV518 + * and the OV6630 support a 16-bit video bus, only the 8 bit Y + * bus is actually used. The UV bus is tied to ground. + * Therefore, the OV6630 needs to be in 8-bit multiplexed + * output mode */ + + if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) { + /* Do nothing - we want to stay in 8-bit mode */ + /* Warning: Messing with reg 0x13 breaks OV518 color */ + } else { + ov_write_mask(c, 0x13, 0x00, 0x20); + } + } + + /******** Clock programming ********/ + + ov_write(c, 0x11, win->clockdiv); + + return 0; +} + +static int ov6x30_set_window(struct i2c_client *c, struct ovcamchip_window *win) +{ + int ret, hwscale, vwscale; + + ret = ov6x30_mode_init(c, win); + if (ret < 0) + return ret; + + if (win->quarter) { + hwscale = 0; + vwscale = 0; + } else { + hwscale = 1; + vwscale = 1; /* The datasheet says 0; it's wrong */ + } + + ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); + ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); + ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); + ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); + + return 0; +} + +static int ov6x30_command(struct i2c_client *c, unsigned int cmd, void *arg) +{ + switch (cmd) { + case OVCAMCHIP_CMD_S_CTRL: + return ov6x30_set_control(c, arg); + case OVCAMCHIP_CMD_G_CTRL: + return ov6x30_get_control(c, arg); + case OVCAMCHIP_CMD_S_MODE: + return ov6x30_set_window(c, arg); + default: + DDEBUG(2, &c->dev, "command not supported: %d", cmd); + return -ENOIOCTLCMD; + } +} + +struct ovcamchip_ops ov6x30_ops = { + .init = ov6x30_init, + .free = ov6x30_free, + .command = ov6x30_command, +}; diff --git a/drivers/media/video/ovcamchip/ov76be.c b/drivers/media/video/ovcamchip/ov76be.c new file mode 100644 index 000000000000..29bbdc05e3b6 --- /dev/null +++ b/drivers/media/video/ovcamchip/ov76be.c @@ -0,0 +1,303 @@ +/* OmniVision OV76BE Camera Chip Support Code + * + * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> + * http://alpha.dyndns.org/ov511/ + * + * 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. NO WARRANTY OF ANY KIND is expressed or implied. + */ + +#define DEBUG + +#include <linux/slab.h> +#include "ovcamchip_priv.h" + +/* OV7610 registers: Since the OV76BE is undocumented, we'll settle for these + * for now. */ +#define REG_GAIN 0x00 /* gain [5:0] */ +#define REG_BLUE 0x01 /* blue channel balance */ +#define REG_RED 0x02 /* red channel balance */ +#define REG_SAT 0x03 /* saturation */ +#define REG_CNT 0x05 /* Y contrast */ +#define REG_BRT 0x06 /* Y brightness */ +#define REG_BLUE_BIAS 0x0C /* blue channel bias [5:0] */ +#define REG_RED_BIAS 0x0D /* red channel bias [5:0] */ +#define REG_GAMMA_COEFF 0x0E /* gamma settings */ +#define REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ +#define REG_EXP 0x10 /* manual exposure setting */ +#define REG_CLOCK 0x11 /* polarity/clock prescaler */ +#define REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ +#define REG_HWIN_START 0x17 /* horizontal window start */ +#define REG_HWIN_END 0x18 /* horizontal window end */ +#define REG_VWIN_START 0x19 /* vertical window start */ +#define REG_VWIN_END 0x1A /* vertical window end */ +#define REG_PIXEL_SHIFT 0x1B /* pixel shift */ +#define REG_YOFFSET 0x21 /* Y channel offset */ +#define REG_UOFFSET 0x22 /* U channel offset */ +#define REG_ECW 0x24 /* exposure white level for AEC */ +#define REG_ECB 0x25 /* exposure black level for AEC */ +#define REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ +#define REG_FRAMERATE_L 0x2B /* frame rate LSB */ +#define REG_ALC 0x2C /* Auto Level Control settings */ +#define REG_VOFFSET 0x2E /* V channel offset adjustment */ +#define REG_ARRAY_BIAS 0x2F /* array bias -- don't change */ +#define REG_YGAMMA 0x33 /* misc gamma settings [7:6] */ +#define REG_BIAS_ADJUST 0x34 /* misc bias settings */ + +/* Window parameters */ +#define HWSBASE 0x38 +#define HWEBASE 0x3a +#define VWSBASE 0x05 +#define VWEBASE 0x05 + +struct ov76be { + int auto_brt; + int auto_exp; + int bandfilt; + int mirror; +}; + +/* NOTE: These are the same as the 7x10 settings, but should eventually be + * optimized for the OV76BE */ +static struct ovcamchip_regvals regvals_init_76be[] = { + { 0x10, 0xff }, + { 0x16, 0x03 }, + { 0x28, 0x24 }, + { 0x2b, 0xac }, + { 0x12, 0x00 }, + { 0x38, 0x81 }, + { 0x28, 0x24 }, /* 0c */ + { 0x0f, 0x85 }, /* lg's setting */ + { 0x15, 0x01 }, + { 0x20, 0x1c }, + { 0x23, 0x2a }, + { 0x24, 0x10 }, + { 0x25, 0x8a }, + { 0x26, 0xa2 }, + { 0x27, 0xc2 }, + { 0x2a, 0x04 }, + { 0x2c, 0xfe }, + { 0x2d, 0x93 }, + { 0x30, 0x71 }, + { 0x31, 0x60 }, + { 0x32, 0x26 }, + { 0x33, 0x20 }, + { 0x34, 0x48 }, + { 0x12, 0x24 }, + { 0x11, 0x01 }, + { 0x0c, 0x24 }, + { 0x0d, 0x24 }, + { 0xff, 0xff }, /* END MARKER */ +}; + +/* This initializes the OV76be camera chip and relevant variables. */ +static int ov76be_init(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov76be *s; + int rc; + + DDEBUG(4, &c->dev, "entered"); + + rc = ov_write_regvals(c, regvals_init_76be); + if (rc < 0) + return rc; + + ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL); + if (!s) + return -ENOMEM; + memset(s, 0, sizeof *s); + + s->auto_brt = 1; + s->auto_exp = 1; + + return rc; +} + +static int ov76be_free(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + + kfree(ov->spriv); + return 0; +} + +static int ov76be_set_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov76be *s = ov->spriv; + int rc; + int v = ctl->value; + + switch (ctl->id) { + case OVCAMCHIP_CID_BRIGHT: + rc = ov_write(c, REG_BRT, v >> 8); + break; + case OVCAMCHIP_CID_SAT: + rc = ov_write(c, REG_SAT, v >> 8); + break; + case OVCAMCHIP_CID_EXP: + rc = ov_write(c, REG_EXP, v); + break; + case OVCAMCHIP_CID_FREQ: + { + int sixty = (v == 60); + + rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80); + if (rc < 0) + goto out; + + rc = ov_write(c, 0x2b, sixty?0x00:0xac); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x76, 0x01, 0x01); + break; + } + case OVCAMCHIP_CID_BANDFILT: + rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); + s->bandfilt = v; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); + s->auto_brt = v; + break; + case OVCAMCHIP_CID_AUTOEXP: + rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01); + s->auto_exp = v; + break; + case OVCAMCHIP_CID_MIRROR: + rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); + s->mirror = v; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + +out: + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); + return rc; +} + +static int ov76be_get_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov76be *s = ov->spriv; + int rc = 0; + unsigned char val = 0; + + switch (ctl->id) { + case OVCAMCHIP_CID_BRIGHT: + rc = ov_read(c, REG_BRT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_SAT: + rc = ov_read(c, REG_SAT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_EXP: + rc = ov_read(c, REG_EXP, &val); + ctl->value = val; + break; + case OVCAMCHIP_CID_BANDFILT: + ctl->value = s->bandfilt; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + ctl->value = s->auto_brt; + break; + case OVCAMCHIP_CID_AUTOEXP: + ctl->value = s->auto_exp; + break; + case OVCAMCHIP_CID_MIRROR: + ctl->value = s->mirror; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); + return rc; +} + +static int ov76be_mode_init(struct i2c_client *c, struct ovcamchip_window *win) +{ + int qvga = win->quarter; + + /******** QVGA-specific regs ********/ + + ov_write(c, 0x14, qvga?0xa4:0x84); + + /******** Palette-specific regs ********/ + + if (win->format == VIDEO_PALETTE_GREY) { + ov_write_mask(c, 0x0e, 0x40, 0x40); + ov_write_mask(c, 0x13, 0x20, 0x20); + } else { + ov_write_mask(c, 0x0e, 0x00, 0x40); + ov_write_mask(c, 0x13, 0x00, 0x20); + } + + /******** Clock programming ********/ + + ov_write(c, 0x11, win->clockdiv); + + /******** Resolution-specific ********/ + + if (win->width == 640 && win->height == 480) + ov_write(c, 0x35, 0x9e); + else + ov_write(c, 0x35, 0x1e); + + return 0; +} + +static int ov76be_set_window(struct i2c_client *c, struct ovcamchip_window *win) +{ + int ret, hwscale, vwscale; + + ret = ov76be_mode_init(c, win); + if (ret < 0) + return ret; + + if (win->quarter) { + hwscale = 1; + vwscale = 0; + } else { + hwscale = 2; + vwscale = 1; + } + + ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); + ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); + ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); + ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); + + return 0; +} + +static int ov76be_command(struct i2c_client *c, unsigned int cmd, void *arg) +{ + switch (cmd) { + case OVCAMCHIP_CMD_S_CTRL: + return ov76be_set_control(c, arg); + case OVCAMCHIP_CMD_G_CTRL: + return ov76be_get_control(c, arg); + case OVCAMCHIP_CMD_S_MODE: + return ov76be_set_window(c, arg); + default: + DDEBUG(2, &c->dev, "command not supported: %d", cmd); + return -ENOIOCTLCMD; + } +} + +struct ovcamchip_ops ov76be_ops = { + .init = ov76be_init, + .free = ov76be_free, + .command = ov76be_command, +}; diff --git a/drivers/media/video/ovcamchip/ov7x10.c b/drivers/media/video/ovcamchip/ov7x10.c new file mode 100644 index 000000000000..6c383d4b14fa --- /dev/null +++ b/drivers/media/video/ovcamchip/ov7x10.c @@ -0,0 +1,335 @@ +/* OmniVision OV7610/OV7110 Camera Chip Support Code + * + * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> + * http://alpha.dyndns.org/ov511/ + * + * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) + * + * 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. NO WARRANTY OF ANY KIND is expressed or implied. + */ + +#define DEBUG + +#include <linux/slab.h> +#include "ovcamchip_priv.h" + +/* Registers */ +#define REG_GAIN 0x00 /* gain [5:0] */ +#define REG_BLUE 0x01 /* blue channel balance */ +#define REG_RED 0x02 /* red channel balance */ +#define REG_SAT 0x03 /* saturation */ +#define REG_CNT 0x05 /* Y contrast */ +#define REG_BRT 0x06 /* Y brightness */ +#define REG_BLUE_BIAS 0x0C /* blue channel bias [5:0] */ +#define REG_RED_BIAS 0x0D /* red channel bias [5:0] */ +#define REG_GAMMA_COEFF 0x0E /* gamma settings */ +#define REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ +#define REG_EXP 0x10 /* manual exposure setting */ +#define REG_CLOCK 0x11 /* polarity/clock prescaler */ +#define REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ +#define REG_HWIN_START 0x17 /* horizontal window start */ +#define REG_HWIN_END 0x18 /* horizontal window end */ +#define REG_VWIN_START 0x19 /* vertical window start */ +#define REG_VWIN_END 0x1A /* vertical window end */ +#define REG_PIXEL_SHIFT 0x1B /* pixel shift */ +#define REG_YOFFSET 0x21 /* Y channel offset */ +#define REG_UOFFSET 0x22 /* U channel offset */ +#define REG_ECW 0x24 /* exposure white level for AEC */ +#define REG_ECB 0x25 /* exposure black level for AEC */ +#define REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ +#define REG_FRAMERATE_L 0x2B /* frame rate LSB */ +#define REG_ALC 0x2C /* Auto Level Control settings */ +#define REG_VOFFSET 0x2E /* V channel offset adjustment */ +#define REG_ARRAY_BIAS 0x2F /* array bias -- don't change */ +#define REG_YGAMMA 0x33 /* misc gamma settings [7:6] */ +#define REG_BIAS_ADJUST 0x34 /* misc bias settings */ + +/* Window parameters */ +#define HWSBASE 0x38 +#define HWEBASE 0x3a +#define VWSBASE 0x05 +#define VWEBASE 0x05 + +struct ov7x10 { + int auto_brt; + int auto_exp; + int bandfilt; + int mirror; +}; + +/* Lawrence Glaister <lg@jfm.bc.ca> reports: + * + * Register 0x0f in the 7610 has the following effects: + * + * 0x85 (AEC method 1): Best overall, good contrast range + * 0x45 (AEC method 2): Very overexposed + * 0xa5 (spec sheet default): Ok, but the black level is + * shifted resulting in loss of contrast + * 0x05 (old driver setting): very overexposed, too much + * contrast + */ +static struct ovcamchip_regvals regvals_init_7x10[] = { + { 0x10, 0xff }, + { 0x16, 0x03 }, + { 0x28, 0x24 }, + { 0x2b, 0xac }, + { 0x12, 0x00 }, + { 0x38, 0x81 }, + { 0x28, 0x24 }, /* 0c */ + { 0x0f, 0x85 }, /* lg's setting */ + { 0x15, 0x01 }, + { 0x20, 0x1c }, + { 0x23, 0x2a }, + { 0x24, 0x10 }, + { 0x25, 0x8a }, + { 0x26, 0xa2 }, + { 0x27, 0xc2 }, + { 0x2a, 0x04 }, + { 0x2c, 0xfe }, + { 0x2d, 0x93 }, + { 0x30, 0x71 }, + { 0x31, 0x60 }, + { 0x32, 0x26 }, + { 0x33, 0x20 }, + { 0x34, 0x48 }, + { 0x12, 0x24 }, + { 0x11, 0x01 }, + { 0x0c, 0x24 }, + { 0x0d, 0x24 }, + { 0xff, 0xff }, /* END MARKER */ +}; + +/* This initializes the OV7x10 camera chip and relevant variables. */ +static int ov7x10_init(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov7x10 *s; + int rc; + + DDEBUG(4, &c->dev, "entered"); + + rc = ov_write_regvals(c, regvals_init_7x10); + if (rc < 0) + return rc; + + ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL); + if (!s) + return -ENOMEM; + memset(s, 0, sizeof *s); + + s->auto_brt = 1; + s->auto_exp = 1; + + return rc; +} + +static int ov7x10_free(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + + kfree(ov->spriv); + return 0; +} + +static int ov7x10_set_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov7x10 *s = ov->spriv; + int rc; + int v = ctl->value; + + switch (ctl->id) { + case OVCAMCHIP_CID_CONT: + rc = ov_write(c, REG_CNT, v >> 8); + break; + case OVCAMCHIP_CID_BRIGHT: + rc = ov_write(c, REG_BRT, v >> 8); + break; + case OVCAMCHIP_CID_SAT: + rc = ov_write(c, REG_SAT, v >> 8); + break; + case OVCAMCHIP_CID_HUE: + rc = ov_write(c, REG_RED, 0xFF - (v >> 8)); + if (rc < 0) + goto out; + + rc = ov_write(c, REG_BLUE, v >> 8); + break; + case OVCAMCHIP_CID_EXP: + rc = ov_write(c, REG_EXP, v); + break; + case OVCAMCHIP_CID_FREQ: + { + int sixty = (v == 60); + + rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80); + if (rc < 0) + goto out; + + rc = ov_write(c, 0x2b, sixty?0x00:0xac); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x13, 0x10, 0x10); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x13, 0x00, 0x10); + break; + } + case OVCAMCHIP_CID_BANDFILT: + rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); + s->bandfilt = v; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); + s->auto_brt = v; + break; + case OVCAMCHIP_CID_AUTOEXP: + rc = ov_write_mask(c, 0x29, v?0x00:0x80, 0x80); + s->auto_exp = v; + break; + case OVCAMCHIP_CID_MIRROR: + rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); + s->mirror = v; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + +out: + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); + return rc; +} + +static int ov7x10_get_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov7x10 *s = ov->spriv; + int rc = 0; + unsigned char val = 0; + + switch (ctl->id) { + case OVCAMCHIP_CID_CONT: + rc = ov_read(c, REG_CNT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_BRIGHT: + rc = ov_read(c, REG_BRT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_SAT: + rc = ov_read(c, REG_SAT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_HUE: + rc = ov_read(c, REG_BLUE, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_EXP: + rc = ov_read(c, REG_EXP, &val); + ctl->value = val; + break; + case OVCAMCHIP_CID_BANDFILT: + ctl->value = s->bandfilt; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + ctl->value = s->auto_brt; + break; + case OVCAMCHIP_CID_AUTOEXP: + ctl->value = s->auto_exp; + break; + case OVCAMCHIP_CID_MIRROR: + ctl->value = s->mirror; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); + return rc; +} + +static int ov7x10_mode_init(struct i2c_client *c, struct ovcamchip_window *win) +{ + int qvga = win->quarter; + + /******** QVGA-specific regs ********/ + + ov_write(c, 0x14, qvga?0x24:0x04); + + /******** Palette-specific regs ********/ + + if (win->format == VIDEO_PALETTE_GREY) { + ov_write_mask(c, 0x0e, 0x40, 0x40); + ov_write_mask(c, 0x13, 0x20, 0x20); + } else { + ov_write_mask(c, 0x0e, 0x00, 0x40); + ov_write_mask(c, 0x13, 0x00, 0x20); + } + + /******** Clock programming ********/ + + ov_write(c, 0x11, win->clockdiv); + + /******** Resolution-specific ********/ + + if (win->width == 640 && win->height == 480) + ov_write(c, 0x35, 0x9e); + else + ov_write(c, 0x35, 0x1e); + + return 0; +} + +static int ov7x10_set_window(struct i2c_client *c, struct ovcamchip_window *win) +{ + int ret, hwscale, vwscale; + + ret = ov7x10_mode_init(c, win); + if (ret < 0) + return ret; + + if (win->quarter) { + hwscale = 1; + vwscale = 0; + } else { + hwscale = 2; + vwscale = 1; + } + + ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); + ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); + ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); + ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); + + return 0; +} + +static int ov7x10_command(struct i2c_client *c, unsigned int cmd, void *arg) +{ + switch (cmd) { + case OVCAMCHIP_CMD_S_CTRL: + return ov7x10_set_control(c, arg); + case OVCAMCHIP_CMD_G_CTRL: + return ov7x10_get_control(c, arg); + case OVCAMCHIP_CMD_S_MODE: + return ov7x10_set_window(c, arg); + default: + DDEBUG(2, &c->dev, "command not supported: %d", cmd); + return -ENOIOCTLCMD; + } +} + +struct ovcamchip_ops ov7x10_ops = { + .init = ov7x10_init, + .free = ov7x10_free, + .command = ov7x10_command, +}; diff --git a/drivers/media/video/ovcamchip/ov7x20.c b/drivers/media/video/ovcamchip/ov7x20.c new file mode 100644 index 000000000000..3c8c48f338ba --- /dev/null +++ b/drivers/media/video/ovcamchip/ov7x20.c @@ -0,0 +1,455 @@ +/* OmniVision OV7620/OV7120 Camera Chip Support Code + * + * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> + * http://alpha.dyndns.org/ov511/ + * + * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> + * + * 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. NO WARRANTY OF ANY KIND is expressed or implied. + */ + +#define DEBUG + +#include <linux/slab.h> +#include "ovcamchip_priv.h" + +/* Registers */ +#define REG_GAIN 0x00 /* gain [5:0] */ +#define REG_BLUE 0x01 /* blue gain */ +#define REG_RED 0x02 /* red gain */ +#define REG_SAT 0x03 /* saturation */ +#define REG_BRT 0x06 /* Y brightness */ +#define REG_SHARP 0x07 /* analog sharpness */ +#define REG_BLUE_BIAS 0x0C /* WB blue ratio [5:0] */ +#define REG_RED_BIAS 0x0D /* WB red ratio [5:0] */ +#define REG_EXP 0x10 /* exposure */ + +/* Default control settings. Values are in terms of V4L2 controls. */ +#define OV7120_DFL_BRIGHT 0x60 +#define OV7620_DFL_BRIGHT 0x60 +#define OV7120_DFL_SAT 0xb0 +#define OV7620_DFL_SAT 0xc0 +#define DFL_AUTO_EXP 1 +#define DFL_AUTO_GAIN 1 +#define OV7120_DFL_GAIN 0x00 +#define OV7620_DFL_GAIN 0x00 +/* NOTE: Since autoexposure is the default, these aren't programmed into the + * OV7x20 chip. They are just here because V4L2 expects a default */ +#define OV7120_DFL_EXP 0x7f +#define OV7620_DFL_EXP 0x7f + +/* Window parameters */ +#define HWSBASE 0x2F /* From 7620.SET (spec is wrong) */ +#define HWEBASE 0x2F +#define VWSBASE 0x05 +#define VWEBASE 0x05 + +struct ov7x20 { + int auto_brt; + int auto_exp; + int auto_gain; + int backlight; + int bandfilt; + int mirror; +}; + +/* Contrast look-up table */ +static unsigned char ctab[] = { + 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, + 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff +}; + +/* Settings for (Black & White) OV7120 camera chip */ +static struct ovcamchip_regvals regvals_init_7120[] = { + { 0x12, 0x80 }, /* reset */ + { 0x13, 0x00 }, /* Autoadjust off */ + { 0x12, 0x20 }, /* Disable AWB */ + { 0x13, DFL_AUTO_GAIN?0x01:0x00 }, /* Autoadjust on (if desired) */ + { 0x00, OV7120_DFL_GAIN }, + { 0x01, 0x80 }, + { 0x02, 0x80 }, + { 0x03, OV7120_DFL_SAT }, + { 0x06, OV7120_DFL_BRIGHT }, + { 0x07, 0x00 }, + { 0x0c, 0x20 }, + { 0x0d, 0x20 }, + { 0x11, 0x01 }, + { 0x14, 0x84 }, + { 0x15, 0x01 }, + { 0x16, 0x03 }, + { 0x17, 0x2f }, + { 0x18, 0xcf }, + { 0x19, 0x06 }, + { 0x1a, 0xf5 }, + { 0x1b, 0x00 }, + { 0x20, 0x08 }, + { 0x21, 0x80 }, + { 0x22, 0x80 }, + { 0x23, 0x00 }, + { 0x26, 0xa0 }, + { 0x27, 0xfa }, + { 0x28, 0x20 }, /* DON'T set bit 6. It is for the OV7620 only */ + { 0x29, DFL_AUTO_EXP?0x00:0x80 }, + { 0x2a, 0x10 }, + { 0x2b, 0x00 }, + { 0x2c, 0x88 }, + { 0x2d, 0x95 }, + { 0x2e, 0x80 }, + { 0x2f, 0x44 }, + { 0x60, 0x20 }, + { 0x61, 0x02 }, + { 0x62, 0x5f }, + { 0x63, 0xd5 }, + { 0x64, 0x57 }, + { 0x65, 0x83 }, /* OV says "don't change this value" */ + { 0x66, 0x55 }, + { 0x67, 0x92 }, + { 0x68, 0xcf }, + { 0x69, 0x76 }, + { 0x6a, 0x22 }, + { 0x6b, 0xe2 }, + { 0x6c, 0x40 }, + { 0x6d, 0x48 }, + { 0x6e, 0x80 }, + { 0x6f, 0x0d }, + { 0x70, 0x89 }, + { 0x71, 0x00 }, + { 0x72, 0x14 }, + { 0x73, 0x54 }, + { 0x74, 0xa0 }, + { 0x75, 0x8e }, + { 0x76, 0x00 }, + { 0x77, 0xff }, + { 0x78, 0x80 }, + { 0x79, 0x80 }, + { 0x7a, 0x80 }, + { 0x7b, 0xe6 }, + { 0x7c, 0x00 }, + { 0x24, 0x3a }, + { 0x25, 0x60 }, + { 0xff, 0xff }, /* END MARKER */ +}; + +/* Settings for (color) OV7620 camera chip */ +static struct ovcamchip_regvals regvals_init_7620[] = { + { 0x12, 0x80 }, /* reset */ + { 0x00, OV7620_DFL_GAIN }, + { 0x01, 0x80 }, + { 0x02, 0x80 }, + { 0x03, OV7620_DFL_SAT }, + { 0x06, OV7620_DFL_BRIGHT }, + { 0x07, 0x00 }, + { 0x0c, 0x24 }, + { 0x0c, 0x24 }, + { 0x0d, 0x24 }, + { 0x11, 0x01 }, + { 0x12, 0x24 }, + { 0x13, DFL_AUTO_GAIN?0x01:0x00 }, + { 0x14, 0x84 }, + { 0x15, 0x01 }, + { 0x16, 0x03 }, + { 0x17, 0x2f }, + { 0x18, 0xcf }, + { 0x19, 0x06 }, + { 0x1a, 0xf5 }, + { 0x1b, 0x00 }, + { 0x20, 0x18 }, + { 0x21, 0x80 }, + { 0x22, 0x80 }, + { 0x23, 0x00 }, + { 0x26, 0xa2 }, + { 0x27, 0xea }, + { 0x28, 0x20 }, + { 0x29, DFL_AUTO_EXP?0x00:0x80 }, + { 0x2a, 0x10 }, + { 0x2b, 0x00 }, + { 0x2c, 0x88 }, + { 0x2d, 0x91 }, + { 0x2e, 0x80 }, + { 0x2f, 0x44 }, + { 0x60, 0x27 }, + { 0x61, 0x02 }, + { 0x62, 0x5f }, + { 0x63, 0xd5 }, + { 0x64, 0x57 }, + { 0x65, 0x83 }, + { 0x66, 0x55 }, + { 0x67, 0x92 }, + { 0x68, 0xcf }, + { 0x69, 0x76 }, + { 0x6a, 0x22 }, + { 0x6b, 0x00 }, + { 0x6c, 0x02 }, + { 0x6d, 0x44 }, + { 0x6e, 0x80 }, + { 0x6f, 0x1d }, + { 0x70, 0x8b }, + { 0x71, 0x00 }, + { 0x72, 0x14 }, + { 0x73, 0x54 }, + { 0x74, 0x00 }, + { 0x75, 0x8e }, + { 0x76, 0x00 }, + { 0x77, 0xff }, + { 0x78, 0x80 }, + { 0x79, 0x80 }, + { 0x7a, 0x80 }, + { 0x7b, 0xe2 }, + { 0x7c, 0x00 }, + { 0xff, 0xff }, /* END MARKER */ +}; + +/* Returns index into the specified look-up table, with 'n' elements, for which + * the value is greater than or equal to "val". If a match isn't found, (n-1) + * is returned. The entries in the table must be in ascending order. */ +static inline int ov7x20_lut_find(unsigned char lut[], int n, unsigned char val) +{ + int i = 0; + + while (lut[i] < val && i < n) + i++; + + return i; +} + +/* This initializes the OV7x20 camera chip and relevant variables. */ +static int ov7x20_init(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov7x20 *s; + int rc; + + DDEBUG(4, &c->dev, "entered"); + + if (ov->mono) + rc = ov_write_regvals(c, regvals_init_7120); + else + rc = ov_write_regvals(c, regvals_init_7620); + + if (rc < 0) + return rc; + + ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL); + if (!s) + return -ENOMEM; + memset(s, 0, sizeof *s); + + s->auto_brt = 1; + s->auto_exp = DFL_AUTO_EXP; + s->auto_gain = DFL_AUTO_GAIN; + + return 0; +} + +static int ov7x20_free(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + + kfree(ov->spriv); + return 0; +} + +static int ov7x20_set_v4l1_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov7x20 *s = ov->spriv; + int rc; + int v = ctl->value; + + switch (ctl->id) { + case OVCAMCHIP_CID_CONT: + { + /* Use Y gamma control instead. Bit 0 enables it. */ + rc = ov_write(c, 0x64, ctab[v >> 12]); + break; + } + case OVCAMCHIP_CID_BRIGHT: + /* 7620 doesn't like manual changes when in auto mode */ + if (!s->auto_brt) + rc = ov_write(c, REG_BRT, v >> 8); + else + rc = 0; + break; + case OVCAMCHIP_CID_SAT: + rc = ov_write(c, REG_SAT, v >> 8); + break; + case OVCAMCHIP_CID_EXP: + if (!s->auto_exp) + rc = ov_write(c, REG_EXP, v); + else + rc = -EBUSY; + break; + case OVCAMCHIP_CID_FREQ: + { + int sixty = (v == 60); + + rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80); + if (rc < 0) + goto out; + + rc = ov_write(c, 0x2b, sixty?0x00:0xac); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x76, 0x01, 0x01); + break; + } + case OVCAMCHIP_CID_BANDFILT: + rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); + s->bandfilt = v; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); + s->auto_brt = v; + break; + case OVCAMCHIP_CID_AUTOEXP: + rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01); + s->auto_exp = v; + break; + case OVCAMCHIP_CID_BACKLIGHT: + { + rc = ov_write_mask(c, 0x68, v?0xe0:0xc0, 0xe0); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08); + if (rc < 0) + goto out; + + rc = ov_write_mask(c, 0x28, v?0x02:0x00, 0x02); + s->backlight = v; + break; + } + case OVCAMCHIP_CID_MIRROR: + rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); + s->mirror = v; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + +out: + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); + return rc; +} + +static int ov7x20_get_v4l1_control(struct i2c_client *c, + struct ovcamchip_control *ctl) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + struct ov7x20 *s = ov->spriv; + int rc = 0; + unsigned char val = 0; + + switch (ctl->id) { + case OVCAMCHIP_CID_CONT: + rc = ov_read(c, 0x64, &val); + ctl->value = ov7x20_lut_find(ctab, 16, val) << 12; + break; + case OVCAMCHIP_CID_BRIGHT: + rc = ov_read(c, REG_BRT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_SAT: + rc = ov_read(c, REG_SAT, &val); + ctl->value = val << 8; + break; + case OVCAMCHIP_CID_EXP: + rc = ov_read(c, REG_EXP, &val); + ctl->value = val; + break; + case OVCAMCHIP_CID_BANDFILT: + ctl->value = s->bandfilt; + break; + case OVCAMCHIP_CID_AUTOBRIGHT: + ctl->value = s->auto_brt; + break; + case OVCAMCHIP_CID_AUTOEXP: + ctl->value = s->auto_exp; + break; + case OVCAMCHIP_CID_BACKLIGHT: + ctl->value = s->backlight; + break; + case OVCAMCHIP_CID_MIRROR: + ctl->value = s->mirror; + break; + default: + DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); + return -EPERM; + } + + DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); + return rc; +} + +static int ov7x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + int qvga = win->quarter; + + /******** QVGA-specific regs ********/ + ov_write_mask(c, 0x14, qvga?0x20:0x00, 0x20); + ov_write_mask(c, 0x28, qvga?0x00:0x20, 0x20); + ov_write(c, 0x24, qvga?0x20:0x3a); + ov_write(c, 0x25, qvga?0x30:0x60); + ov_write_mask(c, 0x2d, qvga?0x40:0x00, 0x40); + if (!ov->mono) + ov_write_mask(c, 0x67, qvga?0xf0:0x90, 0xf0); + ov_write_mask(c, 0x74, qvga?0x20:0x00, 0x20); + + /******** Clock programming ********/ + + ov_write(c, 0x11, win->clockdiv); + + return 0; +} + +static int ov7x20_set_window(struct i2c_client *c, struct ovcamchip_window *win) +{ + int ret, hwscale, vwscale; + + ret = ov7x20_mode_init(c, win); + if (ret < 0) + return ret; + + if (win->quarter) { + hwscale = 1; + vwscale = 0; + } else { + hwscale = 2; + vwscale = 1; + } + + ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); + ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); + ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); + ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); + + return 0; +} + +static int ov7x20_command(struct i2c_client *c, unsigned int cmd, void *arg) +{ + switch (cmd) { + case OVCAMCHIP_CMD_S_CTRL: + return ov7x20_set_v4l1_control(c, arg); + case OVCAMCHIP_CMD_G_CTRL: + return ov7x20_get_v4l1_control(c, arg); + case OVCAMCHIP_CMD_S_MODE: + return ov7x20_set_window(c, arg); + default: + DDEBUG(2, &c->dev, "command not supported: %d", cmd); + return -ENOIOCTLCMD; + } +} + +struct ovcamchip_ops ov7x20_ops = { + .init = ov7x20_init, + .free = ov7x20_free, + .command = ov7x20_command, +}; diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c new file mode 100644 index 000000000000..d88956a26aee --- /dev/null +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -0,0 +1,446 @@ +/* Shared Code for OmniVision Camera Chip Drivers + * + * Copyright (c) 2004 Mark McClelland <mark@alpha.dyndns.org> + * http://alpha.dyndns.org/ov511/ + * + * 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. NO WARRANTY OF ANY KIND is expressed or implied. + */ + +#define DEBUG + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/slab.h> +#include "ovcamchip_priv.h" + +#define DRIVER_VERSION "v2.27 for Linux 2.6" +#define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org>" +#define DRIVER_DESC "OV camera chip I2C driver" + +#define PINFO(fmt, args...) printk(KERN_INFO "ovcamchip: " fmt "\n" , ## args); +#define PERROR(fmt, args...) printk(KERN_ERR "ovcamchip: " fmt "\n" , ## args); + +#ifdef DEBUG +int ovcamchip_debug = 0; +static int debug; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, + "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=all"); +#endif + +/* By default, let bridge driver tell us if chip is monochrome. mono=0 + * will ignore that and always treat chips as color. mono=1 will force + * monochrome mode for all chips. */ +static int mono = -1; +module_param(mono, int, 0); +MODULE_PARM_DESC(mono, + "1=chips are monochrome (OVx1xx), 0=force color, -1=autodetect (default)"); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +/* Registers common to all chips, that are needed for detection */ +#define GENERIC_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ +#define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ +#define GENERIC_REG_COM_I 0x29 /* misc ID bits */ + +extern struct ovcamchip_ops ov6x20_ops; +extern struct ovcamchip_ops ov6x30_ops; +extern struct ovcamchip_ops ov7x10_ops; +extern struct ovcamchip_ops ov7x20_ops; +extern struct ovcamchip_ops ov76be_ops; + +static char *chip_names[NUM_CC_TYPES] = { + [CC_UNKNOWN] = "Unknown chip", + [CC_OV76BE] = "OV76BE", + [CC_OV7610] = "OV7610", + [CC_OV7620] = "OV7620", + [CC_OV7620AE] = "OV7620AE", + [CC_OV6620] = "OV6620", + [CC_OV6630] = "OV6630", + [CC_OV6630AE] = "OV6630AE", + [CC_OV6630AF] = "OV6630AF", +}; + +/* Forward declarations */ +static struct i2c_driver driver; +static struct i2c_client client_template; + +/* ----------------------------------------------------------------------- */ + +int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals) +{ + int rc; + + while (rvals->reg != 0xff) { + rc = ov_write(c, rvals->reg, rvals->val); + if (rc < 0) + return rc; + rvals++; + } + + return 0; +} + +/* Writes bits at positions specified by mask to an I2C reg. Bits that are in + * the same position as 1's in "mask" are cleared and set to "value". Bits + * that are in the same position as 0's in "mask" are preserved, regardless + * of their respective state in "value". + */ +int ov_write_mask(struct i2c_client *c, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int rc; + unsigned char oldval, newval; + + if (mask == 0xff) { + newval = value; + } else { + rc = ov_read(c, reg, &oldval); + if (rc < 0) + return rc; + + oldval &= (~mask); /* Clear the masked bits */ + value &= mask; /* Enforce mask on value */ + newval = oldval | value; /* Set the desired bits */ + } + + return ov_write(c, reg, newval); +} + +/* ----------------------------------------------------------------------- */ + +/* Reset the chip and ensure that I2C is synchronized. Returns <0 if failure. + */ +static int init_camchip(struct i2c_client *c) +{ + int i, success; + unsigned char high, low; + + /* Reset the chip */ + ov_write(c, 0x12, 0x80); + + /* Wait for it to initialize */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1 + 150 * HZ / 1000); + + for (i = 0, success = 0; i < I2C_DETECT_RETRIES && !success; i++) { + if (ov_read(c, GENERIC_REG_ID_HIGH, &high) >= 0) { + if (ov_read(c, GENERIC_REG_ID_LOW, &low) >= 0) { + if (high == 0x7F && low == 0xA2) { + success = 1; + continue; + } + } + } + + /* Reset the chip */ + ov_write(c, 0x12, 0x80); + + /* Wait for it to initialize */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1 + 150 * HZ / 1000); + + /* Dummy read to sync I2C */ + ov_read(c, 0x00, &low); + } + + if (!success) + return -EIO; + + PDEBUG(1, "I2C synced in %d attempt(s)", i); + + return 0; +} + +/* This detects the OV7610, OV7620, or OV76BE chip. */ +static int ov7xx0_detect(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + int rc; + unsigned char val; + + PDEBUG(4, ""); + + /* Detect chip (sub)type */ + rc = ov_read(c, GENERIC_REG_COM_I, &val); + if (rc < 0) { + PERROR("Error detecting ov7xx0 type"); + return rc; + } + + if ((val & 3) == 3) { + PINFO("Camera chip is an OV7610"); + ov->subtype = CC_OV7610; + } else if ((val & 3) == 1) { + rc = ov_read(c, 0x15, &val); + if (rc < 0) { + PERROR("Error detecting ov7xx0 type"); + return rc; + } + + if (val & 1) { + PINFO("Camera chip is an OV7620AE"); + /* OV7620 is a close enough match for now. There are + * some definite differences though, so this should be + * fixed */ + ov->subtype = CC_OV7620; + } else { + PINFO("Camera chip is an OV76BE"); + ov->subtype = CC_OV76BE; + } + } else if ((val & 3) == 0) { + PINFO("Camera chip is an OV7620"); + ov->subtype = CC_OV7620; + } else { + PERROR("Unknown camera chip version: %d", val & 3); + return -ENOSYS; + } + + if (ov->subtype == CC_OV76BE) + ov->sops = &ov76be_ops; + else if (ov->subtype == CC_OV7620) + ov->sops = &ov7x20_ops; + else + ov->sops = &ov7x10_ops; + + return 0; +} + +/* This detects the OV6620, OV6630, OV6630AE, or OV6630AF chip. */ +static int ov6xx0_detect(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + int rc; + unsigned char val; + + PDEBUG(4, ""); + + /* Detect chip (sub)type */ + rc = ov_read(c, GENERIC_REG_COM_I, &val); + if (rc < 0) { + PERROR("Error detecting ov6xx0 type"); + return -1; + } + + if ((val & 3) == 0) { + ov->subtype = CC_OV6630; + PINFO("Camera chip is an OV6630"); + } else if ((val & 3) == 1) { + ov->subtype = CC_OV6620; + PINFO("Camera chip is an OV6620"); + } else if ((val & 3) == 2) { + ov->subtype = CC_OV6630; + PINFO("Camera chip is an OV6630AE"); + } else if ((val & 3) == 3) { + ov->subtype = CC_OV6630; + PINFO("Camera chip is an OV6630AF"); + } + + if (ov->subtype == CC_OV6620) + ov->sops = &ov6x20_ops; + else + ov->sops = &ov6x30_ops; + + return 0; +} + +static int ovcamchip_detect(struct i2c_client *c) +{ + /* Ideally we would just try a single register write and see if it NAKs. + * That isn't possible since the OV518 can't report I2C transaction + * failures. So, we have to try to initialize the chip (i.e. reset it + * and check the ID registers) to detect its presence. */ + + /* Test for 7xx0 */ + PDEBUG(3, "Testing for 0V7xx0"); + c->addr = OV7xx0_SID; + if (init_camchip(c) < 0) { + /* Test for 6xx0 */ + PDEBUG(3, "Testing for 0V6xx0"); + c->addr = OV6xx0_SID; + if (init_camchip(c) < 0) { + return -ENODEV; + } else { + if (ov6xx0_detect(c) < 0) { + PERROR("Failed to init OV6xx0"); + return -EIO; + } + } + } else { + if (ov7xx0_detect(c) < 0) { + PERROR("Failed to init OV7xx0"); + return -EIO; + } + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static int ovcamchip_attach(struct i2c_adapter *adap) +{ + int rc = 0; + struct ovcamchip *ov; + struct i2c_client *c; + + /* I2C is not a PnP bus, so we can never be certain that we're talking + * to the right chip. To prevent damage to EEPROMS and such, only + * attach to adapters that are known to contain OV camera chips. */ + + switch (adap->id) { + case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511): + case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518): + case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OVFX2): + case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF): + PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id); + break; + default: + PDEBUG(1, "Adapter ID 0x%06x rejected", adap->id); + return -ENODEV; + } + + c = kmalloc(sizeof *c, GFP_KERNEL); + if (!c) { + rc = -ENOMEM; + goto no_client; + } + memcpy(c, &client_template, sizeof *c); + c->adapter = adap; + strcpy(i2c_clientname(c), "OV????"); + + ov = kmalloc(sizeof *ov, GFP_KERNEL); + if (!ov) { + rc = -ENOMEM; + goto no_ov; + } + memset(ov, 0, sizeof *ov); + i2c_set_clientdata(c, ov); + + rc = ovcamchip_detect(c); + if (rc < 0) + goto error; + + strcpy(i2c_clientname(c), chip_names[ov->subtype]); + + PDEBUG(1, "Camera chip detection complete"); + + i2c_attach_client(c); + + return rc; +error: + kfree(ov); +no_ov: + kfree(c); +no_client: + PDEBUG(1, "returning %d", rc); + return rc; +} + +static int ovcamchip_detach(struct i2c_client *c) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + int rc; + + rc = ov->sops->free(c); + if (rc < 0) + return rc; + + i2c_detach_client(c); + + kfree(ov); + kfree(c); + return 0; +} + +static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg) +{ + struct ovcamchip *ov = i2c_get_clientdata(c); + + if (!ov->initialized && + cmd != OVCAMCHIP_CMD_Q_SUBTYPE && + cmd != OVCAMCHIP_CMD_INITIALIZE) { + dev_err(&c->dev, "ERROR: Camera chip not initialized yet!\n"); + return -EPERM; + } + + switch (cmd) { + case OVCAMCHIP_CMD_Q_SUBTYPE: + { + *(int *)arg = ov->subtype; + return 0; + } + case OVCAMCHIP_CMD_INITIALIZE: + { + int rc; + + if (mono == -1) + ov->mono = *(int *)arg; + else + ov->mono = mono; + + if (ov->mono) { + if (ov->subtype != CC_OV7620) + dev_warn(&c->dev, "Warning: Monochrome not " + "implemented for this chip\n"); + else + dev_info(&c->dev, "Initializing chip as " + "monochrome\n"); + } + + rc = ov->sops->init(c); + if (rc < 0) + return rc; + + ov->initialized = 1; + return 0; + } + default: + return ov->sops->command(c, cmd, arg); + } +} + +/* ----------------------------------------------------------------------- */ + +static struct i2c_driver driver = { + .owner = THIS_MODULE, + .name = "ovcamchip", + .id = I2C_DRIVERID_OVCAMCHIP, + .class = I2C_CLASS_CAM_DIGITAL, + .flags = I2C_DF_NOTIFY, + .attach_adapter = ovcamchip_attach, + .detach_client = ovcamchip_detach, + .command = ovcamchip_command, +}; + +static struct i2c_client client_template = { + I2C_DEVNAME("(unset)"), + .id = -1, + .driver = &driver, +}; + +static int __init ovcamchip_init(void) +{ +#ifdef DEBUG + ovcamchip_debug = debug; +#endif + + PINFO(DRIVER_VERSION " : " DRIVER_DESC); + return i2c_add_driver(&driver); +} + +static void __exit ovcamchip_exit(void) +{ + i2c_del_driver(&driver); +} + +module_init(ovcamchip_init); +module_exit(ovcamchip_exit); diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h new file mode 100644 index 000000000000..575e612a5546 --- /dev/null +++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h @@ -0,0 +1,87 @@ +/* OmniVision* camera chip driver private definitions for core code and + * chip-specific code + * + * Copyright (c) 1999-2004 Mark McClelland + * + * 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. NO WARRANTY OF ANY KIND is expressed or implied. + * + * * OmniVision is a trademark of OmniVision Technologies, Inc. This driver + * is not sponsored or developed by them. + */ + +#ifndef __LINUX_OVCAMCHIP_PRIV_H +#define __LINUX_OVCAMCHIP_PRIV_H + +#include <media/ovcamchip.h> + +#ifdef DEBUG +extern int ovcamchip_debug; +#endif + +#define PDEBUG(level, fmt, args...) \ + if (ovcamchip_debug >= (level)) pr_debug("[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args) + +#define DDEBUG(level, dev, fmt, args...) \ + if (ovcamchip_debug >= (level)) dev_dbg(dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args) + +/* Number of times to retry chip detection. Increase this if you are getting + * "Failed to init camera chip" */ +#define I2C_DETECT_RETRIES 10 + +struct ovcamchip_regvals { + unsigned char reg; + unsigned char val; +}; + +struct ovcamchip_ops { + int (*init)(struct i2c_client *); + int (*free)(struct i2c_client *); + int (*command)(struct i2c_client *, unsigned int, void *); +}; + +struct ovcamchip { + struct ovcamchip_ops *sops; + void *spriv; /* Private data for OV7x10.c etc... */ + int subtype; /* = SEN_OV7610 etc... */ + int mono; /* Monochrome chip? (invalid until init) */ + int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ +}; + +/* --------------------------------- */ +/* I2C I/O */ +/* --------------------------------- */ + +static inline int ov_read(struct i2c_client *c, unsigned char reg, + unsigned char *value) +{ + int rc; + + rc = i2c_smbus_read_byte_data(c, reg); + *value = (unsigned char) rc; + return rc; +} + +static inline int ov_write(struct i2c_client *c, unsigned char reg, + unsigned char value ) +{ + return i2c_smbus_write_byte_data(c, reg, value); +} + +/* --------------------------------- */ +/* FUNCTION PROTOTYPES */ +/* --------------------------------- */ + +/* Functions in ovcamchip_core.c */ + +extern int ov_write_regvals(struct i2c_client *c, + struct ovcamchip_regvals *rvals); + +extern int ov_write_mask(struct i2c_client *c, unsigned char reg, + unsigned char value, unsigned char mask); + +#endif diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 5ea367e0e78b..3343e41338f2 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -337,7 +337,6 @@ static int saa6752hs_probe(struct i2c_adapter *adap) { if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, saa6752hs_attach); - return 0; } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index cee199e59d83..5bb99d716e8a 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -420,20 +420,14 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .tv = 1, -#if 0 },{ .name = name_comp1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, - .vmux = 3, - .amux = LINE2, - },{ .name = name_svideo, .vmux = 8, .amux = LINE2, -#endif }}, .radio = { .name = name_radio, @@ -515,24 +509,14 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .tv = 1, -#if 0 /* untested */ },{ .name = name_comp1, .vmux = 4, .amux = LINE2, },{ - .name = name_comp2, - .vmux = 2, - .amux = LINE2, - },{ .name = name_svideo, .vmux = 6, .amux = LINE2, - },{ - .name = "S-Video2", - .vmux = 7, - .amux = LINE2, -#endif }}, .radio = { .name = name_radio, @@ -679,7 +663,7 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_MD2819] = { - .name = "Medion 2819/ AverMedia M156", + .name = "AverMedia M156 / Medion 2819", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .need_tda9887 = 1, @@ -951,6 +935,96 @@ struct saa7134_board saa7134_boards[] = { .vmux = 3, }}, }, + [SAA7134_BOARD_NOVAC_PRIMETV7133] = { + /* toshii@netbsd.org */ + .name = "Noval Prime TV 7133", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ALPS_TSBH1_NTSC, + .inputs = {{ + .name = name_comp1, + .vmux = 3, + },{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_svideo, + .vmux = 8, + }}, + }, + [SAA7134_BOARD_AVERMEDIA_305] = { + .name = "AverMedia 305", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .need_tda9887 = 1, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 0, + .amux = LINE2, + },{ + .name = name_comp2, + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + .mute = { + .name = name_mute, + .amux = LINE1, + }, + }, + [SAA7133_BOARD_UPMOST_PURPLE_TV] = { + .name = "UPMOST PURPLE TV", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .need_tda9887 = 1, + .inputs = {{ + .name = name_tv, + .vmux = 7, + .amux = TV, + .tv = 1, + },{ + .name = name_svideo, + .vmux = 7, + .amux = LINE1, + }}, + }, + [SAA7134_BOARD_ITEMS_MTV005] = { + /* Norman Jonas <normanjonas@arcor.de> */ + .name = "Items MuchTV Plus / IT-005", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_PAL, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -1103,12 +1177,11 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0xa70b, .driver_data = SAA7134_BOARD_MD2819, },{ - /* AverMedia Studio 305, using AverMedia M156 entry for now */ .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x1461, /* Avermedia Technologies Inc */ .subdevice = 0x2115, - .driver_data = SAA7134_BOARD_MD2819, + .driver_data = SAA7134_BOARD_AVERMEDIA_305, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, @@ -1141,7 +1214,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x4cb5, .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB5, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x12ab, + .subdevice = 0x0800, + .driver_data = SAA7133_BOARD_UPMOST_PURPLE_TV, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -1251,6 +1330,9 @@ int saa7134_board_init(struct saa7134_dev *dev) case SAA7134_BOARD_ECS_TVP3XP_4CB5: dev->has_remote = 1; break; + case SAA7134_BOARD_AVACSSMARTTV: + dev->has_remote = 1; + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index d343d1e93599..48f130f67402 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -607,10 +607,18 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) }; if (10 == loop) { print_irqstatus(dev,loop,report,status); - printk(KERN_WARNING "%s/irq: looping -- clearing enable bits\n",dev->name); - /* disable all irqs */ - saa_writel(SAA7134_IRQ1,0); - saa_writel(SAA7134_IRQ2,0); + if (report & SAA7134_IRQ_REPORT_PE) { + /* disable all parity error */ + printk(KERN_WARNING "%s/irq: looping -- " + "clearing PE (parity error!) enable bit\n",dev->name); + saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE); + } else { + /* disable all irqs */ + printk(KERN_WARNING "%s/irq: looping -- " + "clearing all enable bits\n",dev->name); + saa_writel(SAA7134_IRQ1,0); + saa_writel(SAA7134_IRQ2,0); + } } out: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index e5ff0e5b6ab2..a34447d6b913 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -20,12 +20,24 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/sched.h> #include <linux/interrupt.h> #include <linux/input.h> #include "saa7134-reg.h" #include "saa7134.h" +static unsigned int disable_ir = 0; +MODULE_PARM(disable_ir,"i"); +MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); + +static unsigned int ir_debug = 0; +MODULE_PARM(ir_debug,"i"); +MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); + +#define dprintk(fmt, arg...) if (ir_debug) \ + printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) + /* ---------------------------------------------------------------------- */ static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = { @@ -156,6 +168,47 @@ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { [ 33 ] = KEY_KPDOT, // . (decimal dot) }; +static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = { + [ 30 ] = KEY_POWER, // power + [ 28 ] = KEY_SEARCH, // scan + [ 7 ] = KEY_SELECT, // source + + [ 22 ] = KEY_VOLUMEUP, + [ 20 ] = KEY_VOLUMEDOWN, + [ 31 ] = KEY_CHANNELUP, + [ 23 ] = KEY_CHANNELDOWN, + [ 24 ] = KEY_MUTE, + + [ 2 ] = KEY_KP0, + [ 1 ] = KEY_KP1, + [ 11 ] = KEY_KP2, + [ 27 ] = KEY_KP3, + [ 5 ] = KEY_KP4, + [ 9 ] = KEY_KP5, + [ 21 ] = KEY_KP6, + [ 6 ] = KEY_KP7, + [ 10 ] = KEY_KP8, + [ 18 ] = KEY_KP9, + [ 16 ] = KEY_KPDOT, + + [ 3 ] = KEY_TUNER, // tv/fm + [ 4 ] = KEY_REWIND, // fm tuning left or function left + [ 12 ] = KEY_FORWARD, // fm tuning right or function right + + [ 0 ] = KEY_RECORD, + [ 8 ] = KEY_STOP, + [ 17 ] = KEY_PLAY, + + [ 25 ] = KEY_ZOOM, + [ 14 ] = KEY_MENU, // function + [ 19 ] = KEY_AGAIN, // recall + [ 29 ] = KEY_RESTART, // reset + +// FIXME + [ 13 ] = KEY_F21, // mts + [ 15 ] = KEY_F22, // min + [ 26 ] = KEY_F23, // freeze +}; /* ---------------------------------------------------------------------- */ static int build_key(struct saa7134_dev *dev) @@ -175,8 +228,8 @@ static int build_key(struct saa7134_dev *dev) } data = ir_extract_bits(gpio, ir->mask_keycode); - printk("%s: build_key gpio=0x%x mask=0x%x data=%d\n", - dev->name, gpio, ir->mask_keycode, data); + dprintk("build_key gpio=0x%x mask=0x%x data=%d\n", + gpio, ir->mask_keycode, data); if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { @@ -218,9 +271,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) int polling = 0; int ir_type = IR_TYPE_OTHER; - /* detect & configure */ if (!dev->has_remote) return -ENODEV; + if (disable_ir) + return -ENODEV; + + /* detect & configure */ switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: @@ -241,6 +297,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x000002; polling = 50; // ms break; + case SAA7134_BOARD_AVACSSMARTTV: + ir_codes = avacssmart_codes; + mask_keycode = 0x00001F; + mask_keyup = 0x000020; + polling = 50; // ms + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index ffa675b91352..b069a1fcdc05 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -50,7 +50,7 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) if (blksize < 0x100) blksize = 0x100; if (blksize > 0x10000) - blksize = 0x100; + blksize = 0x10000; if (blocks < 2) blocks = 2; @@ -74,6 +74,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) if (!dev->oss.bufsize) BUG(); + videobuf_dma_init(&dev->oss.dma); err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, dev->oss.bufsize >> PAGE_SHIFT); if (0 != err) @@ -172,7 +173,7 @@ static int dsp_rec_start(struct saa7134_dev *dev) fmt |= (2 << 4); if (!sign) fmt |= 0x04; - saa_writel(0x588 >> 2, dev->oss.blksize); + saa_writel(0x588 >> 2, dev->oss.blksize -4); saa_writel(0x58c >> 2, 0x543210 | (fmt << 24)); break; } diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index a14bf622d2dd..1c144fe49b3d 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -33,6 +33,8 @@ /* ------------------------------------------------------------------ */ +#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */ + static unsigned int ts_debug = 0; MODULE_PARM(ts_debug,"i"); MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]"); @@ -41,8 +43,9 @@ static unsigned int tsbufs = 4; MODULE_PARM(tsbufs,"i"); MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32"); -#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */ -#define TS_NR_PACKETS 312 +static unsigned int ts_nr_packets = 30; +MODULE_PARM(ts_nr_packets,"i"); +MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); #define dprintk(fmt, arg...) if (ts_debug) \ printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg) @@ -96,7 +99,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]); llength = TS_PACKET_SIZE; - lines = TS_NR_PACKETS; + lines = ts_nr_packets; size = lines * llength; if (0 != buf->vb.baddr && buf->vb.bsize < size) @@ -135,7 +138,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, static int buffer_setup(struct file *file, unsigned int *count, unsigned int *size) { - *size = TS_PACKET_SIZE * TS_NR_PACKETS; + *size = TS_PACKET_SIZE * ts_nr_packets; if (0 == *count) *count = tsbufs; *count = saa7134_buffer_count(*size,*count); @@ -353,7 +356,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, f->fmt.pix.width = 720; /* D1 */ f->fmt.pix.height = 576; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.sizeimage = TS_PACKET_SIZE*TS_NR_PACKETS; + f->fmt.pix.sizeimage = TS_PACKET_SIZE*ts_nr_packets; return 0; } @@ -379,7 +382,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, f->fmt.pix.width = 720; /* D1 */ f->fmt.pix.height = 576; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.sizeimage = TS_PACKET_SIZE*TS_NR_PACKETS; + f->fmt.pix.sizeimage = TS_PACKET_SIZE*ts_nr_packets; return 0; } @@ -408,7 +411,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, case MPEG_SETPARAMS: return ts_init_encoder(dev, arg); - + default: return -ENOIOCTLCMD; } @@ -455,6 +458,10 @@ int saa7134_ts_init1(struct saa7134_dev *dev) tsbufs = 2; if (tsbufs > VIDEO_MAX_FRAME) tsbufs = VIDEO_MAX_FRAME; + if (ts_nr_packets < 4) + ts_nr_packets = 4; + if (ts_nr_packets > 312) + ts_nr_packets = 312; INIT_LIST_HEAD(&dev->ts_q.queue); init_timer(&dev->ts_q.timeout); @@ -472,9 +479,9 @@ int saa7134_ts_init1(struct saa7134_dev *dev) saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* deactivate TS softreset */ saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */ saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); - saa_writeb(SAA7134_TS_DMA0, ((TS_NR_PACKETS-1)&0xff)); - saa_writeb(SAA7134_TS_DMA1, (((TS_NR_PACKETS-1)>>8)&0xff)); - saa_writeb(SAA7134_TS_DMA2, ((((TS_NR_PACKETS-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ + saa_writeb(SAA7134_TS_DMA0, ((ts_nr_packets-1)&0xff)); + saa_writeb(SAA7134_TS_DMA1, (((ts_nr_packets-1)>>8)&0xff)); + saa_writeb(SAA7134_TS_DMA2, ((((ts_nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ return 0; } diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index a896cd83dea5..261d92040dee 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -37,10 +37,6 @@ static unsigned int audio_debug = 0; MODULE_PARM(audio_debug,"i"); MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]"); -static unsigned int audio_carrier = 0; -MODULE_PARM(audio_carrier,"i"); -MODULE_PARM_DESC(audio_carrier,"audio carrier location"); - static unsigned int audio_ddep = 0; MODULE_PARM(audio_ddep,"i"); MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite"); @@ -67,6 +63,30 @@ MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with /* ------------------------------------------------------------------ */ /* saa7134 code */ +static struct mainscan { + char *name; + v4l2_std_id std; + int carr; +} mainscan[] = { + { + .name = "M", + .std = V4L2_STD_NTSC | V4L2_STD_PAL_M, + .carr = 4500, + },{ + .name = "BG", + .std = V4L2_STD_PAL_BG, + .carr = 5500, + },{ + .name = "I", + .std = V4L2_STD_PAL_I, + .carr = 6000, + },{ + .name = "DKL", + .std = V4L2_STD_PAL_DK | V4L2_STD_SECAM, + .carr = 6500, + } +}; + static struct saa7134_tvaudio tvaudio[] = { { .name = "PAL-B/G FM-stereo", @@ -314,15 +334,15 @@ static int tvaudio_sleep(struct saa7134_dev *dev, int timeout) return dev->thread.scan1 != dev->thread.scan2; } -static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier) +static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan) { __s32 left,right,value; if (audio_debug > 1) { int i; - dprintk("debug %d:",carrier); + dprintk("debug %d:",scan->carr); for (i = -150; i <= 150; i += 30) { - tvaudio_setcarrier(dev,carrier+i,carrier+i); + tvaudio_setcarrier(dev,scan->carr+i,scan->carr+i); saa_readl(SAA7134_LEVEL_READOUT1 >> 2); if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) return -1; @@ -334,24 +354,31 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier) } printk("\n"); } - - tvaudio_setcarrier(dev,carrier-90,carrier-90); - saa_readl(SAA7134_LEVEL_READOUT1 >> 2); - if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) - return -1; - left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); - - tvaudio_setcarrier(dev,carrier+90,carrier+90); - saa_readl(SAA7134_LEVEL_READOUT1 >> 2); - if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) - return -1; - right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); - - left >>= 16; - right >>= 16; - value = left > right ? left - right : right - left; - dprintk("scanning %d.%03d MHz => dc is %5d [%d/%d]\n", - carrier/1000,carrier%1000,value,left,right); + + if (dev->tvnorm->id & scan->std) { + tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90); + saa_readl(SAA7134_LEVEL_READOUT1 >> 2); + if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) + return -1; + left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); + + tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90); + saa_readl(SAA7134_LEVEL_READOUT1 >> 2); + if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) + return -1; + right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); + + left >>= 16; + right >>= 16; + value = left > right ? left - right : right - left; + dprintk("scanning %d.%03d MHz [%4s] => dc is %5d [%d/%d]\n", + scan->carr / 1000, scan->carr % 1000, + scan->name, value, left, right); + } else { + value = 0; + dprintk("skipping %d.%03d MHz [%4s]\n", + scan->carr / 1000, scan->carr % 1000, scan->name); + } return value; } @@ -384,6 +411,7 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au case TVAUDIO_FM_K_STEREO: case TVAUDIO_FM_BG_STEREO: idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5; + dprintk("getstereo: fm/stereo: idp=0x%x\n",idp); if (0x03 == (idp & 0x03)) retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; else if (0x05 == (idp & 0x05)) @@ -397,6 +425,7 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au case TVAUDIO_NICAM_FM: case TVAUDIO_NICAM_AM: nicam = saa_readb(SAA7134_NICAM_STATUS); + dprintk("getstereo: nicam=0x%x\n",nicam); switch (nicam & 0x0b) { case 0x08: retval = V4L2_TUNER_SUB_MONO; @@ -458,16 +487,10 @@ static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au static int tvaudio_thread(void *data) { -#define MAX_SCAN 4 - static const int carr_pal[MAX_SCAN] = { 5500, 6000, 6500 }; - static const int carr_ntsc[MAX_SCAN] = { 4500 }; - static const int carr_secam[MAX_SCAN] = { 6500 }; - static const int carr_default[MAX_SCAN] = { 4500, 5500, 6000, 6500 }; struct saa7134_dev *dev = data; - const int *carr_scan; - int carr_vals[4]; - unsigned int i, audio; - int max1,max2,carrier,rx,mode,lastmode; + int carr_vals[ARRAY_SIZE(mainscan)]; + unsigned int i, audio, nscan; + int max1,max2,carrier,rx,mode,lastmode,default_carrier; daemonize("%s", dev->name); allow_signal(SIGTERM); @@ -488,32 +511,40 @@ static int tvaudio_thread(void *data) if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY)) goto restart; - /* find the main carrier */ - carr_scan = carr_default; - if (dev->tvnorm->id & V4L2_STD_PAL) - carr_scan = carr_pal; - if (dev->tvnorm->id & V4L2_STD_NTSC) - carr_scan = carr_ntsc; - if (dev->tvnorm->id & V4L2_STD_SECAM) - carr_scan = carr_secam; - saa_writeb(SAA7134_MONITOR_SELECT,0x00); - tvaudio_setmode(dev,&tvaudio[0],NULL); - for (i = 0; i < MAX_SCAN; i++) { - if (!carr_scan[i]) + max1 = 0; + max2 = 0; + nscan = 0; + carrier = 0; + default_carrier = 0; + for (i = 0; i < ARRAY_SIZE(mainscan); i++) { + if (!(dev->tvnorm->id & mainscan[i].std)) continue; - carr_vals[i] = tvaudio_checkcarrier(dev,carr_scan[i]); - if (dev->thread.scan1 != dev->thread.scan2) - goto restart; + if (!default_carrier) + default_carrier = mainscan[i].carr; + nscan++; } - for (carrier = 0, max1 = 0, max2 = 0, i = 0; i < MAX_SCAN; i++) { - if (!carr_scan[i]) - continue; - if (max1 < carr_vals[i]) { - max2 = max1; - max1 = carr_vals[i]; - carrier = carr_scan[i]; - } else if (max2 < carr_vals[i]) { - max2 = carr_vals[i]; + + if (1 == nscan) { + /* only one candidate -- skip scan ;) */ + max1 = 12345; + carrier = default_carrier; + } else { + /* scan for the main carrier */ + saa_writeb(SAA7134_MONITOR_SELECT,0x00); + tvaudio_setmode(dev,&tvaudio[0],NULL); + for (i = 0; i < ARRAY_SIZE(mainscan); i++) { + carr_vals[i] = tvaudio_checkcarrier(dev, mainscan+i); + if (dev->thread.scan1 != dev->thread.scan2) + goto restart; + } + for (max1 = 0, max2 = 0, i = 0; i < ARRAY_SIZE(mainscan); i++) { + if (max1 < carr_vals[i]) { + max2 = max1; + max1 = carr_vals[i]; + carrier = mainscan[i].carr; + } else if (max2 < carr_vals[i]) { + max2 = carr_vals[i]; + } } } @@ -523,21 +554,17 @@ static int tvaudio_thread(void *data) dev->tvnorm->name, carrier/1000, carrier%1000, max1, max2); dev->last_carrier = carrier; - } else if (0 != audio_carrier) { - /* no carrier -- try insmod option as fallback */ - carrier = audio_carrier; - printk(KERN_WARNING "%s/audio: audio carrier scan failed, " - "using %d.%03d MHz [insmod option]\n", - dev->name, carrier/1000, carrier%1000); + } else if (0 != dev->last_carrier) { /* no carrier -- try last detected one as fallback */ carrier = dev->last_carrier; printk(KERN_WARNING "%s/audio: audio carrier scan failed, " "using %d.%03d MHz [last detected]\n", dev->name, carrier/1000, carrier%1000); + } else { - /* no carrier + no fallback -- try first in list */ - carrier = carr_scan[0]; + /* no carrier + no fallback -- use default */ + carrier = default_carrier; printk(KERN_WARNING "%s/audio: audio carrier scan failed, " "using %d.%03d MHz [default]\n", dev->name, carrier/1000, carrier%1000); @@ -550,7 +577,7 @@ static int tvaudio_thread(void *data) /* find the exact tv audio norm */ for (audio = UNSET, i = 0; i < TVAUDIO; i++) { if (dev->tvnorm->id != UNSET && - dev->tvnorm->id != tvaudio[i].std) + !(dev->tvnorm->id & tvaudio[i].std)) continue; if (tvaudio[i].carr1 != carrier) continue; @@ -722,11 +749,16 @@ static int mute_input_7133(struct saa7134_dev *dev) static int tvaudio_thread_ddep(void *data) { struct saa7134_dev *dev = data; - u32 value, norms; + u32 value, norms, clock; daemonize("%s", dev->name); allow_signal(SIGTERM); + clock = saa7134_boards[dev->board].audio_clock; + if (UNSET != audio_clock_override) + clock = audio_clock_override; + saa_writel(0x598 >> 2, clock); + /* unmute */ saa_dsp_writel(dev, 0x474 >> 2, 0x00); saa_dsp_writel(dev, 0x450 >> 2, 0x00); @@ -769,9 +801,11 @@ static int tvaudio_thread_ddep(void *data) (norms & 0x40) ? " M" : ""); } - /* quick & dirty -- to be fixed up later ... */ + /* kick automatic standard detection */ saa_dsp_writel(dev, 0x454 >> 2, 0); saa_dsp_writel(dev, 0x454 >> 2, norms | 0x80); + + /* setup crossbars */ saa_dsp_writel(dev, 0x464 >> 2, 0x000000); saa_dsp_writel(dev, 0x470 >> 2, 0x101010); diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 4b70156a63aa..acf4a45f7412 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -28,13 +28,15 @@ #include "saa7134-reg.h" #include "saa7134.h" +#define V4L2_I2C_CLIENTS 1 + /* ------------------------------------------------------------------ */ static unsigned int video_debug = 0; static unsigned int gbuffers = 8; static unsigned int noninterlaced = 0; -static unsigned int gbufsize = 768*576*4; -static unsigned int gbufsize_max = 768*576*4; +static unsigned int gbufsize = 720*576*4; +static unsigned int gbufsize_max = 720*576*4; MODULE_PARM(video_debug,"i"); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); MODULE_PARM(gbuffers,"i"); @@ -148,10 +150,65 @@ static struct saa7134_format formats[] = { }; #define FORMATS ARRAY_SIZE(formats) +#define NORM_625_50 \ + .h_start = 0, \ + .h_stop = 719, \ + .video_v_start = 24, \ + .video_v_stop = 311, \ + .vbi_v_start = 7, \ + .vbi_v_stop = 22, \ + .src_timing = 4 + +#define NORM_525_60 \ + .h_start = 0, \ + .h_stop = 703, \ + .video_v_start = 22, \ + .video_v_stop = 22+239, \ + .vbi_v_start = 10, /* FIXME */ \ + .vbi_v_stop = 21, /* FIXME */ \ + .src_timing = 1 + static struct saa7134_tvnorm tvnorms[] = { { - .name = "PAL", + .name = "PAL", /* autodetect */ .id = V4L2_STD_PAL, + NORM_625_50, + + .sync_control = 0x18, + .luma_control = 0x40, + .chroma_ctrl1 = 0x81, + .chroma_gain = 0x2a, + .chroma_ctrl2 = 0x06, + .vgate_misc = 0x1c, + + },{ + .name = "PAL-BG", + .id = V4L2_STD_PAL_BG, + NORM_625_50, + + .sync_control = 0x18, + .luma_control = 0x40, + .chroma_ctrl1 = 0x81, + .chroma_gain = 0x2a, + .chroma_ctrl2 = 0x06, + .vgate_misc = 0x1c, + + },{ + .name = "PAL-I", + .id = V4L2_STD_PAL_I, + NORM_625_50, + + .sync_control = 0x18, + .luma_control = 0x40, + .chroma_ctrl1 = 0x81, + .chroma_gain = 0x2a, + .chroma_ctrl2 = 0x06, + .vgate_misc = 0x1c, + + },{ + .name = "PAL-DK", + .id = V4L2_STD_PAL_DK, + NORM_625_50, .sync_control = 0x18, .luma_control = 0x40, @@ -160,16 +217,10 @@ static struct saa7134_tvnorm tvnorms[] = { .chroma_ctrl2 = 0x06, .vgate_misc = 0x1c, - .h_start = 0, - .h_stop = 719, - .video_v_start = 24, - .video_v_stop = 311, - .vbi_v_start = 7, - .vbi_v_stop = 22, - .src_timing = 4, },{ .name = "NTSC", .id = V4L2_STD_NTSC, + NORM_525_60, .sync_control = 0x59, .luma_control = 0x40, @@ -178,16 +229,10 @@ static struct saa7134_tvnorm tvnorms[] = { .chroma_ctrl2 = 0x0e, .vgate_misc = 0x18, - .h_start = 0, - .h_stop = 719, - .video_v_start = 22, - .video_v_stop = 22+240, - .vbi_v_start = 10, /* FIXME */ - .vbi_v_stop = 21, /* FIXME */ - .src_timing = 1, },{ .name = "SECAM", .id = V4L2_STD_SECAM, + NORM_625_50, .sync_control = 0x18, /* old: 0x58, */ .luma_control = 0x1b, @@ -196,16 +241,10 @@ static struct saa7134_tvnorm tvnorms[] = { .chroma_ctrl2 = 0x00, .vgate_misc = 0x1c, - .h_start = 0, - .h_stop = 719, - .video_v_start = 24, - .video_v_stop = 311, - .vbi_v_start = 7, - .vbi_v_stop = 22, - .src_timing = 4, },{ .name = "PAL-M", .id = V4L2_STD_PAL_M, + NORM_525_60, .sync_control = 0x59, .luma_control = 0x40, @@ -214,16 +253,10 @@ static struct saa7134_tvnorm tvnorms[] = { .chroma_ctrl2 = 0x0e, .vgate_misc = 0x18, - .h_start = 0, - .h_stop = 719, - .video_v_start = 22, - .video_v_stop = 22+240, - .vbi_v_start = 10, /* FIXME */ - .vbi_v_stop = 21, /* FIXME */ - .src_timing = 1, },{ .name = "PAL-Nc", .id = V4L2_STD_PAL_Nc, + NORM_625_50, .sync_control = 0x18, .luma_control = 0x40, @@ -232,35 +265,6 @@ static struct saa7134_tvnorm tvnorms[] = { .chroma_ctrl2 = 0x06, .vgate_misc = 0x1c, - .h_start = 0, - .h_stop = 719, - .video_v_start = 24, - .video_v_stop = 311, - .vbi_v_start = 7, - .vbi_v_stop = 22, - .src_timing = 4, -#if 0 - },{ - .name = "AUTO", - .id = V4L2_STD_PAL|V4L2_STD_NTSC|V4L2_STD_SECAM, - .width = 768, - .height = 576, - - .sync_control = 0x98, - .luma_control = 0x40, - .chroma_ctrl1 = 0x8b, - .chroma_gain = 0x00, - .chroma_ctrl2 = 0x00, - .vgate_misc = 0x18, - - .h_start = 0, - .h_stop = 719, - .video_v_start = 24, - .video_v_stop = 311, - .vbi_v_start = 7, - .vbi_v_stop = 22, - .src_timing = 4, -#endif } }; #define TVNORMS ARRAY_SIZE(tvnorms) @@ -429,7 +433,6 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits) static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) { - struct video_channel c; int luma_control,sync_control,mux; dprintk("set tv norm = %s\n",norm->name); @@ -489,15 +492,22 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40); saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); - /* pass down info to the i2c chips (v4l1) */ - memset(&c,0,sizeof(c)); - c.channel = dev->ctl_input; - c.norm = VIDEO_MODE_PAL; - if (norm->id & V4L2_STD_NTSC) - c.norm = VIDEO_MODE_NTSC; - if (norm->id & V4L2_STD_SECAM) - c.norm = VIDEO_MODE_SECAM; - saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c); +#ifdef V4L2_I2C_CLIENTS + saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id); +#else + { + /* pass down info to the i2c chips (v4l1) */ + struct video_channel c; + memset(&c,0,sizeof(c)); + c.channel = dev->ctl_input; + c.norm = VIDEO_MODE_PAL; + if (norm->id & V4L2_STD_NTSC) + c.norm = VIDEO_MODE_NTSC; + if (norm->id & V4L2_STD_SECAM) + c.norm = VIDEO_MODE_SECAM; + saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c); + } +#endif } static void video_mux(struct saa7134_dev *dev, int input) @@ -593,11 +603,11 @@ static void set_size(struct saa7134_dev *dev, int task, saa_writeb(SAA7134_VIDEO_V_STOP1(task), v_stop & 0xff); saa_writeb(SAA7134_VIDEO_V_STOP2(task), v_stop >> 8); - prescale = dev->crop_defrect.width / width; + prescale = dev->crop_current.width / width; if (0 == prescale) prescale = 1; - xscale = 1024 * dev->crop_defrect.width / prescale / width; - yscale = 512 * div * dev->crop_defrect.height / height; + xscale = 1024 * dev->crop_current.width / prescale / width; + yscale = 512 * div * dev->crop_current.height / height; dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale); set_h_prescale(dev,task,prescale); saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff); @@ -909,10 +919,12 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, /* sanity checks */ if (NULL == fh->fmt) return -EINVAL; - if (fh->width < 48 || - fh->height < 32 || - fh->width > dev->crop_current.width || - fh->height > dev->crop_current.height) + if (fh->width < 48 || + fh->height < 32 || + fh->width/4 > dev->crop_current.width || + fh->height/4 > dev->crop_current.height || + fh->width > dev->crop_bounds.width || + fh->height > dev->crop_bounds.height) return -EINVAL; size = (fh->width * fh->height * fh->fmt->depth) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < size) @@ -1192,7 +1204,7 @@ static int video_open(struct inode *inode, struct file *file) fh->radio = radio; fh->type = type; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - fh->width = 768; + fh->width = 720; fh->height = 576; #ifdef VIDIOC_G_PRIORITY v4l2_prio_open(&dev->prio,&fh->prio); @@ -1409,8 +1421,8 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, return -EINVAL; field = f->fmt.pix.field; - maxw = dev->crop_current.width; - maxh = dev->crop_current.height; + maxw = min(dev->crop_current.width*4, dev->crop_bounds.width); + maxh = min(dev->crop_current.height*4, dev->crop_bounds.height); if (V4L2_FIELD_ANY == field) { field = (f->fmt.pix.height > maxh/2) @@ -1670,10 +1682,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file, v4l2_std_id *id = arg; unsigned int i; - for(i = 0; i < TVNORMS; i++) - if (*id & tvnorms[i].id) + for (i = 0; i < TVNORMS; i++) + if (*id == tvnorms[i].id) break; if (i == TVNORMS) + for (i = 0; i < TVNORMS; i++) + if (*id & tvnorms[i].id) + break; + if (i == TVNORMS) return -EINVAL; down(&dev->lock); @@ -1685,6 +1701,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, spin_unlock_irqrestore(&dev->slock,flags); } else set_tvnorm(dev,&tvnorms[i]); + saa7134_tvaudio_do_scan(dev); up(&dev->lock); return 0; } @@ -1817,7 +1834,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; down(&dev->lock); dev->ctl_freq = f->frequency; +#ifdef V4L2_I2C_CLIENTS + saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f); +#else saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&dev->ctl_freq); +#endif saa7134_tvaudio_do_scan(dev); up(&dev->lock); return 0; @@ -2064,7 +2085,6 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_TUNER: { struct v4l2_tuner *t = arg; - struct video_tuner vt; if (0 != t->index) return -EINVAL; @@ -2073,10 +2093,17 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, strcpy(t->name, "Radio"); t->rangelow = (int)(65*16); t->rangehigh = (int)(108*16); - - memset(&vt,0,sizeof(vt)); - saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt); - t->signal = vt.signal; + +#ifdef V4L2_I2C_CLIENTS + saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,t); +#else + { + struct video_tuner vt; + memset(&vt,0,sizeof(vt)); + saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt); + t->signal = vt.signal; + } +#endif return 0; } case VIDIOC_ENUMINPUT: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 2eccffc67b57..f4d3469496d8 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -19,7 +19,7 @@ */ #include <linux/version.h> -#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,11) +#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,12) #include <linux/pci.h> #include <linux/i2c.h> @@ -152,6 +152,10 @@ struct saa7134_format { #define SAA7134_BOARD_ECS_TVP3XP_4CB5 31 #define SAA7134_BOARD_AVACSSMARTTV 32 #define SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER 33 +#define SAA7134_BOARD_NOVAC_PRIMETV7133 34 +#define SAA7134_BOARD_AVERMEDIA_305 35 +#define SAA7133_BOARD_UPMOST_PURPLE_TV 36 +#define SAA7134_BOARD_ITEMS_MTV005 37 #define SAA7134_INPUT_MAX 8 diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index ddc380e1a878..9768829bd2a2 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -21,7 +21,7 @@ Note: OP2 of tda988x must be set to 1, else MT2032 is disabled! - KNC One TV-Station RDS (saa7134) */ - + /* Addresses to scan */ static unsigned short normal_i2c[] = { @@ -33,22 +33,30 @@ static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END}; I2C_CLIENT_INSMOD; /* insmod options */ -static int debug = 0; -static char *pal = "b"; -static char *secam = "l"; +static unsigned int debug = 0; MODULE_PARM(debug,"i"); -MODULE_PARM(pal,"s"); -MODULE_PARM(secam,"s"); MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ +#define UNSET (-1U) +#define PREFIX "tda9885/6/7: " #define dprintk if (debug) printk struct tda9887 { - struct i2c_client client; - int radio,tvnorm; - int pinnacle_id; + struct i2c_client client; + v4l2_std_id std; + unsigned int radio; + unsigned int pinnacle_id; + unsigned int using_v4l2; +}; + +struct tvnorm { + v4l2_std_id std; + char *name; + unsigned char b; + unsigned char c; + unsigned char e; }; static struct i2c_driver driver; @@ -60,7 +68,7 @@ static struct i2c_client client_template; // TDA defines // -//// first reg +//// first reg (b) #define cVideoTrapBypassOFF 0x00 // bit b0 #define cVideoTrapBypassON 0x01 // bit b0 @@ -85,7 +93,7 @@ static struct i2c_client client_template; #define cOutputPort2Inactive 0x80 // bit b7 -//// second reg +//// second reg (c) #define cDeemphasisOFF 0x00 // bit c5 #define cDeemphasisON 0x20 // bit c5 @@ -96,7 +104,7 @@ static struct i2c_client client_template; #define cAudioGain6 0x80 // bit c7 -//// third reg +//// third reg (e) #define cAudioIF_4_5 0x00 // bit e0:1 #define cAudioIF_5_5 0x01 // bit e0:1 #define cAudioIF_6_0 0x02 // bit e0:1 @@ -122,126 +130,287 @@ static struct i2c_client client_template; #define cAgcOutON 0x80 // bit e7 #define cAgcOutOFF 0x00 // bit e7 -static int tda9887_miro(struct tda9887 *t) +/* ---------------------------------------------------------------------- */ + +static struct tvnorm tvnorms[] = { + { + .std = V4L2_STD_PAL_BG, + .name = "PAL-BG", + .b = ( cNegativeFmTV | + cQSS ), + .c = ( cDeemphasisON | + cDeemphasis50 ), + .e = ( cAudioIF_5_5 | + cVideoIF_38_90 ), + },{ + .std = V4L2_STD_PAL_I, + .name = "PAL-I", + .b = ( cNegativeFmTV | + cQSS ), + .c = ( cDeemphasisON | + cDeemphasis50 ), + .e = ( cAudioIF_6_0 | + cVideoIF_38_90 ), + },{ + .std = V4L2_STD_PAL_DK, + .name = "PAL-DK", + .b = ( cNegativeFmTV | + cQSS ), + .c = ( cDeemphasisON | + cDeemphasis50 ), + .e = ( cAudioIF_6_5 | + cVideoIF_38_00 ), + },{ + .std = V4L2_STD_PAL_M | V4L2_STD_PAL_N, + .name = "PAL-M/N", + .b = ( cNegativeFmTV | + cQSS ), + .c = ( cDeemphasisON | + cDeemphasis75 ), + .e = ( cAudioIF_4_5 | + cVideoIF_45_75 ), + },{ + .std = V4L2_STD_SECAM_L, + .name = "SECAM-L", + .b = ( cPositiveAmTV | + cQSS ), + .e = ( cAudioIF_6_5 | + cVideoIF_38_90 ), + },{ + .std = V4L2_STD_SECAM_DK, + .name = "SECAM-DK", + .b = ( cNegativeFmTV | + cQSS ), + .c = ( cDeemphasisON | + cDeemphasis50 ), + .e = ( cAudioIF_6_5 | + cVideoIF_38_00 ), + },{ + .std = V4L2_STD_NTSC_M, + .name = "NTSC-M", + .b = ( cNegativeFmTV | + cQSS ), + .c = ( cDeemphasisON | + cDeemphasis50 ), + .e = ( cGating_36 | + cAudioIF_4_5 | + cVideoIF_45_75 ), + },{ + .std = V4L2_STD_NTSC_M_JP, + .name = "NTSC-JP", + .b = ( cNegativeFmTV | + cQSS ), + .c = ( cDeemphasisON | + cDeemphasis50 ), + .e = ( cGating_36 | + cAudioIF_4_5 | + cVideoIF_58_75 ), + } +}; + +static struct tvnorm radio = { + .name = "radio", + .b = ( cFmRadio | + cQSS ), + .c = ( cDeemphasisON | + cDeemphasis50 ), + .e = ( cAudioIF_5_5 | + cRadioIF_38_90 ), +}; + +/* ---------------------------------------------------------------------- */ + +static void dump_read_message(unsigned char *buf) { - int rc; - u8 bData[4] = { 0 }; - u8 bVideoIF = 0; - u8 bAudioIF = 0; - u8 bDeEmphasis = 0; - u8 bDeEmphVal = 0; - u8 bModulation = 0; - u8 bCarrierMode = 0; - u8 bOutPort1 = cOutputPort1Inactive; -#if 0 - u8 bOutPort2 = cOutputPort2Inactive & mbTADState; // store i2c tuner state -#else - u8 bOutPort2 = cOutputPort2Inactive; -#endif - u8 bVideoTrap = cVideoTrapBypassOFF; -#if 1 - u8 bTopAdjust = 0x0e /* -2dB */; -#else - u8 bTopAdjust = 0; -#endif + static char *afc[16] = { + "- 12.5 kHz", + "- 37.5 kHz", + "- 62.5 kHz", + "- 87.5 kHz", + "-112.5 kHz", + "-137.5 kHz", + "-162.5 kHz", + "-187.5 kHz [min]", + "+187.5 kHz [max]", + "+162.5 kHz", + "+137.5 kHz", + "+112.5 kHz", + "+ 87.5 kHz", + "+ 62.5 kHz", + "+ 37.5 kHz", + "+ 12.5 kHz", + }; + printk(PREFIX "read: 0x%2x\n", buf[0]); + printk(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); + printk(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); + printk(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); + printk(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); +} -#if 0 - if (mParams.fVideoTrap) - bVideoTrap = cVideoTrapBypassON; -#endif +static void dump_write_message(unsigned char *buf) +{ + static char *sound[4] = { + "AM/TV", + "FM/radio", + "FM/TV", + "FM/radio" + }; + static char *adjust[32] = { + "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9", + "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", + "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", + "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15" + }; + static char *deemph[4] = { + "no", "no", "75", "50" + }; + static char *carrier[4] = { + "4.5 MHz", + "5.5 MHz", + "6.0 MHz", + "6.5 MHz / AM" + }; + static char *vif[8] = { + "58.75 MHz", + "45.75 MHz", + "38.9 MHz", + "38.0 MHz", + "33.9 MHz", + "33.4 MHz", + "45.75 MHz + pin13", + "38.9 MHz + pin13", + }; + static char *rif[4] = { + "44 MHz", + "52 MHz", + "52 MHz", + "44 MHz", + }; + + printk(PREFIX "write: byte B 0x%02x\n",buf[1]); + printk(" B0 video mode : %s\n", + (buf[1] & 0x01) ? "video trap" : "sound trap"); + printk(" B1 auto mute fm : %s\n", + (buf[1] & 0x02) ? "yes" : "no"); + printk(" B2 carrier mode : %s\n", + (buf[1] & 0x04) ? "QSS" : "Intercarrier"); + printk(" B3-4 tv sound/radio : %s\n", + sound[(buf[1] & 0x18) >> 3]); + printk(" B5 force mute audio: %s\n", + (buf[1] & 0x20) ? "yes" : "no"); + printk(" B6 output port 1 : %s\n", + (buf[1] & 0x40) ? "high" : "low"); + printk(" B7 output port 2 : %s\n", + (buf[1] & 0x80) ? "high" : "low"); + + printk(PREFIX "write: byte C 0x%02x\n",buf[2]); + printk(" C0-4 top adjustment : %s dB\n", adjust[buf[2] & 0x1f]); + printk(" C5-6 de-emphasis : %s\n", deemph[(buf[2] & 0x60) >> 5]); + printk(" C7 audio gain : %s\n", + (buf[2] & 0x80) ? "-6" : "0"); + + printk(PREFIX "write: byte E 0x%02x\n",buf[3]); + printk(" E0-1 sound carrier : %s\n", + carrier[(buf[3] & 0x03)]); + printk(" E6 l pll ganting : %s\n", + (buf[3] & 0x40) ? "36" : "13"); + + if (buf[1] & 0x08) { + /* radio */ + printk(" E2-4 video if : %s\n", + rif[(buf[3] & 0x0c) >> 2]); + printk(" E7 vif agc output : %s\n", + (buf[3] & 0x80) + ? ((buf[3] & 0x10) ? "fm-agc radio" : "sif-agc radio") + : "fm radio carrier afc"); + } else { + /* video */ + printk(" E2-4 video if : %s\n", + vif[(buf[3] & 0x1c) >> 2]); + printk(" E5 tuner gain : %s\n", + (buf[3] & 0x80) + ? ((buf[3] & 0x20) ? "external" : "normal") + : ((buf[3] & 0x20) ? "minimum" : "normal")); + printk(" E7 vif agc output : %s\n", + (buf[3] & 0x80) + ? ((buf[3] & 0x20) + ? "pin3 port, pin22 vif agc out" + : "pin22 port, pin3 vif acg ext in") + : "pin3+pin22 port"); + } + printk("--\n"); +} + +/* ---------------------------------------------------------------------- */ + +static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) +{ + struct tvnorm *norm = NULL; + int i; if (t->radio) { - bVideoTrap = cVideoTrapBypassOFF; - bCarrierMode = cQSS; - bModulation = cFmRadio; - bOutPort1 = cOutputPort1Inactive; - bDeEmphasis = cDeemphasisON; - if (3 == t->pinnacle_id) { - /* ntsc */ - bDeEmphVal = cDeemphasis75; - bAudioIF = cAudioIF_4_5; - bVideoIF = cRadioIF_45_75; - } else { - /* pal */ - bAudioIF = cAudioIF_5_5; - bVideoIF = cRadioIF_38_90; - bDeEmphVal = cDeemphasis50; + norm = &radio; + } else { + for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { + if (tvnorms[i].std & t->std) { + norm = tvnorms+i; + break; + } } + } + if (NULL == norm) { + dprintk(PREFIX "Oops: no tvnorm entry found\n"); + return -1; + } + + dprintk(PREFIX "configure for: %s\n",norm->name); + buf[1] = norm->b; + buf[2] = norm->c; + buf[3] = norm->e; + return 0; +} + +static unsigned int port1 = 1; +static unsigned int port2 = 1; +static unsigned int qss = UNSET; +static unsigned int adjust = 0x10; +MODULE_PARM(port1,"i"); +MODULE_PARM(port2,"i"); +MODULE_PARM(qss,"i"); +MODULE_PARM(adjust,"i"); + +static int tda9887_set_insmod(struct tda9887 *t, char *buf) +{ + if (port1) + buf[1] |= cOutputPort1Inactive; + if (port2) + buf[1] |= cOutputPort2Inactive; + if (UNSET != qss) { + if (qss) + buf[1] |= cQSS; + else + buf[1] &= ~cQSS; + } + + if (adjust >= 0x00 && adjust < 0x20) + buf[2] |= adjust; + return 0; +} + +/* ---------------------------------------------------------------------- */ - } else if (t->tvnorm == VIDEO_MODE_PAL) { - bDeEmphasis = cDeemphasisON; - bDeEmphVal = cDeemphasis50; - bModulation = cNegativeFmTV; - bOutPort1 = cOutputPort1Inactive; +static int tda9887_set_pinnacle(struct tda9887 *t, char *buf) +{ + unsigned int bCarrierMode = UNSET; + + if (t->std & V4L2_STD_PAL) { if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) { bCarrierMode = cIntercarrier; } else { - // stereo boards bCarrierMode = cQSS; } - switch (pal[0]) { - case 'b': - case 'g': - case 'h': - bVideoIF = cVideoIF_38_90; - bAudioIF = cAudioIF_5_5; - break; - case 'd': - bVideoIF = cVideoIF_38_00; - bAudioIF = cAudioIF_6_5; - break; - case 'i': - bVideoIF = cVideoIF_38_90; - bAudioIF = cAudioIF_6_0; - break; - case 'm': - case 'n': - bVideoIF = cVideoIF_45_75; - bAudioIF = cAudioIF_4_5; - bDeEmphVal = cDeemphasis75; - if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { - bCarrierMode = cIntercarrier; - } else { - bCarrierMode = cQSS; - } - break; - } - - } else if (t->tvnorm == VIDEO_MODE_SECAM) { - bAudioIF = cAudioIF_6_5; - bDeEmphasis = cDeemphasisON; - bDeEmphVal = cDeemphasis50; - bModulation = cNegativeFmTV; - bCarrierMode = cQSS; - bOutPort1 = cOutputPort1Inactive; - switch (secam[0]) { - case 'd': - bVideoIF = cVideoIF_38_00; - break; - case 'k': - bVideoIF = cVideoIF_38_90; - break; - case 'l': - bVideoIF = cVideoIF_38_90; - bDeEmphasis = cDeemphasisOFF; - bDeEmphVal = cDeemphasis75; - bModulation = cPositiveAmTV; - break; - case 'L' /* L1 */: - bVideoIF = cVideoIF_33_90; - bDeEmphasis = cDeemphasisOFF; - bDeEmphVal = cDeemphasis75; - bModulation = cPositiveAmTV; - break; - } - - } else if (t->tvnorm == VIDEO_MODE_NTSC) { - bVideoIF = cVideoIF_45_75; - bAudioIF = cAudioIF_4_5; - bDeEmphasis = cDeemphasisON; - bDeEmphVal = cDeemphasis75; - bModulation = cNegativeFmTV; - bOutPort1 = cOutputPort1Inactive; + } + if (t->std & V4L2_STD_NTSC) { if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { bCarrierMode = cIntercarrier; } else { @@ -249,99 +418,102 @@ static int tda9887_miro(struct tda9887 *t) } } - bData[1] = bVideoTrap | // B0: video trap bypass - cAutoMuteFmInactive | // B1: auto mute - bCarrierMode | // B2: InterCarrier for PAL else QSS - bModulation | // B3 - B4: positive AM TV for SECAM only - cForcedMuteAudioOFF | // B5: forced Audio Mute (off) - bOutPort1 | // B6: Out Port 1 - bOutPort2; // B7: Out Port 2 - bData[2] = bTopAdjust | // C0 - C4: Top Adjust 0 == -16dB 31 == 15dB - bDeEmphasis | // C5: De-emphasis on/off - bDeEmphVal | // C6: De-emphasis 50/75 microsec - cAudioGain0; // C7: normal audio gain - bData[3] = bAudioIF | // E0 - E1: Sound IF - bVideoIF | // E2 - E4: Video IF - cTunerGainNormal | // E5: Tuner gain (normal) - cGating_18 | // E6: Gating (18%) - cAgcOutOFF; // E7: VAGC (off) - - dprintk("tda9885/6/7: 0x%02x 0x%02x 0x%02x [pinnacle_id=%d]\n", - bData[1],bData[2],bData[3],t->pinnacle_id); - if (4 != (rc = i2c_master_send(&t->client,bData,4))) - printk("tda9885/6/7: i2c i/o error: rc == %d (should be 4)\n",rc); + if (bCarrierMode != UNSET) { + buf[1] &= ~0x04; + buf[1] |= bCarrierMode; + } return 0; } /* ---------------------------------------------------------------------- */ -#if 0 -/* just for reference: old knc-one saa7134 stuff */ -static unsigned char buf_pal_bg[] = { 0x00, 0x16, 0x70, 0x49 }; -static unsigned char buf_pal_i[] = { 0x00, 0x16, 0x70, 0x4a }; -static unsigned char buf_pal_dk[] = { 0x00, 0x16, 0x70, 0x4b }; -static unsigned char buf_pal_l[] = { 0x00, 0x06, 0x50, 0x4b }; -static unsigned char buf_fm_stereo[] = { 0x00, 0x0e, 0x0d, 0x77 }; -#endif - -static unsigned char buf_pal_bg[] = { 0x00, 0x96, 0x70, 0x49 }; -static unsigned char buf_pal_i[] = { 0x00, 0x96, 0x70, 0x4a }; -static unsigned char buf_pal_dk[] = { 0x00, 0x96, 0x70, 0x4b }; -static unsigned char buf_pal_l[] = { 0x00, 0x86, 0x50, 0x4b }; -static unsigned char buf_fm_stereo[] = { 0x00, 0x8e, 0x0d, 0x77 }; -static unsigned char buf_ntsc[] = { 0x00, 0x96, 0x70, 0x44 }; -static unsigned char buf_ntsc_jp[] = { 0x00, 0x96, 0x70, 0x40 }; +static char *pal = "-"; +MODULE_PARM(pal,"s"); +static char *secam = "-"; +MODULE_PARM(secam,"s"); -static int tda9887_configure(struct tda9887 *t) +static int tda9887_fixup_std(struct tda9887 *t) { - unsigned char *buf = NULL; - int rc; - - if (t->radio) { - dprintk("tda9885/6/7: FM Radio mode\n"); - buf = buf_fm_stereo; - - } else if (t->tvnorm == VIDEO_MODE_PAL) { - dprintk("tda9885/6/7: PAL-%c mode\n",pal[0]); + /* get more precise norm info from insmod option */ + if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { switch (pal[0]) { case 'b': + case 'B': case 'g': - buf = buf_pal_bg; + case 'G': + dprintk(PREFIX "insmod fixup: PAL => PAL-BG\n"); + t->std = V4L2_STD_PAL_BG; break; case 'i': - buf = buf_pal_i; + case 'I': + dprintk(PREFIX "insmod fixup: PAL => PAL-I\n"); + t->std = V4L2_STD_PAL_I; + break; + case 'd': + case 'D': + case 'k': + case 'K': + dprintk(PREFIX "insmod fixup: PAL => PAL-DK\n"); + t->std = V4L2_STD_PAL_DK; break; + } + } + if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { + switch (secam[0]) { case 'd': + case 'D': case 'k': - buf = buf_pal_dk; + case 'K': + dprintk(PREFIX "insmod fixup: SECAM => SECAM-DK\n"); + t->std = V4L2_STD_SECAM_DK; break; case 'l': - buf = buf_pal_l; + case 'L': + dprintk(PREFIX "insmod fixup: SECAM => SECAM-L\n"); + t->std = V4L2_STD_SECAM_L; break; } + } + return 0; +} - } else if (t->tvnorm == VIDEO_MODE_NTSC) { - dprintk("tda9885/6/7: NTSC mode\n"); - buf = buf_ntsc; +static int tda9887_status(struct tda9887 *t) +{ + unsigned char buf[1]; + int rc; - } else if (t->tvnorm == VIDEO_MODE_SECAM) { - dprintk("tda9885/6/7: SECAM mode\n"); - buf = buf_pal_l; + memset(buf,0,sizeof(buf)); + if (1 != (rc = i2c_master_recv(&t->client,buf,1))) + printk(PREFIX "i2c i/o error: rc == %d (should be 1)\n",rc); + dump_read_message(buf); + return 0; +} - } else if (t->tvnorm == 6 /* BTTV hack */) { - dprintk("tda9885/6/7: NTSC-Japan mode\n"); - buf = buf_ntsc_jp; - } +static int tda9887_configure(struct tda9887 *t) +{ + unsigned char buf[4]; + int rc; - if (NULL == buf) { - printk("tda9885/6/7 unknown norm=%d\n",t->tvnorm); - return 0; + memset(buf,0,sizeof(buf)); + tda9887_set_tvnorm(t,buf); + if (UNSET != t->pinnacle_id) { + tda9887_set_pinnacle(t,buf); } + tda9887_set_insmod(t,buf); - dprintk("tda9885/6/7: 0x%02x 0x%02x 0x%02x\n", + dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n", buf[1],buf[2],buf[3]); + if (debug > 1) + dump_write_message(buf); + if (4 != (rc = i2c_master_send(&t->client,buf,4))) - printk("tda9885/6/7: i2c i/o error: rc == %d (should be 4)\n",rc); + printk(PREFIX "i2c i/o error: rc == %d (should be 4)\n",rc); + + if (debug > 2) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + tda9887_status(t); + } return 0; } @@ -354,14 +526,14 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) client_template.adapter = adap; client_template.addr = addr; - printk("tda9887: chip found @ 0x%x\n", addr<<1); + printk(PREFIX "chip found @ 0x%x\n", addr<<1); if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) return -ENOMEM; memset(t,0,sizeof(*t)); - t->client = client_template; - t->pinnacle_id = -1; - t->tvnorm=VIDEO_MODE_PAL; + t->client = client_template; + t->std = 0;; + t->pinnacle_id = UNSET; i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); @@ -394,6 +566,13 @@ static int tda9887_detach(struct i2c_client *client) return 0; } +#define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ + printk(PREFIX "switching to v4l2\n"); \ + t->using_v4l2 = 1; +#define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ + printk(PREFIX "ignore v4l1 call\n"); \ + return 0; } + static int tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -404,10 +583,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) /* --- configuration --- */ case AUDC_SET_RADIO: t->radio = 1; - if (-1 != t->pinnacle_id) - tda9887_miro(t); - else - tda9887_configure(t); + tda9887_configure(t); break; case AUDC_CONFIG_PINNACLE: @@ -415,7 +591,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) int *i = arg; t->pinnacle_id = *i; - tda9887_miro(t); + tda9887_configure(t); break; } /* --- v4l ioctls --- */ @@ -423,16 +599,52 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) kernel pointer here... */ case VIDIOCSCHAN: { + static const v4l2_std_id map[] = { + [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, + [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, + [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, + [ 4 /* bttv */ ] = V4L2_STD_PAL_M, + [ 5 /* bttv */ ] = V4L2_STD_PAL_N, + [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, + }; struct video_channel *vc = arg; - t->radio = 0; - t->tvnorm = vc->norm; - if (-1 != t->pinnacle_id) - tda9887_miro(t); - else - tda9887_configure(t); + CHECK_V4L2; + t->radio = 0; + if (vc->norm < ARRAY_SIZE(map)) + t->std = map[vc->norm]; + tda9887_fixup_std(t); + tda9887_configure(t); + break; + } + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + + SWITCH_V4L2; + t->radio = 0; + t->std = *id; + tda9887_fixup_std(t); + tda9887_configure(t); break; } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + SWITCH_V4L2; + if (V4L2_TUNER_ANALOG_TV == f->type) { + if (t->radio == 0) + return 0; + t->radio = 0; + } + if (V4L2_TUNER_RADIO == f->type) { + if (t->radio == 1) + return 0; + t->radio = 1; + } + tda9887_configure(t); + } default: /* nothing */ break; diff --git a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c index ab7030447a34..18e1118df0c6 100644 --- a/drivers/media/video/tuner.c +++ b/drivers/media/video/tuner.c @@ -26,15 +26,17 @@ I2C_CLIENT_INSMOD; static unsigned int debug = 0; static unsigned int type = UNSET; static unsigned int addr = 0; -static char *pal = "b"; static unsigned int tv_range[2] = { 44, 958 }; static unsigned int radio_range[2] = { 65, 108 }; +static unsigned int tv_antenna = 1; +static unsigned int radio_antenna = 0; MODULE_PARM(debug,"i"); MODULE_PARM(type,"i"); MODULE_PARM(addr,"i"); MODULE_PARM(tv_range,"2i"); MODULE_PARM(radio_range,"2i"); -MODULE_PARM(pal,"s"); +MODULE_PARM(tv_antenna,"i"); +MODULE_PARM(radio_antenna,"i"); #define optimize_vco 1 @@ -48,10 +50,10 @@ static int this_adap; struct tuner { unsigned int type; /* chip type */ unsigned int freq; /* keep track of the current settings */ - unsigned int std; + v4l2_std_id std; + int using_v4l2; unsigned int radio; - unsigned int mode; /* current norm for multi-norm tuners */ unsigned int input; // only for MT2032 @@ -537,15 +539,16 @@ static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) int if2,from,to; // signal bandwidth and picture carrier - if (t->mode == VIDEO_MODE_NTSC) { - from=40750*1000; - to=46750*1000; - if2=45750*1000; + if (t->std & V4L2_STD_525_60) { + // NTSC + from = 40750*1000; + to = 46750*1000; + if2 = 45750*1000; } else { - // Pal - from=32900*1000; - to=39900*1000; - if2=38900*1000; + // PAL + from = 32900*1000; + to = 39900*1000; + if2 = 38900*1000; } mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, @@ -619,6 +622,17 @@ static int mt2032_init(struct i2c_client *c) return(1); } +static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) +{ + unsigned char buf[2]; + int ret; + + buf[0] = 6; + buf[1] = antenna ? 0x11 : 0x10; + ret=i2c_master_send(c,buf,2); + dprintk("mt2050: enabled antenna connector %d\n", antenna); +} + static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2) { unsigned int if1=1218*1000*1000; @@ -683,13 +697,15 @@ static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); unsigned int if2; - if (t->mode == VIDEO_MODE_NTSC) { - if2=45750*1000; + if (t->std & V4L2_STD_525_60) { + // NTSC + if2 = 45750*1000; } else { - // Pal - if2=38900*1000; + // PAL + if2 = 38900*1000; } - mt2050_set_if_freq(c,freq*62500,if2); + mt2050_set_if_freq(c, freq*62500, if2); + mt2050_set_antenna(c, tv_antenna); } static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -698,6 +714,7 @@ static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) int if2 = t->radio_if2; mt2050_set_if_freq(c, freq*62500, if2); + mt2050_set_antenna(c, radio_antenna); } static int mt2050_init(struct i2c_client *c) @@ -731,8 +748,8 @@ static int microtune_init(struct i2c_client *c) unsigned char buf[21]; int company_code; - buf[0] = 0; - t->tv_freq = NULL; + memset(buf,0,sizeof(buf)); + t->tv_freq = NULL; t->radio_freq = NULL; name = "unknown"; @@ -751,6 +768,9 @@ static int microtune_init(struct i2c_client *c) company_code = buf[0x11] << 8 | buf[0x12]; printk("tuner: microtune: companycode=%04x part=%02x rev=%02x\n", company_code,buf[0x13],buf[0x14]); + +#if 0 + /* seems to cause more problems than it solves ... */ switch (company_code) { case 0x30bf: case 0x3cbf: @@ -764,6 +784,7 @@ static int microtune_init(struct i2c_client *c) printk("tuner: microtune: unknown companycode\n"); return 0; } +#endif if (buf[0x13] < ARRAY_SIZE(microtune_part) && NULL != microtune_part[buf[0x13]]) @@ -811,54 +832,40 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ config &= ~0x02; - if (t->mode == VIDEO_MODE_SECAM) + if (t->std & V4L2_STD_SECAM) config |= 0x02; break; case TUNER_TEMIC_4046FM5: config &= ~0x0f; - switch (pal[0]) { - case 'i': - case 'I': + + if (t->std & V4L2_STD_PAL_BG) { + config |= TEMIC_SET_PAL_BG; + + } else if (t->std & V4L2_STD_PAL_I) { config |= TEMIC_SET_PAL_I; - break; - case 'd': - case 'D': + + } else if (t->std & V4L2_STD_PAL_DK) { config |= TEMIC_SET_PAL_DK; - break; - case 'l': - case 'L': + + } else if (t->std & V4L2_STD_SECAM_L) { config |= TEMIC_SET_PAL_L; - break; - case 'b': - case 'B': - case 'g': - case 'G': - default: - config |= TEMIC_SET_PAL_BG; - break; + } break; case TUNER_PHILIPS_FQ1216ME: config &= ~0x0f; - switch (pal[0]) { - case 'i': - case 'I': + + if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { + config |= PHILIPS_SET_PAL_BGDK; + + } else if (t->std & V4L2_STD_PAL_I) { config |= PHILIPS_SET_PAL_I; - break; - case 'l': - case 'L': + + } else if (t->std & V4L2_STD_SECAM_L) { config |= PHILIPS_SET_PAL_L; - break; - case 'd': - case 'D': - case 'b': - case 'B': - case 'g': - case 'G': - config |= PHILIPS_SET_PAL_BGDK; - break; + } break; @@ -867,12 +874,9 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* 0x01 -> ATSC antenna input 2 */ /* 0x02 -> NTSC antenna input 1 */ /* 0x03 -> NTSC antenna input 2 */ - config &= ~0x03; -#ifdef VIDEO_MODE_ATSC - if (VIDEO_MODE_ATSC != t->mode) + if (t->std & V4L2_STD_ATSC) config |= 2; -#endif /* FIXME: input */ break; } @@ -990,6 +994,22 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) t->radio_freq(c,freq); } +static void set_freq(struct i2c_client *c, unsigned long freq) +{ + struct tuner *t = i2c_get_clientdata(c); + + if (t->radio) { + dprintk("tuner: radio freq set to %lu.%02lu\n", + freq/16,freq%16*100/16); + set_radio_freq(c,freq); + } else { + dprintk("tuner: tv freq set to %lu.%02lu\n", + freq/16,freq%16*100/16); + set_tv_freq(c, freq); + } + t->freq = freq; +} + static void set_type(struct i2c_client *c, unsigned int type, char *source) { struct tuner *t = i2c_get_clientdata(c); @@ -1019,6 +1039,38 @@ static void set_type(struct i2c_client *c, unsigned int type, char *source) } } +static char *pal = "-"; +MODULE_PARM(pal,"s"); + +static int tuner_fixup_std(struct tuner *t) +{ + if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { + /* get more precise norm info from insmod option */ + switch (pal[0]) { + case 'b': + case 'B': + case 'g': + case 'G': + dprintk("insmod fixup: PAL => PAL-BG\n"); + t->std = V4L2_STD_PAL_BG; + break; + case 'i': + case 'I': + dprintk("insmod fixup: PAL => PAL-I\n"); + t->std = V4L2_STD_PAL_I; + break; + case 'd': + case 'D': + case 'k': + case 'K': + dprintk("insmod fixup: PAL => PAL-DK\n"); + t->std = V4L2_STD_PAL_DK; + break; + } + } + return 0; +} + /* ---------------------------------------------------------------------- */ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) @@ -1054,7 +1106,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) set_type(client, type, "insmod option"); printk("tuner: The type=<n> insmod option will go away soon.\n"); printk("tuner: Please use the tuner=<n> option provided by\n"); - printk("tuner: tv card core driver (bttv, saa7134, ...) instead.\n"); + printk("tuner: tv aard core driver (bttv, saa7134, ...) instead.\n"); } return 0; } @@ -1094,6 +1146,13 @@ static int tuner_detach(struct i2c_client *client) return 0; } +#define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ + printk("tuner: switching to v4l2\n"); \ + t->using_v4l2 = 1; +#define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ + printk("tuner: ignore v4l1 call\n"); \ + return 0; } + static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -1130,10 +1189,21 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) kernel pointer here... */ case VIDIOCSCHAN: { + static const v4l2_std_id map[] = { + [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, + [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, + [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, + [ 4 /* bttv */ ] = V4L2_STD_PAL_M, + [ 5 /* bttv */ ] = V4L2_STD_PAL_N, + [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, + }; struct video_channel *vc = arg; + CHECK_V4L2; t->radio = 0; - t->mode = vc->norm; + if (vc->norm < ARRAY_SIZE(map)) + t->std = map[vc->norm]; + tuner_fixup_std(t); if (t->freq) set_tv_freq(client,t->freq); return 0; @@ -1142,22 +1212,15 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { unsigned long *v = arg; - if (t->radio) { - dprintk("tuner: radio freq set to %lu.%02lu\n", - (*v)/16,(*v)%16*100/16); - set_radio_freq(client,*v); - } else { - dprintk("tuner: tv freq set to %lu.%02lu\n", - (*v)/16,(*v)%16*100/16); - set_tv_freq(client,*v); - } - t->freq = *v; + CHECK_V4L2; + set_freq(client,*v); return 0; } case VIDIOCGTUNER: { struct video_tuner *vt = arg; + CHECK_V4L2; if (t->radio) vt->signal = tuner_signal(client); return 0; @@ -1165,10 +1228,52 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOCGAUDIO: { struct video_audio *va = arg; + + CHECK_V4L2; if (t->radio) va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO); return 0; } + + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + + SWITCH_V4L2; + t->radio = 0; + t->std = *id; + tuner_fixup_std(t); + if (t->freq) + set_freq(client,t->freq); + break; + } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + SWITCH_V4L2; + if (V4L2_TUNER_ANALOG_TV == f->type) { + t->radio = 0; + } + if (V4L2_TUNER_RADIO == f->type) { + if (!t->radio) { + set_tv_freq(client,400*16); + t->radio = 1; + } + } + t->freq = f->frequency; + set_freq(client,t->freq); + break; + } + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *tuner = arg; + + SWITCH_V4L2; + if (t->radio) + tuner->signal = tuner_signal(client); + break; + } default: /* nothing */ break; diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index f541a06df378..6b2eee6de4dc 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -5,10 +5,10 @@ * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data (thus it is probably not useful for USB as - * data often must be uncompressed by the drivers). + * to touch the video data (thus it is probably not useful for USB 1.1 + * as data often must be uncompressed by the drivers). * - * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> + * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] * * 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 @@ -28,6 +28,11 @@ #include <media/video-buf.h> +#define MAGIC_DMABUF 0x19721112 +#define MAGIC_BUFFER 0x20040302 +#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ + { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } + static int debug = 0; MODULE_DESCRIPTION("helper module to manage video4linux pci dma buffers"); @@ -109,6 +114,12 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) /* --------------------------------------------------------------------- */ +void videobuf_dma_init(struct videobuf_dmabuf *dma) +{ + memset(dma,0,sizeof(*dma)); + dma->magic = MAGIC_DMABUF; +} + int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, unsigned long data, unsigned long size) { @@ -178,8 +189,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) { - if (0 == dma->nr_pages) - BUG(); + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + BUG_ON(0 == dma->nr_pages); if (dma->pages) { dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, @@ -211,8 +222,8 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma) { - if (!dma->sglen) - BUG(); + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + BUG_ON(!dma->sglen); if (!dma->bus_addr) pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction); @@ -221,6 +232,7 @@ int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma) int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma) { + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); if (!dma->sglen) return 0; @@ -234,8 +246,8 @@ int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma) int videobuf_dma_free(struct videobuf_dmabuf *dma) { - if (dma->sglen) - BUG(); + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + BUG_ON(dma->sglen); if (dma->pages) { int i; @@ -264,7 +276,9 @@ void* videobuf_alloc(unsigned int size) vb = kmalloc(size,GFP_KERNEL); if (NULL != vb) { memset(vb,0,size); + videobuf_dma_init(&vb->dma); init_waitqueue_head(&vb->done); + vb->magic = MAGIC_BUFFER; } return vb; } @@ -274,6 +288,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) int retval = 0; DECLARE_WAITQUEUE(wait, current); + MAGIC_CHECK(vb->magic,MAGIC_BUFFER); add_wait_queue(&vb->done, &wait); while (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED) { if (non_blocking) { @@ -302,6 +317,7 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, int err,pages; dma_addr_t bus; + MAGIC_CHECK(vb->magic,MAGIC_BUFFER); switch (vb->memory) { case V4L2_MEMORY_MMAP: case V4L2_MEMORY_USERPTR: @@ -453,6 +469,8 @@ void videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb, enum v4l2_buf_type type) { + MAGIC_CHECK(vb->magic,MAGIC_BUFFER); + b->index = vb->i; b->type = type; @@ -491,6 +509,11 @@ videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb, break; } + if (vb->input != UNSET) { + b->flags |= V4L2_BUF_FLAG_INPUT; + b->input = vb->input; + } + b->field = vb->field; b->timestamp = vb->ts; b->bytesused = vb->size; @@ -513,6 +536,11 @@ videobuf_reqbufs(struct file *file, struct videobuf_queue *q, req->memory != V4L2_MEMORY_OVERLAY) return -EINVAL; + if (q->streaming) + return -EBUSY; + if (!list_empty(&q->stream)) + return -EBUSY; + down(&q->lock); count = req->count; if (count > VIDEO_MAX_FRAME) @@ -568,12 +596,21 @@ videobuf_qbuf(struct file *file, struct videobuf_queue *q, buf = q->bufs[b->index]; if (NULL == buf) goto done; + MAGIC_CHECK(buf->magic,MAGIC_BUFFER); if (buf->memory != b->memory) goto done; if (buf->state == STATE_QUEUED || buf->state == STATE_ACTIVE) goto done; + if (b->flags & V4L2_BUF_FLAG_INPUT) { + if (b->input >= q->inputs) + goto done; + buf->input = b->input; + } else { + buf->input = UNSET; + } + switch (b->memory) { case V4L2_MEMORY_MMAP: if (0 == buf->baddr) @@ -582,6 +619,8 @@ videobuf_qbuf(struct file *file, struct videobuf_queue *q, case V4L2_MEMORY_USERPTR: if (b->length < buf->bsize) goto done; + if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr) + q->ops->buf_release(file,buf); buf->baddr = b->m.userptr; break; case V4L2_MEMORY_OVERLAY: @@ -1075,6 +1114,7 @@ int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, for (i = 0; i < bcount; i++) { q->bufs[i] = videobuf_alloc(q->msize); q->bufs[i]->i = i; + q->bufs[i]->input = UNSET; q->bufs[i]->memory = memory; q->bufs[i]->bsize = bsize; switch (memory) { @@ -1085,7 +1125,7 @@ int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, case V4L2_MEMORY_OVERLAY: /* nothing */ break; - }; + } } dprintk(1,"mmap setup: %d buffers, %d bytes each\n", bcount,bsize); @@ -1192,6 +1232,7 @@ int videobuf_mmap_mapper(struct vm_area_struct *vma, EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg); +EXPORT_SYMBOL_GPL(videobuf_dma_init); EXPORT_SYMBOL_GPL(videobuf_dma_init_user); EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index cc031afdd834..a792476b0912 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -83,10 +83,10 @@ #include <linux/pci.h> #include <linux/miscdevice.h> #include <linux/smp_lock.h> +#include <linux/compat.h> #include <asm/io.h> #include <asm/uaccess.h> -#include <asm/compat.h> #include <linux/kdev_t.h> /* needed for access to Scsi_Host struct */ #include <linux/blkdev.h> diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index d9225b32e553..bddc2d99aa65 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -196,6 +196,7 @@ struct e1000_adapter { uint32_t part_num; uint32_t wol; uint32_t smartspeed; + uint32_t en_mng_pt; uint16_t link_speed; uint16_t link_duplex; spinlock_t stats_lock; diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index a4d68616ccc9..41c05e5c37cb 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -265,6 +265,17 @@ e1000_set_mac_type(struct e1000_hw *hw) return -E1000_ERR_MAC_TYPE; } + switch(hw->mac_type) { + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + hw->asf_firmware_present = TRUE; + break; + default: + break; + } + return E1000_SUCCESS; } @@ -5189,3 +5200,27 @@ e1000_set_vco_speed(struct e1000_hw *hw) return E1000_SUCCESS; } +/****************************************************************************** + * Verifies the hardware needs to allow ARPs to be processed by the host + * + * hw - Struct containing variables accessed by shared code + * + * returns: - TRUE/FALSE + * + *****************************************************************************/ +uint32_t +e1000_enable_mng_pass_thru(struct e1000_hw *hw) +{ + uint32_t manc; + + if (hw->asf_firmware_present) { + manc = E1000_READ_REG(hw, MANC); + + if (!(manc & E1000_MANC_RCV_TCO_EN) || + !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) + return FALSE; + if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) + return TRUE; + } + return FALSE; +} diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index da964359de62..c9ee93a0d2de 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -307,6 +307,7 @@ int32_t e1000_led_off(struct e1000_hw *hw); /* Adaptive IFS Functions */ /* Everything else */ +uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw); void e1000_clear_hw_cntrs(struct e1000_hw *hw); void e1000_reset_adaptive(struct e1000_hw *hw); void e1000_update_adaptive(struct e1000_hw *hw); @@ -983,6 +984,7 @@ struct e1000_hw { e1000_ms_type master_slave; e1000_ms_type original_master_slave; e1000_ffe_config ffe_config_state; + uint32_t asf_firmware_present; unsigned long io_base; uint32_t phy_id; uint32_t phy_revision; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b5752685243a..4b9b775677c5 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -299,7 +299,7 @@ e1000_down(struct e1000_adapter *adapter) void e1000_reset(struct e1000_adapter *adapter) { - uint32_t pba; + uint32_t pba, manc; /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. */ @@ -341,6 +341,12 @@ e1000_reset(struct e1000_adapter *adapter) e1000_reset_adaptive(&adapter->hw); e1000_phy_get_info(&adapter->hw, &adapter->phy_info); + + if(adapter->en_mng_pt) { + manc = E1000_READ_REG(&adapter->hw, MANC); + manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST); + E1000_WRITE_REG(&adapter->hw, MANC, manc); + } } /** @@ -483,6 +489,8 @@ e1000_probe(struct pci_dev *pdev, if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw); + /* before reading the EEPROM, reset the controller to * put the device in a known good starting state */ diff --git a/drivers/net/eql.c b/drivers/net/eql.c index 9ab72741d6f5..80ed8b5a6647 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -499,6 +499,8 @@ static int eql_g_slave_cfg(struct net_device *dev, slave_config_t __user *scp) return -ENODEV; ret = -EINVAL; + if (!slave_dev) + return ret; spin_lock_bh(&eql->queue.lock); if (eql_is_slave(slave_dev)) { @@ -534,6 +536,8 @@ static int eql_s_slave_cfg(struct net_device *dev, slave_config_t __user *scp) return -ENODEV; ret = -EINVAL; + if (!slave_dev) + return ret; eql = dev->priv; spin_lock_bh(&eql->queue.lock); diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index f1ec806659eb..3142c00daf12 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -207,10 +207,8 @@ KERN_INFO " Further modifications by Keith Underwood <keithu@parl.clemson.edu> /* Condensed bus+endian portability operations. */ #if ADDRLEN == 64 #define cpu_to_leXX(addr) cpu_to_le64(addr) -#define desc_to_virt(addr) bus_to_virt(le64_to_cpu(addr)) #else #define cpu_to_leXX(addr) cpu_to_le32(addr) -#define desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) #endif @@ -1502,7 +1500,7 @@ static int hamachi_rx(struct net_device *dev) desc->addr, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); - buf_addr = desc_to_virt(desc->addr); + buf_addr = (u8 *) hmp->rx_skbuff[entry]->tail; frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12]))); if (hamachi_debug > 4) printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n", diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 103baaff18a7..1fe769ad6795 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -588,6 +588,8 @@ static int hdlcdrv_close(struct net_device *dev) return -EINVAL; s = (struct hdlcdrv_state *)dev->priv; + netif_stop_queue(dev); + if (s->ops && s->ops->close) i = s->ops->close(dev); if (s->skb) diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 1885bfe3c959..53dc879651e4 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -56,6 +56,7 @@ #include <linux/ip.h> #include <linux/tcp.h> +static struct net_device_stats *loopback_stats; #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) @@ -123,7 +124,6 @@ static void emulate_large_send_offload(struct sk_buff *skb) */ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = dev->priv; skb_orphan(skb); @@ -142,11 +142,12 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) } dev->last_rx = jiffies; - if (likely(stats)) { - stats->rx_bytes+=skb->len; - stats->tx_bytes+=skb->len; - stats->rx_packets++; - stats->tx_packets++; + if (likely(loopback_stats)) { + get_cpu_ptr(loopback_stats)->rx_bytes += skb->len; + get_cpu_ptr(loopback_stats)->tx_bytes += skb->len; + get_cpu_ptr(loopback_stats)->rx_packets++; + get_cpu_ptr(loopback_stats)->tx_packets++; + put_cpu_ptr(loopback_stats); } netif_rx(skb); @@ -156,7 +157,28 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) static struct net_device_stats *get_stats(struct net_device *dev) { - return (struct net_device_stats *)dev->priv; + struct net_device_stats *stats = dev->priv; + int i; + + if (!stats) { + return NULL; + } + + memset(stats, 0, sizeof(struct net_device_stats)); + if (!loopback_stats) { + return stats; + } + + for (i=0; i < NR_CPUS; i++) { + if (!cpu_possible(i)) + continue; + stats->rx_bytes += per_cpu_ptr(loopback_stats, i)->rx_bytes; + stats->tx_bytes += per_cpu_ptr(loopback_stats, i)->tx_bytes; + stats->rx_packets += per_cpu_ptr(loopback_stats, i)->rx_packets; + stats->tx_packets += per_cpu_ptr(loopback_stats, i)->tx_packets; + } + + return stats; } struct net_device loopback_dev = { @@ -173,7 +195,8 @@ struct net_device loopback_dev = { .rebuild_header = eth_rebuild_header, .flags = IFF_LOOPBACK, .features = NETIF_F_SG|NETIF_F_FRAGLIST - |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA, + |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA + |NETIF_F_LLTX, }; /* Setup and register the of the LOOPBACK device. */ @@ -188,6 +211,8 @@ int __init loopback_init(void) loopback_dev.priv = stats; loopback_dev.get_stats = &get_stats; } + + loopback_stats = alloc_percpu(struct net_device_stats); return register_netdev(&loopback_dev); }; diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index f597572be9aa..e67bf67f122f 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -612,7 +612,6 @@ static struct net_device *dev_macsonic; MODULE_PARM(sonic_debug, "i"); MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)"); -MODULE_LICENSE("GPL"); int init_module(void) diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index bdf90d4e602f..ed687ec42b28 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -22,8 +22,8 @@ *************************************************************************/ #define DRV_NAME "pcnet32" -#define DRV_VERSION "1.30c" -#define DRV_RELDATE "05.25.2004" +#define DRV_VERSION "1.30f" +#define DRV_RELDATE "06.16.2004" #define PFX DRV_NAME ": " static const char *version = @@ -245,6 +245,11 @@ static int full_duplex[MAX_UNITS]; * v1.30b 24 May 2004 Don Fry fix bogus tx carrier errors with 79c973, * assisted by Bruce Penrod <bmpenrod@endruntechnologies.com>. * v1.30c 25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart. + * v1.30d 01 Jun 2004 Don Fry discard oversize rx packets. + * v1.30e 11 Jun 2004 Don Fry recover after fifo error and rx hang. + * v1.30f 16 Jun 2004 Don Fry cleanup IRQ to allow 0 and 1 for PCI, + * expanding on suggestions from Ralf Baechle <ralf@linux-mips.org>, + * and Brian Murphy <brian@murphy.dk>. */ @@ -360,7 +365,7 @@ struct pcnet32_private { static void pcnet32_probe_vlbus(void); static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); -static int pcnet32_probe1(unsigned long, unsigned int, int, struct pci_dev *); +static int pcnet32_probe1(unsigned long, int, struct pci_dev *); static int pcnet32_open(struct net_device *); static int pcnet32_init_ring(struct net_device *); static int pcnet32_start_xmit(struct sk_buff *, struct net_device *); @@ -958,7 +963,7 @@ pcnet32_probe_vlbus(void) if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) { /* check if there is really a pcnet chip on that ioaddr */ if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) { - pcnet32_probe1(ioaddr, 0, 0, NULL); + pcnet32_probe1(ioaddr, 0, NULL); } else { release_region(ioaddr, PCNET32_TOTAL_SIZE); } @@ -999,7 +1004,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) return -EBUSY; } - return pcnet32_probe1(ioaddr, pdev->irq, 1, pdev); + return pcnet32_probe1(ioaddr, 1, pdev); } @@ -1008,8 +1013,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) * pdev will be NULL when called from pcnet32_probe_vlbus. */ static int __devinit -pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, - struct pci_dev *pdev) +pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) { struct pcnet32_private *lp; dma_addr_t lp_dma_addr; @@ -1270,11 +1274,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16); - if (irq_line) { - dev->irq = irq_line; - } - - if (dev->irq >= 2) { + if (pdev) { /* use the IRQ provided by PCI */ + dev->irq = pdev->irq; if (pcnet32_debug & NETIF_MSG_PROBE) printk(" assigned IRQ %d.\n", dev->irq); } else { @@ -1362,8 +1363,7 @@ pcnet32_open(struct net_device *dev) int rc; unsigned long flags; - if (dev->irq == 0 || - request_irq(dev->irq, &pcnet32_interrupt, + if (request_irq(dev->irq, &pcnet32_interrupt, lp->shared_irq ? SA_SHIRQ : 0, dev->name, (void *)dev)) { return -EAGAIN; } @@ -1531,13 +1531,15 @@ pcnet32_purge_tx_ring(struct net_device *dev) int i; for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ if (lp->tx_skbuff[i]) { pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); dev_kfree_skb_any(lp->tx_skbuff[i]); - lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; } + lp->tx_skbuff[i] = NULL; + lp->tx_dma_addr[i] = 0; } } @@ -1566,21 +1568,23 @@ pcnet32_init_ring(struct net_device *dev) skb_reserve (rx_skbuff, 2); } + rmb(); if (lp->rx_dma_addr[i] == 0) lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]); lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ); + wmb(); /* Make sure owner changes after all others are visible */ lp->rx_ring[i].status = le16_to_cpu(0x8000); } /* The Tx buffer address is filled in as needed, but we do need to clear * the upper ownership bit. */ for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ lp->tx_ring[i].base = 0; - lp->tx_ring[i].status = 0; lp->tx_dma_addr[i] = 0; } - wmb(); /* Make sure all changes are visible */ lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); for (i = 0; i < 6; i++) @@ -1589,9 +1593,14 @@ pcnet32_init_ring(struct net_device *dev) offsetof(struct pcnet32_private, rx_ring)); lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)); + wmb(); /* Make sure all changes are visible */ return 0; } +/* the pcnet32 has been issued a stop or reset. Wait for the stop bit + * then flush the pending transmit operations, re-initialize the ring, + * and tell the chip to initialize. + */ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) { @@ -1599,6 +1608,15 @@ pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) unsigned long ioaddr = dev->base_addr; int i; + /* wait for stop */ + for (i=0; i<100; i++) + if (lp->a.read_csr(ioaddr, 0) & 0x0004) + break; + + if (i >= 100 && netif_msg_drv(lp)) + printk(KERN_ERR "%s: pcnet32_restart timed out waiting for stop.\n", + dev->name); + pcnet32_purge_tx_ring(dev); if (pcnet32_init_ring(dev)) return; @@ -1857,15 +1875,16 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) } if (must_restart) { - /* stop the chip to clear the error condition, then restart */ - lp->a.write_csr (ioaddr, 0, 0x0004); + /* reset the chip to clear the error condition, then restart */ + lp->a.reset(ioaddr); + lp->a.write_csr(ioaddr, 4, 0x0915); pcnet32_restart(dev, 0x0002); netif_wake_queue(dev); } } - /* Clear any other interrupt, and set interrupt enable. */ - lp->a.write_csr (ioaddr, 0, 0x7940); + /* Set interrupt enable. */ + lp->a.write_csr (ioaddr, 0, 0x0040); lp->a.write_rap (ioaddr,rap); if (netif_msg_intr(lp)) @@ -1907,7 +1926,13 @@ pcnet32_rx(struct net_device *dev) short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4; struct sk_buff *skb; - if (pkt_len < 60) { + /* Discard oversize frames. */ + if (unlikely(pkt_len > PKT_BUF_SZ - 2)) { + if (netif_msg_drv(lp)) + printk(KERN_ERR "%s: Impossible packet size %d!\n", + dev->name, pkt_len); + lp->stats.rx_errors++; + } else if (pkt_len < 60) { if (netif_msg_rx_err(lp)) printk(KERN_ERR "%s: Runt packet!\n", dev->name); lp->stats.rx_errors++; diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 0e1e057a84bd..b6157c89ba65 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -29,7 +29,7 @@ * PPP driver, written by Michael Callahan and Al Longyear, and * subsequently hacked by Paul Mackerras. * - * ==FILEVERSION 20020125== + * ==FILEVERSION 20040616== */ #include <linux/module.h> @@ -65,7 +65,9 @@ struct syncppp { struct sk_buff *tpkt; unsigned long last_xmit; - struct sk_buff *rpkt; + struct sk_buff_head rqueue; + + struct tasklet_struct tsk; atomic_t refcnt; struct semaphore dead_sem; @@ -88,6 +90,7 @@ static struct sk_buff* ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *); static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb); static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg); +static void ppp_sync_process(unsigned long arg); static int ppp_sync_push(struct syncppp *ap); static void ppp_sync_flush_output(struct syncppp *ap); static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf, @@ -217,6 +220,9 @@ ppp_sync_open(struct tty_struct *tty) ap->xaccm[3] = 0x60000000U; ap->raccm = ~0U; + skb_queue_head_init(&ap->rqueue); + tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap); + atomic_set(&ap->refcnt, 1); init_MUTEX_LOCKED(&ap->dead_sem); @@ -267,10 +273,10 @@ ppp_sync_close(struct tty_struct *tty) */ if (!atomic_dec_and_test(&ap->refcnt)) down(&ap->dead_sem); + tasklet_kill(&ap->tsk); ppp_unregister_channel(&ap->chan); - if (ap->rpkt != 0) - kfree_skb(ap->rpkt); + skb_queue_purge(&ap->rqueue); if (ap->tpkt != 0) kfree_skb(ap->tpkt); kfree(ap); @@ -369,17 +375,24 @@ ppp_sync_room(struct tty_struct *tty) return 65535; } +/* + * This can now be called from hard interrupt level as well + * as soft interrupt level or mainline. + */ static void ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, - char *flags, int count) + char *cflags, int count) { struct syncppp *ap = sp_get(tty); + unsigned long flags; if (ap == 0) return; - spin_lock_bh(&ap->recv_lock); - ppp_sync_input(ap, buf, flags, count); - spin_unlock_bh(&ap->recv_lock); + spin_lock_irqsave(&ap->recv_lock, flags); + ppp_sync_input(ap, buf, cflags, count); + spin_unlock_irqrestore(&ap->recv_lock, flags); + if (skb_queue_len(&ap->rqueue)) + tasklet_schedule(&ap->tsk); sp_put(ap); if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && tty->driver->unthrottle) @@ -394,8 +407,8 @@ ppp_sync_wakeup(struct tty_struct *tty) clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); if (ap == 0) return; - if (ppp_sync_push(ap)) - ppp_output_wakeup(&ap->chan); + set_bit(XMIT_WAKEUP, &ap->xmit_flags); + tasklet_schedule(&ap->tsk); sp_put(ap); } @@ -449,9 +462,9 @@ ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) if (get_user(val, (int *) arg)) break; ap->flags = val & ~SC_RCV_BITS; - spin_lock_bh(&ap->recv_lock); + spin_lock_irq(&ap->recv_lock); ap->rbits = val & SC_RCV_BITS; - spin_unlock_bh(&ap->recv_lock); + spin_unlock_irq(&ap->recv_lock); err = 0; break; @@ -512,6 +525,32 @@ ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) } /* + * This is called at softirq level to deliver received packets + * to the ppp_generic code, and to tell the ppp_generic code + * if we can accept more output now. + */ +static void ppp_sync_process(unsigned long arg) +{ + struct syncppp *ap = (struct syncppp *) arg; + struct sk_buff *skb; + + /* process received packets */ + while ((skb = skb_dequeue(&ap->rqueue)) != NULL) { + if (skb->len == 0) { + /* zero length buffers indicate error */ + ppp_input_error(&ap->chan, 0); + kfree_skb(skb); + } + else + ppp_input(&ap->chan, skb); + } + + /* try to push more stuff out */ + if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_sync_push(ap)) + ppp_output_wakeup(&ap->chan); +} + +/* * Procedures for encapsulation and framing. */ @@ -600,7 +639,6 @@ ppp_sync_push(struct syncppp *ap) struct tty_struct *tty = ap->tty; int tty_stuffed = 0; - set_bit(XMIT_WAKEUP, &ap->xmit_flags); if (!spin_trylock_bh(&ap->xmit_lock)) return 0; for (;;) { @@ -667,15 +705,44 @@ ppp_sync_flush_output(struct syncppp *ap) * Receive-side routines. */ -static inline void -process_input_packet(struct syncppp *ap) +/* called when the tty driver has data for us. + * + * Data is frame oriented: each call to ppp_sync_input is considered + * a whole frame. If the 1st flag byte is non-zero then the whole + * frame is considered to be in error and is tossed. + */ +static void +ppp_sync_input(struct syncppp *ap, const unsigned char *buf, + char *flags, int count) { struct sk_buff *skb; unsigned char *p; - int code = 0; - skb = ap->rpkt; - ap->rpkt = 0; + if (count == 0) + return; + + if (ap->flags & SC_LOG_INPKT) + ppp_print_buffer ("receive buffer", buf, count); + + /* stuff the chars in the skb */ + if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) { + printk(KERN_ERR "PPPsync: no memory (input pkt)\n"); + goto err; + } + /* Try to get the payload 4-byte aligned */ + if (buf[0] != PPP_ALLSTATIONS) + skb_reserve(skb, 2 + (buf[0] & 1)); + + if (flags != 0 && *flags) { + /* error flag set, ignore frame */ + goto err; + } else if (count > skb_tailroom(skb)) { + /* packet overflowed MRU */ + goto err; + } + + p = skb_put(skb, count); + memcpy(p, buf, count); /* strip address/control field if present */ p = skb->data; @@ -693,59 +760,15 @@ process_input_packet(struct syncppp *ap) } else if (skb->len < 2) goto err; - /* pass to generic layer */ - ppp_input(&ap->chan, skb); + /* queue the frame to be processed */ + skb_queue_tail(&ap->rqueue, skb); return; - err: - kfree_skb(skb); - ppp_input_error(&ap->chan, code); -} - -/* called when the tty driver has data for us. - * - * Data is frame oriented: each call to ppp_sync_input is considered - * a whole frame. If the 1st flag byte is non-zero then the whole - * frame is considered to be in error and is tossed. - */ -static void -ppp_sync_input(struct syncppp *ap, const unsigned char *buf, - char *flags, int count) -{ - struct sk_buff *skb; - unsigned char *sp; - - if (count == 0) - return; - - /* if flag set, then error, ignore frame */ - if (flags != 0 && *flags) { - ppp_input_error(&ap->chan, *flags); - return; - } - - if (ap->flags & SC_LOG_INPKT) - ppp_print_buffer ("receive buffer", buf, count); - - /* stuff the chars in the skb */ - if ((skb = ap->rpkt) == 0) { - if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) { - printk(KERN_ERR "PPPsync: no memory (input pkt)\n"); - ppp_input_error(&ap->chan, 0); - return; - } - /* Try to get the payload 4-byte aligned */ - if (buf[0] != PPP_ALLSTATIONS) - skb_reserve(skb, 2 + (buf[0] & 1)); - ap->rpkt = skb; - } - if (count > skb_tailroom(skb)) { - /* packet overflowed MRU */ - ppp_input_error(&ap->chan, 1); - } else { - sp = skb_put(skb, count); - memcpy(sp, buf, count); - process_input_packet(ap); +err: + /* queue zero length packet as error indication */ + if (skb || (skb = dev_alloc_skb(0))) { + skb_trim(skb, 0); + skb_queue_tail(&ap->rqueue, skb); } } diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 7914167acc8f..39b09cd6ba13 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2900,15 +2900,15 @@ static void __exit sbmac_cleanup_module(void) { struct net_device *dev; - sbmac_port_t port; int idx; for (idx = 0; idx < MAX_UNITS; idx++) { + struct sbmac_softc *sc; dev = dev_sbmac[idx]; if (!dev) continue; - struct sbmac_softc *sc = netdev_priv(dev); + sc = netdev_priv(dev); unregister_netdev(dev); sbmac_uninitctx(sc); free_netdev(dev); diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 3493b7974d1f..b71f45f5cb58 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -64,13 +64,13 @@ static char *sgiseeqstr = "SGI Seeq8003"; #define DEBUG struct sgiseeq_rx_desc { - struct hpc_dma_desc rdma; - signed int buf_vaddr; + volatile struct hpc_dma_desc rdma; + volatile signed int buf_vaddr; }; struct sgiseeq_tx_desc { - struct hpc_dma_desc tdma; - signed int buf_vaddr; + volatile struct hpc_dma_desc tdma; + volatile signed int buf_vaddr; }; /* @@ -79,17 +79,17 @@ struct sgiseeq_tx_desc { * some care. */ struct sgiseeq_init_block { /* Note the name ;-) */ - /* Ptrs to the descriptors in KSEG1 uncached space. */ - struct sgiseeq_rx_desc *rx_desc; - struct sgiseeq_tx_desc *tx_desc; - unsigned int _padding[30]; /* Pad out to largest cache line size. */ - struct sgiseeq_rx_desc rxvector[SEEQ_RX_BUFFERS]; struct sgiseeq_tx_desc txvector[SEEQ_TX_BUFFERS]; }; struct sgiseeq_private { - volatile struct sgiseeq_init_block srings; + struct sgiseeq_init_block *srings; + + /* Ptrs to the descriptors in uncached space. */ + struct sgiseeq_rx_desc *rx_desc; + struct sgiseeq_tx_desc *tx_desc; + char *name; struct hpc3_ethregs *hregs; struct sgiseeq_regs *sregs; @@ -152,8 +152,7 @@ static inline void seeq_load_eaddr(struct net_device *dev, static int seeq_init_ring(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; - volatile struct sgiseeq_init_block *ib = &sp->srings; + struct sgiseeq_private *sp = netdev_priv(dev); int i; netif_stop_queue(dev); @@ -170,32 +169,32 @@ static int seeq_init_ring(struct net_device *dev) /* Setup tx ring. */ for(i = 0; i < SEEQ_TX_BUFFERS; i++) { - if (!ib->tx_desc[i].tdma.pbuf) { + if (!sp->tx_desc[i].tdma.pbuf) { unsigned long buffer; buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL); if (!buffer) return -ENOMEM; - ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer); - ib->tx_desc[i].tdma.pbuf = CPHYSADDR(buffer); + sp->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer); + sp->tx_desc[i].tdma.pbuf = CPHYSADDR(buffer); } - ib->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT; + sp->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT; } /* And now the rx ring. */ for (i = 0; i < SEEQ_RX_BUFFERS; i++) { - if (!ib->rx_desc[i].rdma.pbuf) { + if (!sp->rx_desc[i].rdma.pbuf) { unsigned long buffer; buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL); if (!buffer) return -ENOMEM; - ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer); - ib->rx_desc[i].rdma.pbuf = CPHYSADDR(buffer); + sp->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer); + sp->rx_desc[i].rdma.pbuf = CPHYSADDR(buffer); } - ib->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT; + sp->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT; } - ib->rx_desc[i - 1].rdma.cntinfo |= HPCDMA_EOR; + sp->rx_desc[i - 1].rdma.cntinfo |= HPCDMA_EOR; return 0; } @@ -206,8 +205,8 @@ static struct net_device *gdev; void sgiseeq_dump_rings(void) { static int once; - struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc; - struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc; + struct sgiseeq_rx_desc *r = gpriv->rx_desc; + struct sgiseeq_tx_desc *t = gpriv->tx_desc; struct hpc3_ethregs *hregs = gpriv->hregs; int i; @@ -268,8 +267,8 @@ static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp, hregs->rx_dconfig |= RDMACFG_INIT; - hregs->rx_ndptr = CPHYSADDR(sp->srings.rx_desc); - hregs->tx_ndptr = CPHYSADDR(sp->srings.tx_desc); + hregs->rx_ndptr = CPHYSADDR(sp->rx_desc); + hregs->tx_ndptr = CPHYSADDR(sp->tx_desc); seeq_go(sp, hregs, sregs); return 0; @@ -294,14 +293,14 @@ static inline void rx_maybe_restart(struct sgiseeq_private *sp, struct sgiseeq_regs *sregs) { if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) { - hregs->rx_ndptr = CPHYSADDR(sp->srings.rx_desc + sp->rx_new); + hregs->rx_ndptr = CPHYSADDR(sp->rx_desc + sp->rx_new); seeq_go(sp, hregs, sregs); } } -#define for_each_rx(rd, sp) for((rd) = &(sp)->srings.rx_desc[(sp)->rx_new]; \ +#define for_each_rx(rd, sp) for((rd) = &(sp)->rx_desc[(sp)->rx_new]; \ !((rd)->rdma.cntinfo & HPCDMA_OWN); \ - (rd) = &(sp)->srings.rx_desc[(sp)->rx_new]) + (rd) = &(sp)->rx_desc[(sp)->rx_new]) static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp, struct hpc3_ethregs *hregs, @@ -349,8 +348,8 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp rd->rdma.cntinfo = RCNTINFO_INIT; sp->rx_new = NEXT_RX(sp->rx_new); } - sp->srings.rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR); - sp->srings.rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR; + sp->rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR); + sp->rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR; rx_maybe_restart(sp, hregs, sregs); } @@ -403,7 +402,7 @@ static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp /* Ack 'em... */ for (j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) { - td = &sp->srings.tx_desc[j]; + td = &sp->tx_desc[j]; if (!(td->tdma.cntinfo & (HPCDMA_XIU))) break; @@ -424,7 +423,7 @@ static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct hpc3_ethregs *hregs = sp->hregs; struct sgiseeq_regs *sregs = sp->sregs; @@ -450,21 +449,33 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs static int sgiseeq_open(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct sgiseeq_regs *sregs = sp->sregs; + unsigned int irq = dev->irq; + int err; - int err = init_seeq(dev, sp, sregs); + if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { + printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq); + err = -EAGAIN; + } + + err = init_seeq(dev, sp, sregs); if (err) - return err; + goto out_free_irq; netif_start_queue(dev); return 0; + +out_free_irq: + free_irq(irq, dev); + + return err; } static int sgiseeq_close(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct sgiseeq_regs *sregs = sp->sregs; netif_stop_queue(dev); @@ -477,7 +488,7 @@ static int sgiseeq_close(struct net_device *dev) static inline int sgiseeq_reset(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct sgiseeq_regs *sregs = sp->sregs; int err; @@ -499,7 +510,7 @@ void sgiseeq_my_reset(void) static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct hpc3_ethregs *hregs = sp->hregs; unsigned long flags; struct sgiseeq_tx_desc *td; @@ -512,7 +523,7 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; sp->stats.tx_bytes += len; entry = sp->tx_new; - td = &sp->srings.tx_desc[entry]; + td = &sp->tx_desc[entry]; /* Create entry. There are so many races with adding a new * descriptor to the chain: @@ -535,14 +546,14 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) if (sp->tx_old != sp->tx_new) { struct sgiseeq_tx_desc *backend; - backend = &sp->srings.tx_desc[PREV_TX(sp->tx_new)]; + backend = &sp->tx_desc[PREV_TX(sp->tx_new)]; backend->tdma.cntinfo &= ~HPCDMA_EOX; } sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */ /* Maybe kick the HPC back into motion. */ if (!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) - kick_tx(&sp->srings.tx_desc[sp->tx_old], hregs); + kick_tx(&sp->tx_desc[sp->tx_old], hregs); dev->trans_start = jiffies; dev_kfree_skb(skb); @@ -565,7 +576,7 @@ static void timeout(struct net_device *dev) static struct net_device_stats *sgiseeq_get_stats(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); return &sp->stats; } @@ -601,31 +612,29 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs) #define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf)) -int sgiseeq_init(struct hpc3_regs* regs, int irq) +static int sgiseeq_init(struct hpc3_regs* regs, int irq) { - struct net_device *dev; + struct sgiseeq_init_block *sr; struct sgiseeq_private *sp; + struct net_device *dev; int err, i; - dev = alloc_etherdev(0); + dev = alloc_etherdev(sizeof (struct sgiseeq_private)); if (!dev) { printk(KERN_ERR "Sgiseeq: Etherdev alloc failed, aborting.\n"); err = -ENOMEM; goto err_out; } + sp = netdev_priv(dev); + /* Make private data page aligned */ - sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL); - if (!sp) { + sr = (struct sgiseeq_init_block *) get_zeroed_page(GFP_KERNEL); + if (!sr) { printk(KERN_ERR "Sgiseeq: Page alloc failed, aborting.\n"); err = -ENOMEM; goto err_out_free_dev; } - - if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { - printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq); - err = -EAGAIN; - goto err_out_free_page; - } + sp->srings = sr; #define EADDR_NVOFS 250 for (i = 0; i < 3; i++) { @@ -643,18 +652,18 @@ int sgiseeq_init(struct hpc3_regs* regs, int irq) sp->hregs = &hpc3c0->ethregs; sp->name = sgiseeqstr; - sp->srings.rx_desc = (struct sgiseeq_rx_desc *) - KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0])); - dma_cache_wback_inv((unsigned long)&sp->srings.rxvector, - sizeof(sp->srings.rxvector)); - sp->srings.tx_desc = (struct sgiseeq_tx_desc *) - KSEG1ADDR(ALIGNED(&sp->srings.txvector[0])); - dma_cache_wback_inv((unsigned long)&sp->srings.txvector, - sizeof(sp->srings.txvector)); + sp->rx_desc = (struct sgiseeq_rx_desc *) + KSEG1ADDR(ALIGNED(&sp->srings->rxvector[0])); + dma_cache_wback_inv((unsigned long)&sp->srings->rxvector, + sizeof(sp->srings->rxvector)); + sp->tx_desc = (struct sgiseeq_tx_desc *) + KSEG1ADDR(ALIGNED(&sp->srings->txvector[0])); + dma_cache_wback_inv((unsigned long)&sp->srings->txvector, + sizeof(sp->srings->txvector)); /* A couple calculations now, saves many cycles later. */ - setup_rx_ring(sp->srings.rx_desc, SEEQ_RX_BUFFERS); - setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS); + setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS); + setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS); /* Reset the chip. */ hpc3_eth_reset(sp->hregs); @@ -673,14 +682,12 @@ int sgiseeq_init(struct hpc3_regs* regs, int irq) dev->get_stats = sgiseeq_get_stats; dev->set_multicast_list = sgiseeq_set_multicast; dev->irq = irq; - dev->dma = 0; - dev->priv = sp; if (register_netdev(dev)) { printk(KERN_ERR "Sgiseeq: Cannot register net device, " "aborting.\n"); err = -ENODEV; - goto err_out_free_irq; + goto err_out_free_page; } printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name); @@ -692,8 +699,6 @@ int sgiseeq_init(struct hpc3_regs* regs, int irq) return 0; -err_out_free_irq: - free_irq(irq, dev); err_out_free_page: free_page((unsigned long) sp); err_out_free_dev: @@ -718,12 +723,12 @@ static void __exit sgiseeq_exit(void) int irq; for (dev = root_sgiseeq_dev; dev; dev = next) { - sp = (struct sgiseeq_private *) dev->priv; + sp = (struct sgiseeq_private *) netdev_priv(dev); next = sp->next_module; irq = dev->irq; unregister_netdev(dev); free_irq(irq, dev); - free_page((unsigned long) dev->priv); + free_page((unsigned long) sp); free_netdev(dev); } } diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h index e3e83ed0f246..dba3d2dd2f40 100644 --- a/drivers/net/sk98lin/h/skdrv2nd.h +++ b/drivers/net/sk98lin/h/skdrv2nd.h @@ -58,7 +58,8 @@ /* 3Com (0x10b7) */ \ if (pdev->vendor == 0x10b7) { \ /* Gigabit Ethernet Adapter (0x1700) */ \ - if ((pdev->device == 0x1700)) { \ + if ((pdev->device == 0x1700) || \ + (pdev->device == 0x80eb)) { \ result = SK_TRUE; \ } \ /* SysKonnect (0x1148) */ \ diff --git a/drivers/net/skfp/cfm.c b/drivers/net/skfp/cfm.c index 91eb36f3ec3a..4c8aaa762333 100644 --- a/drivers/net/skfp/cfm.c +++ b/drivers/net/skfp/cfm.c @@ -96,14 +96,13 @@ static const u_char cf_to_ptype[] = { /* * function declarations */ -static void cfm_fsm() ; +static void cfm_fsm(struct s_smc *smc, int cmd); /* init CFM state machine clear all CFM vars and flags */ -void cfm_init(smc) -struct s_smc *smc ; +void cfm_init(struct s_smc *smc) { smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ; smc->r.rm_join = 0 ; @@ -118,9 +117,7 @@ struct s_smc *smc ; #define THRU_ENABLED(smc) (smc->y[PA].pc_mode != PM_TREE && \ smc->y[PB].pc_mode != PM_TREE) /* Selection criteria for the ports */ -static void selection_criteria (smc,phy) -struct s_smc *smc ; -struct s_phy *phy ; +static void selection_criteria (struct s_smc *smc, struct s_phy *phy) { switch (phy->mib->fddiPORTMy_Type) { @@ -146,8 +143,7 @@ struct s_phy *phy ; } -void all_selection_criteria (smc) -struct s_smc *smc ; +void all_selection_criteria(struct s_smc *smc) { struct s_phy *phy ; int p ; @@ -158,9 +154,7 @@ struct s_smc *smc ; } } -static void cem_priv_state (smc, event) -struct s_smc *smc ; -int event ; +static void cem_priv_state(struct s_smc *smc, int event) /* State machine for private PORT states: used to optimize dual homing */ { int np; /* Number of the port */ @@ -216,9 +210,7 @@ int event ; process event until SM is stable */ -void cfm(smc,event) -struct s_smc *smc ; -int event ; +void cfm(struct s_smc *smc, int event) { int state ; /* remember last state */ int cond ; @@ -290,9 +282,7 @@ int event ; process CFM event */ /*ARGSUSED1*/ -static void cfm_fsm(smc,cmd) -struct s_smc *smc ; -int cmd ; +static void cfm_fsm(struct s_smc *smc, int cmd) { switch(smc->mib.fddiSMTCF_State) { case ACTIONS(SC0_ISOLATED) : @@ -550,8 +540,7 @@ int cmd ; * return : * PA or PB */ -int cfm_get_mac_input(smc) -struct s_smc *smc ; +int cfm_get_mac_input(struct s_smc *smc) { return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA) ; @@ -562,8 +551,7 @@ struct s_smc *smc ; * return : * PA or PB */ -int cfm_get_mac_output(smc) -struct s_smc *smc ; +int cfm_get_mac_output(struct s_smc *smc) { return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA) ; @@ -603,10 +591,7 @@ static char path_iso_s[] = { 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO, } ; -int cem_build_path(smc,to,path_index) -struct s_smc *smc ; -char *to ; -int path_index ; +int cem_build_path(struct s_smc *smc, char *to, int path_index) { char *path ; int len ; diff --git a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c index 0f473dd93256..052e841ba187 100644 --- a/drivers/net/skfp/drvfbi.c +++ b/drivers/net/skfp/drvfbi.c @@ -100,14 +100,13 @@ const struct s_oem_ids oem_ids[] = { #endif /* MULT_OEM */ /* Prototypes of external functions */ -extern void hwt_restart() ; #ifdef AIX extern int AIX_vpdReadByte() ; #endif /* Prototypes of local functions. */ -void smt_stop_watchdog() ; +void smt_stop_watchdog(struct s_smc *smc); #ifdef MCA static int read_card_id() ; @@ -129,8 +128,7 @@ extern int AIX_vpdReadByte() ; /* * FDDI card reset */ -static void card_start(smc) -struct s_smc *smc ; +static void card_start(struct s_smc *smc) { int i ; #ifdef PCI @@ -250,8 +248,7 @@ struct s_smc *smc ; GET_PAGE(0) ; /* necessary for BOOT */ } -void card_stop(smc) -struct s_smc *smc ; +void card_stop(struct s_smc *smc) { smt_stop_watchdog(smc) ; smc->hw.mac_ring_is_up = 0 ; /* ring down */ @@ -282,14 +279,11 @@ struct s_smc *smc ; } /*--------------------------- ISR handling ----------------------------------*/ -#ifndef PCI -void mac1_irq(smc,stu, stl) -struct s_smc *smc ; -u_short stu; -u_short stl; +void mac1_irq(struct s_smc *smc, u_short stu, u_short stl) { int restart_tx = 0 ; again: +#ifndef PCI #ifndef ISA /* * FORMAC+ bug modified the queue pointer if many read/write accesses happens!? @@ -344,14 +338,6 @@ again: } #else /* PCI */ -void mac1_irq(smc,stu, stl) -struct s_smc *smc ; -u_short stu; -u_short stl; -{ - int restart_tx = 0 ; -again: - /* * parity error: note encoding error is not possible in tag mode */ @@ -396,8 +382,7 @@ again: * interrupt source= plc1 * this function is called in nwfbisr.asm */ -void plc1_irq(smc) -struct s_smc *smc ; +void plc1_irq(struct s_smc *smc) { u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ; @@ -412,8 +397,7 @@ struct s_smc *smc ; * interrupt source= plc2 * this function is called in nwfbisr.asm */ -void plc2_irq(smc) -struct s_smc *smc ; +void plc2_irq(struct s_smc *smc) { u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ; @@ -428,8 +412,7 @@ struct s_smc *smc ; /* * interrupt source= timer */ -void timer_irq(smc) -struct s_smc *smc ; +void timer_irq(struct s_smc *smc) { hwt_restart(smc); smc->hw.t_stop = smc->hw.t_start; @@ -439,8 +422,7 @@ struct s_smc *smc ; /* * return S-port (PA or PB) */ -int pcm_get_s_port(smc) -struct s_smc *smc ; +int pcm_get_s_port(struct s_smc *smc) { SK_UNUSED(smc) ; return(PS) ; @@ -457,9 +439,7 @@ struct s_smc *smc ; #define STATION_LABEL_PMD_OFFSET 6 #define STATION_LABEL_PORT_OFFSET 7 -void read_address(smc,mac_addr) -struct s_smc *smc ; -u_char *mac_addr ; +void read_address(struct s_smc *smc, u_char *mac_addr) { char ConnectorType ; char PmdType ; @@ -528,9 +508,7 @@ u_char *mac_addr ; /* * FDDI card soft reset */ -void init_board(smc,mac_addr) -struct s_smc *smc ; -u_char *mac_addr ; +void init_board(struct s_smc *smc, u_char *mac_addr) { card_start(smc) ; read_address(smc,mac_addr) ; @@ -559,9 +537,7 @@ u_char *mac_addr ; /* * insert or deinsert optical bypass (called by ECM) */ -void sm_pm_bypass_req(smc,mode) -struct s_smc *smc ; -int mode; +void sm_pm_bypass_req(struct s_smc *smc, int mode) { #if (defined(ISA) || defined(EISA)) int csra_v ; @@ -614,8 +590,7 @@ int mode; /* * check if bypass connected */ -int sm_pm_bypass_present(smc) -struct s_smc *smc ; +int sm_pm_bypass_present(struct s_smc *smc) { #ifndef PCI return( (inpw(CSR_A) & CS_BYSTAT) ? FALSE : TRUE ) ; @@ -624,9 +599,7 @@ struct s_smc *smc ; #endif } -void plc_clear_irq(smc,p) -struct s_smc *smc ; -int p ; +void plc_clear_irq(struct s_smc *smc, int p) { SK_UNUSED(p) ; @@ -658,9 +631,7 @@ int p ; * LED_Y_OFF just switch yellow LED off * LED_Y_ON just switch yello LED on */ -void led_indication(smc,led_event) -struct s_smc *smc ; -int led_event; +void led_indication(struct s_smc *smc, int led_event) { /* use smc->hw.mac_ring_is_up == TRUE * as indication for Ring Operational @@ -754,10 +725,7 @@ int led_event; } -void pcm_state_change(smc,plc,p_state) -struct s_smc *smc; -int plc; -int p_state; +void pcm_state_change(struct s_smc *smc, int plc, int p_state) { /* * the current implementation of pcm_state_change() in the driver @@ -770,9 +738,7 @@ int p_state; } -void rmt_indication(smc,i) -struct s_smc *smc ; -int i; +void rmt_indication(struct s_smc *smc, int i) { /* Call a driver special function if defined */ DRV_RMT_INDICATION(smc,i) ; @@ -784,8 +750,7 @@ int i; /* * llc_recover_tx called by init_tx (fplus.c) */ -void llc_recover_tx(smc) -struct s_smc *smc ; +void llc_recover_tx(struct s_smc *smc) { #ifdef LOAD_GEN extern int load_gen_flag ; @@ -805,9 +770,7 @@ struct s_smc *smc ; /* * init DMA */ -void init_dma(smc,dma) -struct s_smc *smc; -int dma; +void init_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; @@ -828,9 +791,7 @@ int dma; /* * disable DMA */ -void dis_dma(smc,dma) -struct s_smc *smc ; -int dma; +void dis_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; @@ -854,9 +815,7 @@ static const int cntr[8] = { 0x001,0x003,0x005,0x007,0,0x0c6,0x0ca,0x0ce } ; static const int base[8] = { 0x000,0x002,0x004,0x006,0,0x0c4,0x0c8,0x0cc } ; static const int page[8] = { 0x087,0x083,0x081,0x082,0,0x08b,0x089,0x08a } ; -void init_dma(smc,dma) -struct s_smc *smc ; -int dma; +void init_dma(struct s_smc *smc, int dma) { /* * extended mode register @@ -885,9 +844,7 @@ int dma; } -void dis_dma(smc,dma) -struct s_smc *smc ; -int dma; +void dis_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; @@ -896,16 +853,13 @@ int dma; #endif /* EISA */ #ifdef MCA -void init_dma(smc,dma) -struct s_smc *smc; -int dma; +void init_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; SK_UNUSED(dma) ; } -void dis_dma(smc,dma) -struct s_smc *smc; -int dma; + +void dis_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; SK_UNUSED(dma) ; @@ -913,16 +867,13 @@ int dma; #endif #ifdef PCI -void init_dma(smc,dma) -struct s_smc *smc; -int dma; +void init_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; SK_UNUSED(dma) ; } -void dis_dma(smc,dma) -struct s_smc *smc; -int dma; + +void dis_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; SK_UNUSED(dma) ; @@ -930,10 +881,7 @@ int dma; #endif #ifdef MULT_OEM -static int is_equal_num(comp1,comp2,num) -char comp1[] ; -char comp2[] ; -int num ; +static int is_equal_num(char comp1[], char comp2[], int num) { int i ; @@ -954,8 +902,7 @@ int num ; * 2 data base empty * 3 no active entry */ -int set_oi_id_def(smc) -struct s_smc *smc ; +int set_oi_id_def(struct s_smc *smc) { int sel_id ; int i ; @@ -1029,9 +976,7 @@ struct s_smc *smc ; * ************************/ #define LONG_CARD_ID(lo, hi) ((((hi) & 0xff) << 8) | ((lo) & 0xff)) -int exist_board(smc,slot) -struct s_smc *smc ; -int slot ; +int exist_board(struct s_smc *smc, int slot) { #ifdef MULT_OEM SK_LOC_DECL(u_char,id[2]) ; @@ -1081,9 +1026,8 @@ int slot ; * number is specified, the function returns zero. * ************************/ -static int read_card_id(smc,slot) -struct s_smc *smc ; /* Do not use. */ -int slot ; +static int read_card_id(struct s_smc *smc, int slot) +/* struct s_smc *smc ; Do not use. */ { int card_id ; @@ -1126,9 +1070,7 @@ int slot ; * END_MANUAL_ENTRY() * ************************/ -int get_board_para(smc,slot) -struct s_smc *smc ; -int slot ; +int get_board_para(struct s_smc *smc, int slot) { int val ; int i ; @@ -1175,9 +1117,7 @@ int slot ; } /* Enable access to specified MCA slot. */ -static void EnableSlotAccess(smc,slot) -struct s_smc *smc ; -int slot ; +static void EnableSlotAccess(struct s_smc *smc, int slot) { SK_UNUSED(slot) ; @@ -1195,8 +1135,7 @@ int slot ; } /* Disable access to MCA slot formerly enabled via EnableSlotAccess(). */ -static void DisableSlotAccess(smc) -struct s_smc *smc ; +static void DisableSlotAccess(struct s_smc *smc) { #ifndef AIX SK_UNUSED(smc) ; @@ -1245,9 +1184,7 @@ struct s_smc *smc ; * The smc pointer must be valid now. * ************************/ -int exist_board(smc,slot) -struct s_smc *smc ; -int slot ; +int exist_board(struct s_smc *smc, int slot) { int i ; #ifdef MULT_OEM @@ -1284,9 +1221,7 @@ int slot ; } -int get_board_para(smc,slot) -struct s_smc *smc ; -int slot ; +int get_board_para(struct s_smc *smc, int slot) { int i ; @@ -1327,9 +1262,7 @@ const u_char sklogo[6] = SKLOGO_STR ; #endif /* MULT_OEM */ -int exist_board(smc,port) -struct s_smc *smc ; -HW_PTR port ; +int exist_board(struct s_smc *smc, HW_PTR port) { int i ; #ifdef MULT_OEM @@ -1400,9 +1333,7 @@ HW_PTR port ; #endif /* MULT_OEM */ } -int get_board_para(smc,slot) -struct s_smc *smc ; -int slot ; +int get_board_para(struct s_smc *smc, int slot) { SK_UNUSED(smc) ; SK_UNUSED(slot) ; @@ -1412,9 +1343,7 @@ int slot ; #ifdef PCI #ifdef USE_BIOS_FUN -int exist_board(smc,slot) -struct s_smc *smc ; -int slot ; +int exist_board(struct s_smc *smc, int slot) { u_short dev_id ; u_short ven_id ; @@ -1452,9 +1381,7 @@ int slot ; #endif /* PCI */ #endif /* USE_BIOS_FUNC */ -void driver_get_bia(smc, bia_addr) -struct s_smc *smc ; -struct fddi_addr *bia_addr ; +void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr) { int i ; @@ -1465,8 +1392,7 @@ struct fddi_addr *bia_addr ; } } -void smt_start_watchdog(smc) -struct s_smc *smc ; +void smt_start_watchdog(struct s_smc *smc) { SK_UNUSED(smc) ; /* Make LINT happy. */ @@ -1481,8 +1407,7 @@ struct s_smc *smc ; #endif /* DEBUG */ } -void smt_stop_watchdog(smc) -struct s_smc *smc ; +void smt_stop_watchdog(struct s_smc *smc) { SK_UNUSED(smc) ; /* Make LINT happy. */ #ifndef DEBUG @@ -1497,9 +1422,7 @@ struct s_smc *smc ; } #ifdef PCI -static char get_rom_byte(smc,addr) -struct s_smc *smc ; -u_short addr ; +static char get_rom_byte(struct s_smc *smc, u_short addr) { GET_PAGE(addr) ; return (READ_PROM(ADDR(B2_FDP))) ; @@ -1544,11 +1467,7 @@ u_short addr ; * * END_MANUAL_ENTRY */ -int mac_drv_vpd_read(smc,buf,size,image) -struct s_smc *smc ; -char *buf ; -int size ; -char image ; +int mac_drv_vpd_read(struct s_smc *smc, char *buf, int size, char image) { u_short ibase ; u_short pci_base ; @@ -1597,16 +1516,14 @@ char image ; return(len) ; } -void mac_drv_pci_fix(smc,fix_value) -struct s_smc *smc ; -u_long fix_value ; +void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value) { smc->hw.pci_fix_value = fix_value ; } -void mac_do_pci_fix(smc) -struct s_smc *smc ; +void mac_do_pci_fix(struct s_smc *smc) { SK_UNUSED(smc) ; } #endif /* PCI */ + diff --git a/drivers/net/skfp/ecm.c b/drivers/net/skfp/ecm.c index 7eaab1c3f9d2..47d922cb3c08 100644 --- a/drivers/net/skfp/ecm.c +++ b/drivers/net/skfp/ecm.c @@ -94,17 +94,16 @@ static const char * const ecm_events[] = { * function declarations */ -static void ecm_fsm() ; -static void start_ecm_timer() ; -static void stop_ecm_timer() ; -static void prop_actions() ; +static void ecm_fsm(struct s_smc *smc, int cmd); +static void start_ecm_timer(struct s_smc *smc, u_long value, int event); +static void stop_ecm_timer(struct s_smc *smc); +static void prop_actions(struct s_smc *smc); /* init ECM state machine clear all ECM vars and flags */ -void ecm_init(smc) -struct s_smc *smc ; +void ecm_init(struct s_smc *smc) { smc->e.path_test = PT_PASSED ; smc->e.trace_prop = 0 ; @@ -122,9 +121,7 @@ struct s_smc *smc ; process event until SM is stable */ -void ecm(smc,event) -struct s_smc *smc ; -int event ; +void ecm(struct s_smc *smc, int event) { int state ; @@ -143,9 +140,7 @@ int event ; /* process ECM event */ -static void ecm_fsm(smc,cmd) -struct s_smc *smc ; -int cmd ; +static void ecm_fsm(struct s_smc *smc, int cmd) { int ls_a ; /* current line state PHY A */ int ls_b ; /* current line state PHY B */ @@ -429,8 +424,7 @@ int cmd ; /* * trace propagation actions for SAS & DAS */ -static void prop_actions(smc) -struct s_smc *smc ; +static void prop_actions(struct s_smc *smc) { int port_in = 0 ; int port_out = 0 ; @@ -480,8 +474,7 @@ struct s_smc *smc ; /* * trace propagation actions for Concentrator */ -static void prop_actions(smc) -struct s_smc *smc ; +static void prop_actions(struct s_smc *smc) { int initiator ; int upstream ; @@ -527,10 +520,7 @@ struct s_smc *smc ; * SMT timer interface * start ECM timer */ -static void start_ecm_timer(smc,value,event) -struct s_smc *smc ; -u_long value; -int event ; +static void start_ecm_timer(struct s_smc *smc, u_long value, int event) { smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event)); } @@ -539,8 +529,7 @@ int event ; * SMT timer interface * stop ECM timer */ -static void stop_ecm_timer(smc) -struct s_smc *smc ; +static void stop_ecm_timer(struct s_smc *smc) { if (smc->e.ecm_timer.tm_active) smt_timer_stop(smc,&smc->e.ecm_timer) ; diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c index e5fecf8f9e73..fd39b4b2ef7d 100644 --- a/drivers/net/skfp/ess.c +++ b/drivers/net/skfp/ess.c @@ -80,8 +80,11 @@ static const struct fddi_addr null_addr = {{0,0,0,0,0,0}} ; ------------------------------------------------------------- */ -static void ess_send_response(), ess_config_fifo(), - ess_send_alc_req(), ess_send_frame() ; +static void ess_send_response(struct s_smc *smc, struct smt_header *sm, + int sba_cmd); +static void ess_config_fifo(struct s_smc *smc); +static void ess_send_alc_req(struct s_smc *smc); +static void ess_send_frame(struct s_smc *smc, SMbuf *mb); /* ------------------------------------------------------------- @@ -89,26 +92,17 @@ static void ess_send_response(), ess_config_fifo(), ------------------------------------------------------------- */ -extern void *sm_to_para() ; - -extern void smt_send_frame(), smt_free_mbuf(), - set_formac_tsync(), formac_reinit_tx() ; - -extern int smt_check_para() ; - -extern SMbuf *smt_get_mbuf(), *smt_build_frame() ; - -extern u_long smt_get_tid() ; - /* ------------------------------------------------------------- PUBLIC FUNCTIONS: ------------------------------------------------------------- */ - void ess_timer_poll(), ess_para_change() ; - - int ess_raf_received_pack(), process_bw_alloc() ; +void ess_timer_poll(struct s_smc *smc); +void ess_para_change(struct s_smc *smc); +int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, + int fs); +int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); /* @@ -120,11 +114,8 @@ extern u_long smt_get_tid() ; /* * evaluate the RAF frame */ -int ess_raf_received_pack(smc,mb,sm,fs) -struct s_smc *smc ; -SMbuf *mb ; -struct smt_header *sm ; -int fs ; +int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, + int fs) { void *p ; /* universal pointer */ struct smt_p_0016 *cmd ; /* para: command for the ESS */ @@ -384,10 +375,7 @@ int fs ; * determines the synchronous bandwidth, set the TSYNC register and the * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG. */ -int process_bw_alloc(smc,payload,overhead) -struct s_smc *smc ; -long payload ; -long overhead ; +int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) { /* * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG, @@ -483,10 +471,8 @@ long overhead ; return(TRUE) ; } -static void ess_send_response(smc,sm,sba_cmd) -struct s_smc *smc ; -struct smt_header *sm ; -int sba_cmd ; +static void ess_send_response(struct s_smc *smc, struct smt_header *sm, + int sba_cmd) { struct smt_sba_chg *chg ; SMbuf *mb ; @@ -550,9 +536,7 @@ int sba_cmd ; ess_send_frame(smc,mb) ; } - -void ess_timer_poll(smc) -struct s_smc *smc ; +void ess_timer_poll(struct s_smc *smc) { if (!smc->ess.raf_act_timer_poll) return ; @@ -566,8 +550,7 @@ struct s_smc *smc ; } } -static void ess_send_alc_req(smc) -struct s_smc *smc ; +static void ess_send_alc_req(struct s_smc *smc) { struct smt_sba_alc_req *req ; SMbuf *mb ; @@ -675,9 +658,7 @@ struct s_smc *smc ; ess_send_frame(smc,mb) ; } -static void ess_send_frame(smc,mb) -struct s_smc *smc ; -SMbuf *mb ; +static void ess_send_frame(struct s_smc *smc, SMbuf *mb) { /* * check if the frame must be send to the own ESS @@ -703,15 +684,13 @@ SMbuf *mb ; } } -void ess_para_change(smc) -struct s_smc *smc ; +void ess_para_change(struct s_smc *smc) { (void)process_bw_alloc(smc,(long)smc->mib.a[PATH0].fddiPATHSbaPayload, (long)smc->mib.a[PATH0].fddiPATHSbaOverhead) ; } -static void ess_config_fifo(smc) -struct s_smc *smc ; +static void ess_config_fifo(struct s_smc *smc) { /* * if nothing to do exit @@ -738,3 +717,4 @@ struct s_smc *smc ; #endif /* ESS */ #endif /* no SLIM_SMT */ + diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c index 834100b97d73..d2b43139375f 100644 --- a/drivers/net/skfp/fplustm.c +++ b/drivers/net/skfp/fplustm.c @@ -43,10 +43,10 @@ static const char ID_sccs[] = "@(#)fplustm.c 1.32 99/02/23 (C) SK " ; /* * prototypes for static function */ -static void build_claim_beacon() ; -static int init_mac() ; -static void rtm_init() ; -static void smt_split_up_fifo() ; +static void build_claim_beacon(struct s_smc *smc, u_long t_request); +static int init_mac(struct s_smc *smc, int all); +static void rtm_init(struct s_smc *smc); +static void smt_split_up_fifo(struct s_smc *smc); #if (!defined(NO_SMT_PANIC) || defined(DEBUG)) static char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n"; @@ -107,8 +107,7 @@ static int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC | FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ; -static u_long mac_get_tneg(smc) -struct s_smc *smc ; +static u_long mac_get_tneg(struct s_smc *smc) { u_long tneg ; @@ -117,8 +116,7 @@ struct s_smc *smc ; 0xffe00000L)) ; } -void mac_update_counter(smc) -struct s_smc *smc ; +void mac_update_counter(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACFrame_Ct = (smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L) @@ -143,9 +141,7 @@ struct s_smc *smc ; /* * write long value into buffer memory over memory data register (MDR), */ -void write_mdr(smc,val) -struct s_smc *smc ; -u_long val; +void write_mdr(struct s_smc *smc, u_long val) { CHECK_NPP() ; MDRW(val) ; @@ -154,9 +150,7 @@ u_long val; /* * read long value from buffer memory over memory data register (MDR), */ -u_long read_mdr(smc,addr) -struct s_smc *smc ; -unsigned int addr; +u_long read_mdr(struct s_smc *smc, unsigned int addr) { long p ; CHECK_NPP() ; @@ -173,8 +167,7 @@ unsigned int addr; /* * clear buffer memory */ -static void init_ram(smc) -struct s_smc *smc ; +static void init_ram(struct s_smc *smc) { u_short i ; @@ -193,8 +186,7 @@ struct s_smc *smc ; /* * set receive FIFO pointer */ -static void set_recvptr(smc) -struct s_smc *smc ; +static void set_recvptr(struct s_smc *smc) { /* * initialize the pointer for receive queue 1 @@ -224,8 +216,7 @@ struct s_smc *smc ; /* * set transmit FIFO pointer */ -static void set_txptr(smc) -struct s_smc *smc ; +static void set_txptr(struct s_smc *smc) { outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ; /* reset transmit queues */ @@ -257,8 +248,7 @@ struct s_smc *smc ; /* * init memory buffer management registers */ -static void init_rbc(smc) -struct s_smc *smc ; +static void init_rbc(struct s_smc *smc) { u_short rbc_ram_addr ; @@ -279,8 +269,7 @@ struct s_smc *smc ; /* * init rx pointer */ -static void init_rx(smc) -struct s_smc *smc ; +static void init_rx(struct s_smc *smc) { struct s_smt_rx_queue *queue ; @@ -302,9 +291,7 @@ struct s_smc *smc ; /* * set the TSYNC register of the FORMAC to regulate synchronous transmission */ -void set_formac_tsync(smc,sync_bw) -struct s_smc *smc ; -long sync_bw ; +void set_formac_tsync(struct s_smc *smc, long sync_bw) { outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ; } @@ -312,8 +299,7 @@ long sync_bw ; /* * init all tx data structures */ -static void init_tx(smc) -struct s_smc *smc ; +static void init_tx(struct s_smc *smc) { struct s_smt_tx_queue *queue ; @@ -339,8 +325,7 @@ struct s_smc *smc ; llc_recover_tx(smc) ; } -static void mac_counter_init(smc) -struct s_smc *smc ; +static void mac_counter_init(struct s_smc *smc) { int i ; u_long *ec ; @@ -363,8 +348,7 @@ struct s_smc *smc ; /* * set FORMAC address, and t_request */ -static void set_formac_addr(smc) -struct s_smc *smc ; +static void set_formac_addr(struct s_smc *smc) { long t_requ = smc->mib.m[MAC0].fddiMACT_Req ; @@ -390,9 +374,7 @@ struct s_smc *smc ; outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ; } -static void set_int(p,l) -char *p; -int l; +static void set_int(char *p, int l) { p[0] = (char)(l >> 24) ; p[1] = (char)(l >> 16) ; @@ -408,12 +390,12 @@ int l; * else * append 'end of chain' pointer */ -static void copy_tx_mac(smc,td,mac,off,len) -struct s_smc *smc ; -u_long td; /* transmit descriptor */ -struct fddi_mac *mac; /* mac frame pointer */ -unsigned off; /* start address within buffer memory */ -int len ; /* lenght of the frame including the FC */ +static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac, + unsigned off, int len) +/* u_long td; transmit descriptor */ +/* struct fddi_mac *mac; mac frame pointer */ +/* unsigned off; start address within buffer memory */ +/* int len ; lenght of the frame including the FC */ { int i ; u_int *p ; @@ -457,8 +439,7 @@ int len ; /* lenght of the frame including the FC */ END_MANUAL_ENTRY */ -static void directed_beacon(smc) -struct s_smc *smc ; +static void directed_beacon(struct s_smc *smc) { SK_LOC_DECL(u_int,a[2]) ; @@ -487,9 +468,7 @@ struct s_smc *smc ; special frame packets end with a pointer to their own descriptor, and the MORE bit is set in the descriptor */ -static void build_claim_beacon(smc,t_request) -struct s_smc *smc ; -u_long t_request; +static void build_claim_beacon(struct s_smc *smc, u_long t_request) { u_int td ; int len ; @@ -550,8 +529,7 @@ u_long t_request; outpw(FM_A(FM_RPXSF),0) ; } -void formac_rcv_restart(smc) -struct s_smc *smc ; +void formac_rcv_restart(struct s_smc *smc) { /* enable receive function */ SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ; @@ -559,15 +537,13 @@ struct s_smc *smc ; outpw(FM_A(FM_CMDREG1),FM_ICLLR) ; /* clear receive lock */ } -void formac_tx_restart(smc) -struct s_smc *smc ; +void formac_tx_restart(struct s_smc *smc) { outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */ outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */ } -static void enable_formac(smc) -struct s_smc *smc ; +static void enable_formac(struct s_smc *smc) { /* set formac IMSK : 0 enables irq */ outpw(FM_A(FM_IMSK1U),~mac_imsk1u) ; @@ -607,9 +583,8 @@ Note After any ring operational change the transmit complete END_MANUAL_ENTRY */ -void enable_tx_irq(smc, queue) -struct s_smc *smc ; -u_short queue ; /* 0 = synchronous queue, 1 = asynchronous queue 0 */ +void enable_tx_irq(struct s_smc *smc, u_short queue) +/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */ { u_short imask ; @@ -643,9 +618,8 @@ Note The operating system dependent module should disable END_MANUAL_ENTRY */ -void disable_tx_irq(smc, queue) -struct s_smc *smc ; -u_short queue ; /* 0 = synchronous queue, 1 = asynchronous queue 0 */ +void disable_tx_irq(struct s_smc *smc, u_short queue) +/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */ { u_short imask ; @@ -660,8 +634,7 @@ u_short queue ; /* 0 = synchronous queue, 1 = asynchronous queue 0 */ } #endif -static void disable_formac(smc) -struct s_smc *smc ; +static void disable_formac(struct s_smc *smc) { /* clear formac IMSK : 1 disables irq */ outpw(FM_A(FM_IMSK1U),MW) ; @@ -673,9 +646,7 @@ struct s_smc *smc ; } -static void mac_ring_up(smc,up) -struct s_smc *smc ; -int up; +static void mac_ring_up(struct s_smc *smc, int up) { if (up) { formac_rcv_restart(smc) ; /* enable receive function */ @@ -702,10 +673,7 @@ int up; * mac2_irq: status bits for the receive queue 1, and ring status * ring status indication bits */ -void mac2_irq(smc,code_s2u,code_s2l) -struct s_smc *smc ; -u_short code_s2u ; -u_short code_s2l ; +void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l) { u_short change_s2l ; u_short change_s2u ; @@ -831,10 +799,7 @@ mac2_end: /* * mac3_irq: receive queue 2 bits and address detection bits */ -void mac3_irq(smc,code_s3u,code_s3l) -struct s_smc *smc ; -u_short code_s3u ; -u_short code_s3l ; +void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l) { UNUSED(code_s3l) ; @@ -857,8 +822,7 @@ u_short code_s3l ; /* * take formac offline */ -static void formac_offline(smc) -struct s_smc *smc ; +static void formac_offline(struct s_smc *smc) { outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */ @@ -876,8 +840,7 @@ struct s_smc *smc ; /* * bring formac online */ -static void formac_online(smc) -struct s_smc *smc ; +static void formac_online(struct s_smc *smc) { enable_formac(smc) ; SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT | @@ -887,8 +850,7 @@ struct s_smc *smc ; /* * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon) */ -int init_fplus(smc) -struct s_smc *smc ; +int init_fplus(struct s_smc *smc) { smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ; smc->hw.fp.rx_mode = FM_MDAMA ; @@ -926,9 +888,7 @@ struct s_smc *smc ; /* enable_formac(smc) ; */ } -static int init_mac(smc,all) -struct s_smc *smc ; -int all ; +static int init_mac(struct s_smc *smc, int all) { u_short t_max,x ; u_long time=0 ; @@ -1033,9 +993,7 @@ int all ; /* * called by CFM */ -void config_mux(smc,mux) -struct s_smc *smc ; -int mux; +void config_mux(struct s_smc *smc, int mux) { plc_config_mux(smc,mux) ; @@ -1049,8 +1007,7 @@ int mux; * the interrupt must not be permanently enabled * RMT calls this function periodically (timer driven polling) */ -void sm_mac_check_beacon_claim(smc) -struct s_smc *smc ; +void sm_mac_check_beacon_claim(struct s_smc *smc) { /* set formac IMSK : 0 enables irq */ outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ; @@ -1063,9 +1020,7 @@ struct s_smc *smc ; /* * control ODL output */ -void sm_pm_control(smc,mode) -struct s_smc *smc ; -int mode; +void sm_pm_control(struct s_smc *smc, int mode) { SK_UNUSED(smc) ; @@ -1084,9 +1039,7 @@ int mode; /* * control MAC layer (called by RMT) */ -void sm_ma_control(smc,mode) -struct s_smc *smc ; -int mode; +void sm_ma_control(struct s_smc *smc, int mode) { switch(mode) { case MA_OFFLINE : @@ -1110,8 +1063,7 @@ int mode; } } -int sm_mac_get_tx_state(smc) -struct s_smc *smc ; +int sm_mac_get_tx_state(struct s_smc *smc) { return((inpw(FM_A(FM_STMCHN))>>4)&7) ; } @@ -1120,12 +1072,10 @@ struct s_smc *smc ; * multicast functions */ -static struct s_fpmc *mac_get_mc_table(smc,user,own,del,can) -struct s_smc *smc ; -struct fddi_addr *user ; -struct fddi_addr *own ; -int del ; -int can ; +static struct s_fpmc* mac_get_mc_table(struct s_smc *smc, + struct fddi_addr *user, + struct fddi_addr *own, + int del, int can) { struct s_fpmc *tb ; struct s_fpmc *slot ; @@ -1166,8 +1116,7 @@ Function DOWNCALL (SMT, fplustm.c) END_MANUAL_ENTRY() */ -void mac_clear_multicast(smc) -struct s_smc *smc ; +void mac_clear_multicast(struct s_smc *smc) { struct s_fpmc *tb ; int i ; @@ -1198,9 +1147,7 @@ Returns 0: always success END_MANUAL_ENTRY() */ -int mac_set_func_addr(smc,f_addr) -struct s_smc *smc ; -u_long f_addr ; +int mac_set_func_addr(struct s_smc *smc, u_long f_addr) { smc->hw.fp.func_addr = f_addr ; return(0) ; @@ -1235,10 +1182,7 @@ Note After a 'driver reset' or a 'station set address' all END_MANUAL_ENTRY() */ -int mac_add_multicast(smc,addr,can) -struct s_smc *smc ; -struct fddi_addr *addr ; -int can ; +int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) { SK_LOC_DECL(struct fddi_addr,own) ; struct s_fpmc *tb ; @@ -1292,10 +1236,7 @@ Para addr pointer to a multicast address END_MANUAL_ENTRY() */ -void mac_del_multicast(smc,addr,can) -struct s_smc *smc ; -struct fddi_addr *addr ; -int can ; +void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) { SK_LOC_DECL(struct fddi_addr,own) ; struct s_fpmc *tb ; @@ -1341,8 +1282,7 @@ Function DOWNCALL (SMT, fplustm.c) END_MANUAL_ENTRY() */ -void mac_update_multicast(smc) -struct s_smc *smc ; +void mac_update_multicast(struct s_smc *smc) { struct s_fpmc *tb ; u_char *fu ; @@ -1418,9 +1358,7 @@ Note The selected receive modes will be lost after 'driver reset' END_MANUAL_ENTRY */ -void mac_set_rx_mode(smc,mode) -struct s_smc *smc ; -int mode ; +void mac_set_rx_mode(struct s_smc *smc, int mode) { switch (mode) { case RX_ENABLE_ALLMULTI : @@ -1476,8 +1414,7 @@ int mode ; END_MANUAL_ENTRY */ -void rtm_irq(smc) -struct s_smc *smc ; +void rtm_irq(struct s_smc *smc) { outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ; /* clear IRQ */ if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) { @@ -1490,15 +1427,13 @@ struct s_smc *smc ; outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable RTM monitoring */ } -static void rtm_init(smc) -struct s_smc *smc ; +static void rtm_init(struct s_smc *smc) { outpd(ADDR(B2_RTM_INI),0) ; /* timer = 0 */ outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable IRQ */ } -void rtm_set_timer(smc) -struct s_smc *smc ; +void rtm_set_timer(struct s_smc *smc) { /* * MIB timer and hardware timer have the same resolution of 80nS @@ -1508,8 +1443,7 @@ struct s_smc *smc ; outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ; } -static void smt_split_up_fifo(smc) -struct s_smc *smc ; +static void smt_split_up_fifo(struct s_smc *smc) { /* @@ -1629,8 +1563,7 @@ struct s_smc *smc ; smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ; } -void formac_reinit_tx(smc) -struct s_smc *smc ; +void formac_reinit_tx(struct s_smc *smc) { /* * Split up the FIFO and reinitialize the MAC if synchronous @@ -1642,4 +1575,3 @@ struct s_smc *smc ; } } - diff --git a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h index f4e6c4826ebe..899c8c0413b0 100644 --- a/drivers/net/skfp/h/cmtdef.h +++ b/drivers/net/skfp/h/cmtdef.h @@ -418,7 +418,6 @@ struct s_pcon { void *pc_p ; } ; - /* * link error monitor */ @@ -444,7 +443,6 @@ struct lem_counter { #define NUMBITS 10 - #ifdef AMDPLC /* @@ -480,216 +478,184 @@ struct s_plc { * function prototypes */ #include "h/mbuf.h" /* Type definitions for MBUFs */ -void hwt_restart( /* hwt.c */ -#ifdef ANSIC - struct s_smc *smc -#endif - ) ; - -SMbuf *smt_build_frame( /* smt.c */ -#ifdef ANSIC - struct s_smc *smc, - int class, - int type, - int length -#endif - ) ; +#include "h/smtstate.h" /* struct smt_state */ -SMbuf *smt_get_mbuf( /* drvsr.c */ -#ifdef ANSIC - struct s_smc *smc -#endif - ) ; - -void *sm_to_para( /* smt.c */ -#ifdef ANSIC - struct s_smc *smc, - struct smt_header *sm, - int para -#endif - ) ; +void hwt_restart(struct s_smc *smc); /* hwt.c */ +SMbuf *smt_build_frame(struct s_smc *smc, int class, int type, + int length); /* smt.c */ +SMbuf *smt_get_mbuf(struct s_smc *smc); /* drvsr.c */ +void *sm_to_para(struct s_smc *smc, struct smt_header *sm, + int para); /* smt.c */ #ifndef SK_UNUSED #define SK_UNUSED(var) (void)(var) #endif -void queue_event() ; -void ecm() ; -void ecm_init() ; -void rmt() ; -void rmt_init() ; -void pcm() ; -void pcm_init() ; -void cfm() ; -void cfm_init() ; -void smt_timer_start() ; -void smt_timer_stop() ; -void pcm_status_state() ; -void plc_config_mux() ; -void sm_lem_evaluate() ; -void smt_clear_una_dna() ; -void mac_status_para() ; -void mac_update_counter() ; -void sm_pm_ls_latch() ; -void sm_ma_control() ; -void sm_mac_check_beacon_claim() ; -void config_mux() ; -void smt_agent_init() ; -void smt_timer_init() ; -void smt_received_pack() ; -void smt_add_para() ; -void smt_swap_para() ; -void ev_init() ; -void hwt_init() ; -u_long hwt_read() ; -void hwt_stop() ; -void hwt_start() ; -void smt_send_mbuf() ; -void smt_free_mbuf() ; -void sm_pm_bypass_req() ; -void rmt_indication() ; -void cfm_state_change() ; -void rx_indication() ; -void tx_indication() ; -#ifndef NO_SMT_PANIC -void smt_panic() ; -#else -#ifdef DEBUG -void smt_panic() ; +void queue_event(struct s_smc *smc, int class, int event); +void ecm(struct s_smc *smc, int event); +void ecm_init(struct s_smc *smc); +void rmt(struct s_smc *smc, int event); +void rmt_init(struct s_smc *smc); +void pcm(struct s_smc *smc, const int np, int event); +void pcm_init(struct s_smc *smc); +void cfm(struct s_smc *smc, int event); +void cfm_init(struct s_smc *smc); +void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time, + u_long token); +void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer); +void pcm_status_state(struct s_smc *smc, int np, int *type, int *state, + int *remote, int *mac); +void plc_config_mux(struct s_smc *smc, int mux); +void sm_lem_evaluate(struct s_smc *smc); +void smt_clear_una_dna(struct s_smc *smc); +void mac_update_counter(struct s_smc *smc); +void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off); +void sm_ma_control(struct s_smc *smc, int mode); +void sm_mac_check_beacon_claim(struct s_smc *smc); +void config_mux(struct s_smc *smc, int mux); +void smt_agent_init(struct s_smc *smc); +void smt_timer_init(struct s_smc *smc); +void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs); +void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, + int index, int local); +void smt_swap_para(struct smt_header *sm, int len, int direction); +void ev_init(struct s_smc *smc); +void hwt_init(struct s_smc *smc); +u_long hwt_read(struct s_smc *smc); +void hwt_stop(struct s_smc *smc); +void hwt_start(struct s_smc *smc, u_long time); +void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc); +void smt_free_mbuf(struct s_smc *smc, SMbuf *mb); +void sm_pm_bypass_req(struct s_smc *smc, int mode); +void rmt_indication(struct s_smc *smc, int i); +void cfm_state_change(struct s_smc *smc, int c_state); + +#if defined(DEBUG) || !defined(NO_SMT_PANIC) +void smt_panic(struct s_smc *smc, char *text); #else #define smt_panic(smc,text) -#endif /* DEBUG */ -#endif /* NO_SMT_PANIC */ -void smt_stat_counter() ; -void smt_timer_poll() ; -u_long smt_get_time() ; -u_long smt_get_tid() ; -void smt_timer_done() ; -void smt_set_defaults() ; -void smt_fixup_mib() ; -void smt_reset_defaults() ; -void smt_agent_task() ; -void smt_please_reconnect() ; -int smt_check_para() ; -void driver_get_bia() ; -#ifdef SUPERNET_3 -void drv_reset_indication() ; +#endif /* DEBUG || !NO_SMT_PANIC */ + +void smt_stat_counter(struct s_smc *smc, int stat); +void smt_timer_poll(struct s_smc *smc); +u_long smt_get_time(void); +u_long smt_get_tid(struct s_smc *smc); +void smt_timer_done(struct s_smc *smc); +void smt_set_defaults(struct s_smc *smc); +void smt_fixup_mib(struct s_smc *smc); +void smt_reset_defaults(struct s_smc *smc, int level); +void smt_agent_task(struct s_smc *smc); +void smt_please_reconnect(struct s_smc *smc, int reconn_time); +int smt_check_para(struct s_smc *smc, struct smt_header *sm, + const u_short list[]); +void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr); + +#ifdef SUPERNET_3 +void drv_reset_indication(struct s_smc *smc); #endif /* SUPERNET_3 */ -void smt_start_watchdog() ; - -void smt_event() ; -void pcm_event() ; -void rmt_event() ; -void cfm_event() ; -void timer_event() ; -void ev_dispatcher() ; - -void smt_get_state() ; -void ecm_get_state() ; -void pcm_get_state() ; -void rmt_get_state() ; - -void ecm_state_change() ; -int sm_pm_bypass_present() ; -void pcm_state_change() ; -void rmt_state_change() ; -int sm_pm_get_ls() ; -int pcm_get_s_port() ; -int pcm_rooted_station() ; -int cfm_get_mac_input() ; -int cfm_get_mac_output() ; -int port_to_mib() ; -int cem_build_path() ; -int sm_mac_get_tx_state() ; -int is_individual() ; -int is_my_addr() ; -int is_broadcast() ; -int is_equal() ; -char *get_pcmstate() ; - -int smt_action() ; -u_short smt_online() ; -void smt_force_irq() ; -void smt_pmf_received_pack() ; -void smt_send_frame() ; -void smt_set_timestamp() ; -void mac_set_rx_mode() ; -int mac_add_multicast() ; -int mac_set_func_addr() ; -void mac_del_multicast() ; -void mac_update_multicast() ; -void mac_clear_multicast() ; -void mac_rx_directed_beacon() ; -void set_formac_tsync() ; -void formac_reinit_tx() ; -void formac_tx_restart() ; -void process_receive() ; -void init_driver_fplus() ; - -void rtm_irq() ; -void rtm_set_timer() ; -void ring_status_indication() ; -void llc_recover_tx() ; -void llc_restart_tx() ; -void plc_clear_irq() ; -void plc_irq() ; -int smt_set_mac_opvalues() ; -#ifdef TAG_MODE -void mac_drv_pci_fix() ; -void mac_do_pci_fix() ; -void mac_drv_clear_tx_queue() ; -void mac_drv_repair_descr() ; -u_long hwt_quick_read() ; -void hwt_wait_time() ; + +void smt_start_watchdog(struct s_smc *smc); +void smt_event(struct s_smc *smc, int event); +void timer_event(struct s_smc *smc, u_long token); +void ev_dispatcher(struct s_smc *smc); +void pcm_get_state(struct s_smc *smc, struct smt_state *state); +void ecm_state_change(struct s_smc *smc, int e_state); +int sm_pm_bypass_present(struct s_smc *smc); +void pcm_state_change(struct s_smc *smc, int plc, int p_state); +void rmt_state_change(struct s_smc *smc, int r_state); +int sm_pm_get_ls(struct s_smc *smc, int phy); +int pcm_get_s_port(struct s_smc *smc); +int pcm_rooted_station(struct s_smc *smc); +int cfm_get_mac_input(struct s_smc *smc); +int cfm_get_mac_output(struct s_smc *smc); +int port_to_mib(struct s_smc *smc, int p); +int cem_build_path(struct s_smc *smc, char *to, int path_index); +int sm_mac_get_tx_state(struct s_smc *smc); +int is_individual(struct fddi_addr *addr); +int is_my_addr(struct s_smc *smc, struct fddi_addr *addr); +int is_broadcast(struct fddi_addr *addr); +int is_equal(struct fddi_addr *addr1, struct fddi_addr *addr2); +char *get_pcmstate(struct s_smc *smc, int np); +int smt_action(struct s_smc *smc, int class, int code, int index); +u_short smt_online(struct s_smc *smc, int on); +void smt_force_irq(struct s_smc *smc); +void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local); +void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local); +void smt_set_timestamp(struct s_smc *smc, u_char *p); +void mac_set_rx_mode(struct s_smc *smc, int mode); +int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); +int mac_set_func_addr(struct s_smc *smc, u_long f_addr); +void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); +void mac_update_multicast(struct s_smc *smc); +void mac_clear_multicast(struct s_smc *smc); +void set_formac_tsync(struct s_smc *smc, long sync_bw); +void formac_reinit_tx(struct s_smc *smc); +void formac_tx_restart(struct s_smc *smc); +void process_receive(struct s_smc *smc); +void init_driver_fplus(struct s_smc *smc); +void rtm_irq(struct s_smc *smc); +void rtm_set_timer(struct s_smc *smc); +void ring_status_indication(struct s_smc *smc, u_long status); +void llc_recover_tx(struct s_smc *smc); +void llc_restart_tx(struct s_smc *smc); +void plc_clear_irq(struct s_smc *smc, int p); +void plc_irq(struct s_smc *smc, int np, unsigned int cmd); +int smt_set_mac_opvalues(struct s_smc *smc); + +#ifdef TAG_MODE +void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value); +void mac_do_pci_fix(struct s_smc *smc); +void mac_drv_clear_tx_queue(struct s_smc *smc); +void mac_drv_repair_descr(struct s_smc *smc); +u_long hwt_quick_read(struct s_smc *smc); +void hwt_wait_time(struct s_smc *smc, u_long start, long duration); #endif #ifdef SMT_PNMI -#ifdef ANSIC -int pnmi_init (struct s_smc* smc); -int pnmi_process_ndis_id (struct s_smc* smc, u_long ndis_oid, void* buf, - int len, int* BytesAccessed, int* BytesNeeded, u_char action); -#else -int pnmi_init (); -int pnmi_process_ndis_id (); -#endif +int pnmi_init(struct s_smc* smc); +int pnmi_process_ndis_id(struct s_smc *smc, u_long ndis_oid, void *buf, int len, + int *BytesAccessed, int *BytesNeeded, u_char action); #endif #ifdef SBA #ifndef _H2INC -void sba() ; +void sba(); #endif -void sba_raf_received_pack() ; -void sba_timer_poll() ; -void smt_init_sba() ; +void sba_raf_received_pack(); +void sba_timer_poll(); +void smt_init_sba(); #endif + #ifdef ESS -int ess_raf_received_pack() ; -void ess_timer_poll() ; -void ess_para_change() ; +int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, + int fs); +void ess_timer_poll(struct s_smc *smc); +void ess_para_change(struct s_smc *smc); #endif -#ifdef BOOT -#define smt_srf_event(a,b,c,d) -#define smt_init_evc(a) +#ifndef BOOT +void smt_init_evc(struct s_smc *smc); +void smt_srf_event(struct s_smc *smc, int code, int index, int cond); #else -void smt_init_evc() ; -void smt_srf_event() ; +#define smt_init_evc(smc) +#define smt_srf_event(smc,code,index,cond) #endif #ifndef SMT_REAL_TOKEN_CT -void smt_emulate_token_ct(); +void smt_emulate_token_ct(struct s_smc *smc, int mac_index); #endif #if defined(DEBUG) && !defined(BOOT) -void dump_smt() ; +void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text); #else #define dump_smt(smc,sm,text) #endif #ifdef DEBUG -char *addr_to_string() ; -void dump_hex() ; +char* addr_to_string(struct fddi_addr *addr); +void dump_hex(char *p, int len); #endif + #endif /* PROTOTYP_INC */ /* PNMI default defines */ diff --git a/drivers/net/skfp/h/smtstate.h b/drivers/net/skfp/h/smtstate.h index 689fa25dc044..62fe695077a9 100644 --- a/drivers/net/skfp/h/smtstate.h +++ b/drivers/net/skfp/h/smtstate.h @@ -12,6 +12,9 @@ * ******************************************************************************/ +#ifndef _SKFP_H_SMTSTATE_H_ +#define _SKFP_H_SMTSTATE_H_ + /* * SMT state definitions */ @@ -98,3 +101,6 @@ struct pcm_state { struct smt_state { struct pcm_state pcm_state[NUMPHYS] ; /* port A & port B */ } ; + +#endif + diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c index ea5f5e090864..8016c9ae14e1 100644 --- a/drivers/net/skfp/hwmtm.c +++ b/drivers/net/skfp/hwmtm.c @@ -75,15 +75,17 @@ extern u_char force_irq_pending ; ------------------------------------------------------------- */ -static void queue_llc_rx(), smt_to_llc(), - init_txd_ring(), init_rxd_ring(), - queue_txd_mb() ; - -static u_long init_descr_ring(), repair_txd_ring(), - repair_rxd_ring() ; - -static SMbuf *get_llc_rx(), *get_txd_mb() ; - +static void queue_llc_rx(struct s_smc *smc, SMbuf *mb); +static void smt_to_llc(struct s_smc *smc, SMbuf *mb); +static void init_txd_ring(struct s_smc *smc); +static void init_rxd_ring(struct s_smc *smc); +static void queue_txd_mb(struct s_smc *smc, SMbuf *mb); +static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start, + int count); +static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue); +static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue); +static SMbuf* get_llc_rx(struct s_smc *smc); +static SMbuf* get_txd_mb(struct s_smc *smc); /* ------------------------------------------------------------- @@ -92,55 +94,81 @@ static SMbuf *get_llc_rx(), *get_txd_mb() ; */ /* The external SMT functions are listed in cmtdef.h */ -extern void *mac_drv_get_space(), *mac_drv_get_desc_mem(), - init_board(), mac_drv_fill_rxd(), - plc1_irq(), mac_drv_tx_complete(), - plc2_irq(), mac1_irq(), - mac2_irq(), mac3_irq(), - timer_irq(), mac_drv_rx_complete(), - mac_drv_requeue_rxd(), init_plc(), - mac_drv_clear_rxd(), llc_restart_tx(), - ev_dispatcher(), smt_force_irq() ; +extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size); +extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size); +extern void init_board(struct s_smc *smc, u_char *mac_addr); +extern void mac_drv_fill_rxd(struct s_smc *smc); +extern void plc1_irq(struct s_smc *smc); +extern void mac_drv_tx_complete(struct s_smc *smc, + volatile struct s_smt_fp_txd *txd); +extern void plc2_irq(struct s_smc *smc); +extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl); +extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l); +extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l); +extern void timer_irq(struct s_smc *smc); +extern void mac_drv_rx_complete(struct s_smc *smc, + volatile struct s_smt_fp_rxd *rxd, + int frag_count, int len); +extern void mac_drv_requeue_rxd(struct s_smc *smc, + volatile struct s_smt_fp_rxd *rxd, + int frag_count); +extern void init_plc(struct s_smc *smc); +extern void mac_drv_clear_rxd(struct s_smc *smc, + volatile struct s_smt_fp_rxd *rxd, int frag_count); #ifdef USE_OS_CPY -extern void hwm_cpy_rxd2mb(), hwm_cpy_txd2mb() ; +extern void hwm_cpy_rxd2mb(void); +extern void hwm_cpy_txd2mb(void); #endif + #ifdef ALL_RX_COMPLETE -extern void mac_drv_all_receives_complete() ; +extern void mac_drv_all_receives_complete(void); #endif -extern u_long mac_drv_virt2phys(), dma_master() ; +extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt); +extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag); #ifdef NDIS_OS2 -extern void post_proc() ; +extern void post_proc(void); #else -extern void dma_complete() ; +extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, + int flag); #endif -extern int init_fplus(), mac_drv_rx_init() ; +extern int init_fplus(struct s_smc *smc); +extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, + int la_len); /* ------------------------------------------------------------- PUBLIC FUNCTIONS: ------------------------------------------------------------- */ - void process_receive(), smt_send_mbuf(), - fddi_isr(), mac_drv_clear_txd(), - smt_free_mbuf(), init_driver_fplus(), - mac_drv_rx_mode(), init_fddi_driver(), - mac_drv_clear_tx_queue(), - mac_drv_clear_rx_queue(), - hwm_tx_frag(), hwm_rx_frag() ; - - int mac_drv_rx_frag(), mac_drv_init(), - hwm_tx_init() ; - - u_int mac_drv_check_space() ; - - SMbuf *smt_get_mbuf() ; +void process_receive(struct s_smc *smc); +void fddi_isr(struct s_smc *smc); +void mac_drv_clear_txd(struct s_smc *smc); +void smt_free_mbuf(struct s_smc *smc, SMbuf *mb); +void init_driver_fplus(struct s_smc *smc); +void mac_drv_rx_mode(struct s_smc *smc, int mode); +void init_fddi_driver(struct s_smc *smc, u_char *mac_addr); +void mac_drv_clear_tx_queue(struct s_smc *smc); +void mac_drv_clear_rx_queue(struct s_smc *smc); +void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, + int frame_status); +void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, + int frame_status); + +int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len); +int mac_drv_init(struct s_smc *smc); +int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, + int frame_status); + +u_int mac_drv_check_space(void); + +SMbuf* smt_get_mbuf(struct s_smc *smc); #ifdef DEBUG - void mac_drv_debug_lev() ; + void mac_drv_debug_lev(void); #endif /* @@ -208,7 +236,7 @@ extern int init_fplus(), mac_drv_rx_init() ; * * END_MANUAL_ENTRY */ -u_int mac_drv_check_space() +u_int mac_drv_check_space(void) { #ifdef MB_OUTSIDE_SMC #ifdef COMMON_MB_POOL @@ -238,8 +266,7 @@ u_int mac_drv_check_space() * mac_drv_init once, after the adatper is detected. * END_MANUAL_ENTRY */ -int mac_drv_init(smc) -struct s_smc *smc ; +int mac_drv_init(struct s_smc *smc) { if (sizeof(struct s_smt_fp_rxd) % 16) { SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ; @@ -289,8 +316,7 @@ struct s_smc *smc ; * least significant byte etc.) * END_MANUAL_ENTRY */ -void init_driver_fplus(smc) -struct s_smc *smc ; +void init_driver_fplus(struct s_smc *smc) { smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ; @@ -305,10 +331,9 @@ struct s_smc *smc ; #endif } -static u_long init_descr_ring(smc,start,count) -struct s_smc *smc ; -union s_fp_descr volatile *start; -int count ; +static u_long init_descr_ring(struct s_smc *smc, + union s_fp_descr volatile *start, + int count) { int i ; union s_fp_descr volatile *d1 ; @@ -337,8 +362,7 @@ int count ; return(phys) ; } -static void init_txd_ring(smc) -struct s_smc *smc ; +static void init_txd_ring(struct s_smc *smc) { struct s_smt_fp_txd volatile *ds ; struct s_smt_tx_queue *queue ; @@ -375,8 +399,7 @@ struct s_smc *smc ; outpd(ADDR(B5_XS_DA),phys) ; } -static void init_rxd_ring(smc) -struct s_smc *smc ; +static void init_rxd_ring(struct s_smc *smc) { struct s_smt_fp_rxd volatile *ds ; struct s_smt_rx_queue *queue ; @@ -406,9 +429,7 @@ struct s_smc *smc ; * * END_MANUAL_ENTRY */ -void init_fddi_driver(smc,mac_addr) -struct s_smc *smc ; -u_char *mac_addr ; /* canonical address */ +void init_fddi_driver(struct s_smc *smc, u_char *mac_addr) { SMbuf *mb ; int i ; @@ -472,8 +493,7 @@ u_char *mac_addr ; /* canonical address */ } -SMbuf *smt_get_mbuf(smc) -struct s_smc *smc ; +SMbuf *smt_get_mbuf(struct s_smc *smc) { register SMbuf *mb ; @@ -495,9 +515,7 @@ struct s_smc *smc ; return (mb) ; /* May be NULL */ } -void smt_free_mbuf(smc, mb) -struct s_smc *smc ; -SMbuf *mb; +void smt_free_mbuf(struct s_smc *smc, SMbuf *mb) { if (mb) { @@ -543,8 +561,7 @@ SMbuf *mb; * * END_MANUAL_ENTRY */ -void mac_drv_repair_descr(smc) -struct s_smc *smc ; +void mac_drv_repair_descr(struct s_smc *smc) { u_long phys ; @@ -576,9 +593,7 @@ struct s_smc *smc ; outpd(ADDR(B0_R1_CSR),CSR_START) ; } -static u_long repair_txd_ring(smc,queue) -struct s_smc *smc ; -struct s_smt_tx_queue *queue ; +static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue) { int i ; int tx_used ; @@ -630,9 +645,7 @@ struct s_smt_tx_queue *queue ; * RxDs with an OWN bit set but with a reset STF bit should be * skipped and owned by the driver (OWN = 0). */ -static u_long repair_rxd_ring(smc,queue) -struct s_smc *smc ; -struct s_smt_rx_queue *queue ; +static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue) { int i ; int rx_used ; @@ -703,8 +716,7 @@ struct s_smt_rx_queue *queue ; * * END_MANUAL_ENTRY */ -void fddi_isr(smc) -struct s_smc *smc ; +void fddi_isr(struct s_smc *smc) { u_long is ; /* ISR source */ u_short stu, stl ; @@ -987,9 +999,7 @@ struct s_smc *smc ; * * END_MANUAL_ENTRY */ -void mac_drv_rx_mode(smc,mode) -struct s_smc *smc ; -int mode ; +void mac_drv_rx_mode(struct s_smc *smc, int mode) { switch(mode) { case RX_ENABLE_PASS_SMT: @@ -1038,8 +1048,7 @@ int mode ; /* * process receive queue */ -void process_receive(smc) -struct s_smc *smc ; +void process_receive(struct s_smc *smc) { int i ; int n ; @@ -1379,9 +1388,7 @@ rx_end: return ; /* lint bug: needs return detect end of function */ } -static void smt_to_llc(smc,mb) -struct s_smc *smc ; -SMbuf *mb ; +static void smt_to_llc(struct s_smc *smc, SMbuf *mb) { u_char fc ; @@ -1416,12 +1423,8 @@ SMbuf *mb ; * * END_MANUAL_ENTRY */ -void hwm_rx_frag(smc,virt,phys,len,frame_status) -struct s_smc *smc ; -char far *virt ; -u_long phys ; -int len ; -int frame_status ; +void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, + int frame_status) { struct s_smt_fp_rxd volatile *r ; u_int rbctrl ; @@ -1460,10 +1463,7 @@ int frame_status ; * * END_MANUAL_ENTRY */ -int mac_drv_rx_frag(smc,virt,len) -struct s_smc *smc ; -void far *virt ; -int len ; +int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len) { NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ; @@ -1500,8 +1500,7 @@ int len ; * * END_MANUAL_ENTRY */ -void mac_drv_clear_rx_queue(smc) -struct s_smc *smc ; +void mac_drv_clear_rx_queue(struct s_smc *smc) { struct s_smt_fp_rxd volatile *r ; struct s_smt_fp_rxd volatile *next_rxd ; @@ -1588,12 +1587,8 @@ struct s_smc *smc ; * * END_MANUAL_ENTRY */ -int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status) -struct s_smc *smc ; -u_char fc ; -int frag_count ; -int frame_len ; -int frame_status ; +int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, + int frame_status) { NDD_TRACE("THiB",fc,frag_count,frame_len) ; smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ; @@ -1670,12 +1665,8 @@ int frame_status ; * * END_MANUAL_ENTRY */ -void hwm_tx_frag(smc,virt,phys,len,frame_status) -struct s_smc *smc ; -char far *virt ; -u_long phys ; -int len ; -int frame_status ; +void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, + int frame_status) { struct s_smt_fp_txd volatile *t ; struct s_smt_tx_queue *queue ; @@ -1780,9 +1771,7 @@ int frame_status ; /* * queues a receive for later send */ -static void queue_llc_rx(smc,mb) -struct s_smc *smc ; -SMbuf *mb ; +static void queue_llc_rx(struct s_smc *smc, SMbuf *mb) { DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ; smc->os.hwm.queued_rx_frames++ ; @@ -1806,8 +1795,7 @@ SMbuf *mb ; /* * get a SMbuf from the llc_rx_queue */ -static SMbuf *get_llc_rx(smc) -struct s_smc *smc ; +static SMbuf *get_llc_rx(struct s_smc *smc) { SMbuf *mb ; @@ -1823,9 +1811,7 @@ struct s_smc *smc ; * queues a transmit SMT MBuf during the time were the MBuf is * queued the TxD ring */ -static void queue_txd_mb(smc,mb) -struct s_smc *smc ; -SMbuf *mb ; +static void queue_txd_mb(struct s_smc *smc, SMbuf *mb) { DB_GEN("_rx: queue_txd_mb = %x",(void *)mb,0,4) ; smc->os.hwm.queued_txd_mb++ ; @@ -1842,8 +1828,7 @@ SMbuf *mb ; /* * get a SMbuf from the txd_tx_queue */ -static SMbuf *get_txd_mb(smc) -struct s_smc *smc ; +static SMbuf *get_txd_mb(struct s_smc *smc) { SMbuf *mb ; @@ -1858,10 +1843,7 @@ struct s_smc *smc ; /* * SMT Send function */ -void smt_send_mbuf(smc,mb,fc) -struct s_smc *smc; -SMbuf *mb; -int fc; +void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc) { char far *data ; int len ; @@ -1995,8 +1977,7 @@ int fc; * * END_MANUAL_ENTRY */ -void mac_drv_clear_txd(smc) -struct s_smc *smc ; +void mac_drv_clear_txd(struct s_smc *smc) { struct s_smt_tx_queue *queue ; struct s_smt_fp_txd volatile *t1 ; @@ -2087,8 +2068,7 @@ free_next_queue: ; * * END_MANUAL_ENTRY */ -void mac_drv_clear_tx_queue(smc) -struct s_smc *smc ; +void mac_drv_clear_tx_queue(struct s_smc *smc) { struct s_smt_fp_txd volatile *t ; struct s_smt_tx_queue *queue ; @@ -2180,10 +2160,7 @@ struct s_smc *smc ; * * END_MANUAL_ENTRY */ -void mac_drv_debug_lev(smc,flag,lev) -struct s_smc *smc ; -int flag ; -int lev ; +void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev) { switch(flag) { case (int)NULL: diff --git a/drivers/net/skfp/hwt.c b/drivers/net/skfp/hwt.c index 50755ba8a1aa..e01f8a0f35c6 100644 --- a/drivers/net/skfp/hwt.c +++ b/drivers/net/skfp/hwt.c @@ -39,7 +39,7 @@ static const char ID_sccs[] = "@(#)hwt.c 1.13 97/04/23 (C) SK " ; * Prototypes of local functions. */ /* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */ -/*static*/ void hwt_restart() ; +/*static void hwt_restart() ; */ /************************ * @@ -60,9 +60,7 @@ static const char ID_sccs[] = "@(#)hwt.c 1.13 97/04/23 (C) SK " ; ************************/ #define HWT_MAX (65000) -void hwt_start(smc, time) -struct s_smc *smc ; -u_long time ; +void hwt_start(struct s_smc *smc, u_long time) { u_short cnt ; @@ -115,8 +113,7 @@ u_long time ; * Nothing. * ************************/ -void hwt_stop(smc) -struct s_smc *smc ; +void hwt_stop(struct s_smc *smc) { #ifndef PCI /* stop counter 0 by switching to mode 0 */ @@ -145,8 +142,7 @@ struct s_smc *smc ; * Nothing. * ************************/ -void hwt_init(smc) -struct s_smc *smc ; +void hwt_init(struct s_smc *smc) { smc->hw.t_start = 0 ; smc->hw.t_stop = 0 ; @@ -169,8 +165,7 @@ struct s_smc *smc ; * Nothing. * ************************/ -void hwt_restart(smc) -struct s_smc *smc ; +void hwt_restart(struct s_smc *smc) { hwt_stop(smc) ; #ifndef PCI @@ -193,8 +188,7 @@ struct s_smc *smc ; * The elapsed time since last start in units of 16us. * ************************/ -u_long hwt_read(smc) -struct s_smc *smc ; +u_long hwt_read(struct s_smc *smc) { u_short tr ; #ifndef PCI @@ -238,8 +232,7 @@ struct s_smc *smc ; * current timer value in units of 80ns. * ************************/ -u_long hwt_quick_read(smc) -struct s_smc *smc ; +u_long hwt_quick_read(struct s_smc *smc) { u_long interval ; u_long time ; @@ -267,10 +260,7 @@ struct s_smc *smc ; * NOTE: The fuction will return immediately, if the timer is not * started ************************/ -void hwt_wait_time(smc,start,duration) -struct s_smc *smc ; -u_long start ; -long duration ; +void hwt_wait_time(struct s_smc *smc, u_long start, long int duration) { long diff ; long interval ; @@ -312,3 +302,4 @@ long duration ; } } #endif + diff --git a/drivers/net/skfp/lnkstat.c b/drivers/net/skfp/lnkstat.c index 7d2d94eaee0d..00a248044f86 100644 --- a/drivers/net/skfp/lnkstat.c +++ b/drivers/net/skfp/lnkstat.c @@ -52,8 +52,7 @@ Return smt_error_word These bits are supported: END_MANUAL_ENTRY() */ -u_long smt_get_error_word(smc) -struct s_smc *smc ; +u_long smt_get_error_word(struct s_smc *smc) { u_long st; @@ -92,8 +91,7 @@ Return smt_event_word always 0 END_MANUAL_ENTRY() */ -u_long smt_get_event_word(smc) -struct s_smc *smc ; +u_long smt_get_event_word(struct s_smc *smc) { return (u_long) 0; } @@ -111,8 +109,7 @@ Return smt_port_event_word always 0 END_MANUAL_ENTRY() */ -u_long smt_get_port_event_word(smc) -struct s_smc *smc ; +u_long smt_get_port_event_word(struct s_smc *smc) { return (u_long) 0; } @@ -135,10 +132,7 @@ Return len used len of the error log field END_MANUAL_ENTRY() */ -int smt_read_errorlog(smc,p,len) -struct s_smc *smc ; -char _far *p ; -int len ; +int smt_read_errorlog(struct s_smc *smc, char _far *p, int len) { int i ; int st ; @@ -207,3 +201,4 @@ int len ; er->ucode_version_level = 0x0101 ; return(len) ; } + diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c index 4be8f3a9e8f4..571f055c096b 100644 --- a/drivers/net/skfp/pcmplc.c +++ b/drivers/net/skfp/pcmplc.c @@ -199,28 +199,25 @@ static int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR; /* external functions */ -void all_selection_criteria (); +void all_selection_criteria(struct s_smc *smc); /* internal functions */ -static void pcm_fsm() ; -static void pc_rcode_actions() ; -static void pc_tcode_actions() ; -static void reset_lem_struct() ; -static void plc_init() ; -static void sm_ph_lem_start() ; -static void sm_ph_lem_stop() ; -static void sm_ph_linestate() ; -static void real_init_plc() ; +static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd); +static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy); +static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy); +static void reset_lem_struct(struct s_phy *phy); +static void plc_init(struct s_smc *smc, int p); +static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold); +static void sm_ph_lem_stop(struct s_smc *smc, int np); +static void sm_ph_linestate(struct s_smc *smc, int phy, int ls); +static void real_init_plc(struct s_smc *smc); /* * SMT timer interface * start PCM timer 0 */ -static void start_pcm_timer0(smc,value,event,phy) -struct s_smc *smc ; -u_long value; -int event; -struct s_phy *phy; +static void start_pcm_timer0(struct s_smc *smc, u_long value, int event, + struct s_phy *phy) { phy->timer0_exp = FALSE ; /* clear timer event flag */ smt_timer_start(smc,&phy->pcm_timer0,value, @@ -230,9 +227,7 @@ struct s_phy *phy; * SMT timer interface * stop PCM timer 0 */ -static void stop_pcm_timer0(smc,phy) -struct s_smc *smc ; -struct s_phy *phy; +static void stop_pcm_timer0(struct s_smc *smc, struct s_phy *phy) { if (phy->pcm_timer0.tm_active) smt_timer_stop(smc,&phy->pcm_timer0) ; @@ -242,8 +237,7 @@ struct s_phy *phy; init PCM state machine (called by driver) clear all PCM vars and flags */ -void pcm_init(smc) -struct s_smc *smc ; +void pcm_init(struct s_smc *smc) { int i ; int np ; @@ -407,8 +401,7 @@ struct s_smc *smc ; real_init_plc(smc) ; } -void init_plc(smc) -struct s_smc *smc ; +void init_plc(struct s_smc *smc) { SK_UNUSED(smc) ; @@ -421,8 +414,7 @@ struct s_smc *smc ; */ } -static void real_init_plc(smc) -struct s_smc *smc ; +static void real_init_plc(struct s_smc *smc) { int p ; @@ -430,9 +422,7 @@ struct s_smc *smc ; plc_init(smc,p) ; } -static void plc_init(smc,p) -struct s_smc *smc ; -int p; +static void plc_init(struct s_smc *smc, int p) { int i ; #ifndef MOT_ELM @@ -495,10 +485,7 @@ int p; /* * control PCM state machine */ -static void plc_go_state(smc,p,state) -struct s_smc *smc ; -int p; -int state; +static void plc_go_state(struct s_smc *smc, int p, int state) { HW_PTR port ; int val ; @@ -514,9 +501,7 @@ int state; /* * read current line state (called by ECM & PCM) */ -int sm_pm_get_ls(smc,phy) -struct s_smc *smc ; -int phy; +int sm_pm_get_ls(struct s_smc *smc, int phy) { int state ; @@ -549,10 +534,7 @@ int phy; return(state) ; } -static int plc_send_bits(smc,phy,len) -struct s_smc *smc ; -struct s_phy *phy; -int len; +static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len) { int np = phy->np ; /* PHY index */ int n ; @@ -589,9 +571,7 @@ int len; /* * config plc muxes */ -void plc_config_mux(smc,mux) -struct s_smc *smc ; -int mux ; +void plc_config_mux(struct s_smc *smc, int mux) { if (smc->s.sas != SMT_DAS) return ; @@ -615,10 +595,7 @@ int mux ; process event until SM is stable */ -void pcm(smc,np,event) -struct s_smc *smc ; -const int np; -int event; +void pcm(struct s_smc *smc, const int np, int event) { int state ; int oldstate ; @@ -697,10 +674,7 @@ int event; /* * PCM state machine */ -static void pcm_fsm(smc,phy,cmd) -struct s_smc *smc ; -struct s_phy *phy; -int cmd; +static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd) { int i ; int np = phy->np ; /* PHY index */ @@ -1063,10 +1037,7 @@ int cmd; /* * force line state on a PHY output (only in MAINT state) */ -static void sm_ph_linestate(smc,phy,ls) -struct s_smc *smc ; -int phy; -int ls; +static void sm_ph_linestate(struct s_smc *smc, int phy, int ls) { int cntrl ; @@ -1095,9 +1066,7 @@ int ls; outpw(PLC(phy,PL_CNTRL_B),cntrl) ; } - -static void reset_lem_struct(phy) -struct s_phy *phy; +static void reset_lem_struct(struct s_phy *phy) { struct lem_counter *lem = &phy->lem ; @@ -1108,9 +1077,7 @@ struct s_phy *phy; /* * link error monitor */ -static void lem_evaluate(smc,phy) -struct s_smc *smc ; -struct s_phy *phy; +static void lem_evaluate(struct s_smc *smc, struct s_phy *phy) { int ber ; u_long errors ; @@ -1210,8 +1177,7 @@ struct s_phy *phy; /* * called by SMT to calculate LEM bit error rate */ -void sm_lem_evaluate(smc) -struct s_smc *smc ; +void sm_lem_evaluate(struct s_smc *smc) { int np ; @@ -1219,9 +1185,7 @@ struct s_smc *smc ; lem_evaluate(smc,&smc->y[np]) ; } -static void lem_check_lct(smc,phy) -struct s_smc *smc ; -struct s_phy *phy ; +static void lem_check_lct(struct s_smc *smc, struct s_phy *phy) { struct lem_counter *lem = &phy->lem ; struct fddi_mib_p *mib ; @@ -1265,10 +1229,7 @@ struct s_phy *phy ; /* * LEM functions */ -static void sm_ph_lem_start(smc,np,threshold) -struct s_smc *smc ; -int np; -int threshold; +static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold) { struct lem_counter *lem = &smc->y[np].lem ; @@ -1286,9 +1247,7 @@ int threshold; SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ; } -static void sm_ph_lem_stop(smc,np) -struct s_smc *smc ; -int np; +static void sm_ph_lem_stop(struct s_smc *smc, int np) { struct lem_counter *lem = &smc->y[np].lem ; @@ -1297,10 +1256,8 @@ int np; } /* ARGSUSED */ -void sm_pm_ls_latch(smc,phy,on_off) -struct s_smc *smc ; -int phy; -int on_off; /* en- or disable ident. ls */ +void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off) +/* int on_off; en- or disable ident. ls */ { SK_UNUSED(smc) ; @@ -1317,10 +1274,7 @@ int on_off; /* en- or disable ident. ls */ /* * PCM pseudo code 5.1 .. 6.1 */ -static void pc_rcode_actions(smc,bit,phy) -struct s_smc *smc ; -int bit; -struct s_phy *phy; +static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy) { struct fddi_mib_p *mib ; @@ -1456,10 +1410,7 @@ struct s_phy *phy; /* * PCM pseudo code 5.1 .. 6.1 */ -static void pc_tcode_actions(smc,bit,phy) -struct s_smc *smc ; -const int bit; -struct s_phy *phy; +static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy) { int np = phy->np ; struct fddi_mib_p *mib ; @@ -1638,8 +1589,7 @@ struct s_phy *phy; /* * return status twisted (called by SMT) */ -int pcm_status_twisted(smc) -struct s_smc *smc ; +int pcm_status_twisted(struct s_smc *smc) { int twist = 0 ; if (smc->s.sas != SMT_DAS) @@ -1658,13 +1608,8 @@ struct s_smc *smc ; * remote phy type * remote mac yes/no */ -void pcm_status_state(smc,np,type,state,remote,mac) -struct s_smc *smc ; -int np; -int *type; -int *state; -int *remote; -int *mac; +void pcm_status_state(struct s_smc *smc, int np, int *type, int *state, + int *remote, int *mac) { struct s_phy *phy = &smc->y[np] ; struct fddi_mib_p *mib ; @@ -1687,8 +1632,7 @@ int *mac; /* * return rooted station status (called by SMT) */ -int pcm_rooted_station(smc) -struct s_smc *smc ; +int pcm_rooted_station(struct s_smc *smc) { int n ; @@ -1703,10 +1647,8 @@ struct s_smc *smc ; /* * Interrupt actions for PLC & PCM events */ -void plc_irq(smc,np,cmd) -struct s_smc *smc ; -int np; /* PHY index */ -unsigned int cmd; +void plc_irq(struct s_smc *smc, int np, unsigned int cmd) +/* int np; PHY index */ { struct s_phy *phy = &smc->y[np] ; struct s_plc *plc = &phy->plc ; @@ -1919,9 +1861,7 @@ unsigned int cmd; #endif } -void pcm_set_lct_short(smc,n) -struct s_smc *smc ; -int n ; +void pcm_set_lct_short(struct s_smc *smc, int n) { if (n <= 0 || n > 1000) return ; @@ -1932,9 +1872,7 @@ int n ; /* * fill state struct */ -void pcm_get_state(smc,state) -struct s_smc *smc ; -struct smt_state *state ; +void pcm_get_state(struct s_smc *smc, struct smt_state *state) { struct s_phy *phy ; struct pcm_state *pcs ; @@ -1968,9 +1906,7 @@ struct smt_state *state ; } } -int get_pcm_state(smc,np) -struct s_smc *smc ; -int np; +int get_pcm_state(struct s_smc *smc, int np) { int pcs ; @@ -1992,9 +1928,7 @@ int np; return(pcs) ; } -char *get_linestate(smc,np) -struct s_smc *smc ; -int np; +char *get_linestate(struct s_smc *smc, int np) { char *ls = "" ; @@ -2016,9 +1950,7 @@ int np; return(ls) ; } -char *get_pcmstate(smc,np) -struct s_smc *smc ; -int np; +char *get_pcmstate(struct s_smc *smc, int np) { char *pcs ; @@ -2040,8 +1972,7 @@ int np; return(pcs) ; } -void list_phy(smc) -struct s_smc *smc ; +void list_phy(struct s_smc *smc) { struct s_plc *plc ; int np ; @@ -2069,8 +2000,7 @@ struct s_smc *smc ; #ifdef CONCENTRATOR -void pcm_lem_dump(smc) -struct s_smc *smc ; +void pcm_lem_dump(struct s_smc *smc) { int i ; struct s_phy *phy ; diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c index ee0a8c58b5fc..e9422e654cbf 100644 --- a/drivers/net/skfp/pmf.c +++ b/drivers/net/skfp/pmf.c @@ -32,12 +32,16 @@ static const char ID_sccs[] = "@(#)pmf.c 1.37 97/08/04 (C) SK " ; #endif -static int smt_authorize() ; -static int smt_check_set_count() ; -static const struct s_p_tab *smt_get_ptab() ; -static int smt_mib_phys() ; -int smt_set_para() ; -void smt_add_para() ; +static int smt_authorize(struct s_smc *smc, struct smt_header *sm); +static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm); +static const struct s_p_tab* smt_get_ptab(u_short para); +static int smt_mib_phys(struct s_smc *smc); +int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, + int set); +void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, + int index, int local); +static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, + int set, int local); #define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e)) #define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e)) @@ -280,13 +284,7 @@ static const struct s_p_tab { { 0 } } ; - -static SMbuf *smt_build_pmf_response() ; - -void smt_pmf_received_pack(smc,mb,local) -struct s_smc *smc ; -SMbuf *mb ; -int local ; +void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local) { struct smt_header *sm ; SMbuf *reply ; @@ -316,13 +314,8 @@ int local ; } } -extern SMbuf *smt_get_mbuf() ; - -static SMbuf *smt_build_pmf_response(smc,req,set,local) -struct s_smc *smc ; -struct smt_header *req ; -int set ; -int local ; +static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, + int set, int local) { SMbuf *mb ; struct smt_header *smt ; @@ -509,11 +502,7 @@ int local ; return(mb) ; } -extern void *sm_to_para() ; - -static int smt_authorize(smc,sm) -struct s_smc *smc ; -struct smt_header *sm ; +static int smt_authorize(struct s_smc *smc, struct smt_header *sm) { struct smt_para *pa ; int i ; @@ -548,9 +537,7 @@ struct smt_header *sm ; return(0) ; } -static int smt_check_set_count(smc,sm) -struct s_smc *smc ; -struct smt_header *sm ; +static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm) { struct smt_para *pa ; struct smt_p_setcount *sc ; @@ -566,12 +553,8 @@ struct smt_header *sm ; return(0) ; } -void smt_add_para(smc,pcon,para,index,local) -struct s_smc *smc ; -struct s_pcon *pcon ; -u_short para ; -int index ; -int local ; +void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, + int index, int local) { struct smt_para *pa ; const struct s_p_tab *pt ; @@ -1095,12 +1078,8 @@ wrong_error: /* * set parameter */ -int smt_set_para(smc,pa,index,local,set) -struct s_smc *smc ; -struct smt_para *pa ; -int index ; -int local ; -int set ; +int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, + int set) { #define IFSET(x) if (set) (x) @@ -1549,8 +1528,7 @@ no_author_error: #endif } -static const struct s_p_tab *smt_get_ptab(para) -u_short para ; +static const struct s_p_tab *smt_get_ptab(u_short para) { const struct s_p_tab *pt ; for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++) @@ -1558,8 +1536,7 @@ u_short para ; return(pt->p_num ? pt : 0) ; } -static int smt_mib_phys(smc) -struct s_smc *smc ; +static int smt_mib_phys(struct s_smc *smc) { #ifdef CONCENTRATOR SK_UNUSED(smc) ; @@ -1572,9 +1549,7 @@ struct s_smc *smc ; #endif } -int port_to_mib(smc,p) -struct s_smc *smc ; -int p ; +int port_to_mib(struct s_smc *smc, int p) { #ifdef CONCENTRATOR SK_UNUSED(smc) ; @@ -1590,10 +1565,7 @@ int p ; #ifdef DEBUG #ifndef BOOT -void dump_smt(smc,sm,text) -struct s_smc *smc ; -struct smt_header *sm ; -char *text ; +void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text) { int len ; struct smt_para *pa ; @@ -1680,9 +1652,7 @@ char *text ; printf("-------------------------------------------------\n\n") ; } -void dump_hex(p,len) -char *p ; -int len ; +void dump_hex(char *p, int len) { int n = 0 ; while (len--) { diff --git a/drivers/net/skfp/queue.c b/drivers/net/skfp/queue.c index e54b544ff273..09adb3d68b7c 100644 --- a/drivers/net/skfp/queue.c +++ b/drivers/net/skfp/queue.c @@ -31,8 +31,7 @@ static const char ID_sccs[] = "@(#)queue.c 2.9 97/08/04 (C) SK " ; /* * init event queue management */ -void ev_init(smc) -struct s_smc *smc ; +void ev_init(struct s_smc *smc) { smc->q.ev_put = smc->q.ev_get = smc->q.ev_queue ; } @@ -40,10 +39,7 @@ struct s_smc *smc ; /* * add event to queue */ -void queue_event(smc,class,event) -struct s_smc *smc ; -int class ; -int event ; +void queue_event(struct s_smc *smc, int class, int event) { PRINTF("queue class %d event %d\n",class,event) ; smc->q.ev_put->class = class ; @@ -59,9 +55,7 @@ int event ; /* * timer_event is called from HW timer package. */ -void timer_event(smc,token) -struct s_smc *smc ; -u_long token ; +void timer_event(struct s_smc *smc, u_long token) { PRINTF("timer event class %d token %d\n", EV_T_CLASS(token), @@ -76,8 +70,7 @@ u_long token ; * send command to state machine * end */ -void ev_dispatcher(smc) -struct s_smc *smc ; +void ev_dispatcher(struct s_smc *smc) { struct event_queue *ev ; /* pointer into queue */ int class ; @@ -131,9 +124,7 @@ struct s_smc *smc ; * on 0 disconnect * on 1 connect */ -u_short smt_online(smc,on) -struct s_smc *smc ; -int on ; +u_short smt_online(struct s_smc *smc, int on) { queue_event(smc,EVENT_ECM,on ? EC_CONNECT : EC_DISCONNECT) ; ev_dispatcher(smc) ; @@ -147,10 +138,7 @@ int on ; * dump current flag setting */ #ifdef CONCENTRATOR -void do_smt_flag(smc,flag,value) -struct s_smc *smc ; -char *flag ; -int value ; +void do_smt_flag(struct s_smc *smc, char *flag, int value) { #ifdef DEBUG struct smt_debug *deb; diff --git a/drivers/net/skfp/rmt.c b/drivers/net/skfp/rmt.c index 5771dc42ced8..ef8d5672d9e8 100644 --- a/drivers/net/skfp/rmt.c +++ b/drivers/net/skfp/rmt.c @@ -102,17 +102,17 @@ static const char * const rmt_events[] = { /* * function declarations */ -static void rmt_fsm() ; -static void start_rmt_timer0() ; -static void start_rmt_timer1() ; -static void start_rmt_timer2() ; -static void stop_rmt_timer0() ; -static void stop_rmt_timer1() ; -static void stop_rmt_timer2() ; -static void rmt_dup_actions() ; -static void rmt_reinsert_actions() ; -static void rmt_leave_actions() ; -static void rmt_new_dup_actions() ; +static void rmt_fsm(struct s_smc *smc, int cmd); +static void start_rmt_timer0(struct s_smc *smc, u_long value, int event); +static void start_rmt_timer1(struct s_smc *smc, u_long value, int event); +static void start_rmt_timer2(struct s_smc *smc, u_long value, int event); +static void stop_rmt_timer0(struct s_smc *smc); +static void stop_rmt_timer1(struct s_smc *smc); +static void stop_rmt_timer2(struct s_smc *smc); +static void rmt_dup_actions(struct s_smc *smc); +static void rmt_reinsert_actions(struct s_smc *smc); +static void rmt_leave_actions(struct s_smc *smc); +static void rmt_new_dup_actions(struct s_smc *smc); #ifndef SUPERNET_3 extern void restart_trt_for_dbcn() ; @@ -122,8 +122,7 @@ extern void restart_trt_for_dbcn() ; init RMT state machine clear all RMT vars and flags */ -void rmt_init(smc) -struct s_smc *smc ; +void rmt_init(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ; smc->r.dup_addr_test = DA_NONE ; @@ -145,9 +144,7 @@ struct s_smc *smc ; process event until SM is stable */ -void rmt(smc,event) -struct s_smc *smc ; -int event ; +void rmt(struct s_smc *smc, int event) { int state ; @@ -166,9 +163,7 @@ int event ; /* process RMT event */ -static void rmt_fsm(smc,cmd) -struct s_smc *smc ; -int cmd ; +static void rmt_fsm(struct s_smc *smc, int cmd) { /* * RM00-RM70 : from all states @@ -535,8 +530,7 @@ int cmd ; * (jd) RMT duplicate address actions * leave the ring or reinsert just as configured */ -static void rmt_dup_actions(smc) -struct s_smc *smc ; +static void rmt_dup_actions(struct s_smc *smc) { if (smc->r.jm_flag) { } @@ -555,8 +549,7 @@ struct s_smc *smc ; /* * Reconnect to the Ring */ -static void rmt_reinsert_actions(smc) -struct s_smc *smc ; +static void rmt_reinsert_actions(struct s_smc *smc) { queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; queue_event(smc,EVENT_ECM,EC_CONNECT) ; @@ -565,8 +558,7 @@ struct s_smc *smc ; /* * duplicate address detected */ -static void rmt_new_dup_actions(smc) -struct s_smc *smc ; +static void rmt_new_dup_actions(struct s_smc *smc) { smc->r.da_flag = TRUE ; smc->r.bn_flag = FALSE ; @@ -591,8 +583,7 @@ struct s_smc *smc ; /* * leave the ring */ -static void rmt_leave_actions(smc) -struct s_smc *smc ; +static void rmt_leave_actions(struct s_smc *smc) { queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; /* @@ -605,10 +596,7 @@ struct s_smc *smc ; * SMT timer interface * start RMT timer 0 */ -static void start_rmt_timer0(smc,value,event) -struct s_smc *smc ; -u_long value ; -int event ; +static void start_rmt_timer0(struct s_smc *smc, u_long value, int event) { smc->r.timer0_exp = FALSE ; /* clear timer event flag */ smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event)); @@ -618,10 +606,7 @@ int event ; * SMT timer interface * start RMT timer 1 */ -static void start_rmt_timer1(smc,value,event) -struct s_smc *smc ; -u_long value ; -int event ; +static void start_rmt_timer1(struct s_smc *smc, u_long value, int event) { smc->r.timer1_exp = FALSE ; /* clear timer event flag */ smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event)); @@ -631,10 +616,7 @@ int event ; * SMT timer interface * start RMT timer 2 */ -static void start_rmt_timer2(smc,value,event) -struct s_smc *smc ; -u_long value ; -int event ; +static void start_rmt_timer2(struct s_smc *smc, u_long value, int event) { smc->r.timer2_exp = FALSE ; /* clear timer event flag */ smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event)); @@ -644,8 +626,7 @@ int event ; * SMT timer interface * stop RMT timer 0 */ -static void stop_rmt_timer0(smc) -struct s_smc *smc ; +static void stop_rmt_timer0(struct s_smc *smc) { if (smc->r.rmt_timer0.tm_active) smt_timer_stop(smc,&smc->r.rmt_timer0) ; @@ -655,8 +636,7 @@ struct s_smc *smc ; * SMT timer interface * stop RMT timer 1 */ -static void stop_rmt_timer1(smc) -struct s_smc *smc ; +static void stop_rmt_timer1(struct s_smc *smc) { if (smc->r.rmt_timer1.tm_active) smt_timer_stop(smc,&smc->r.rmt_timer1) ; @@ -666,9 +646,9 @@ struct s_smc *smc ; * SMT timer interface * stop RMT timer 2 */ -static void stop_rmt_timer2(smc) -struct s_smc *smc ; +static void stop_rmt_timer2(struct s_smc *smc) { if (smc->r.rmt_timer2.tm_active) smt_timer_stop(smc,&smc->r.rmt_timer2) ; } + diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 24032c79c1c5..a5e5d874c1f2 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -131,20 +131,10 @@ void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, int frag_count); int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, int la_len); -void smt_timer_poll(struct s_smc *smc); -void ring_status_indication(struct s_smc *smc, u_long status); -unsigned long smt_get_time(void); -void smt_stat_counter(struct s_smc *smc, int stat); -void cfm_state_change(struct s_smc *smc, int c_state); -void ecm_state_change(struct s_smc *smc, int e_state); -void pcm_state_change(struct s_smc *smc, int plc, int p_state); -void rmt_state_change(struct s_smc *smc, int r_state); -void drv_reset_indication(struct s_smc *smc); void dump_data(unsigned char *Data, int length); - // External functions from the hardware module -extern u_int mac_drv_check_space(); +extern u_int mac_drv_check_space(void); extern void read_address(struct s_smc *smc, u_char * mac_addr); extern void card_stop(struct s_smc *smc); extern int mac_drv_init(struct s_smc *smc); @@ -157,9 +147,7 @@ extern void fddi_isr(struct s_smc *smc); extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys, int len, int frame_status); extern void mac_drv_rx_mode(struct s_smc *smc, int mode); -extern void mac_drv_clear_tx_queue(struct s_smc *smc); extern void mac_drv_clear_rx_queue(struct s_smc *smc); -extern void mac_clear_multicast(struct s_smc *smc); extern void enable_tx_irq(struct s_smc *smc, u_short queue); extern void mac_drv_clear_txd(struct s_smc *smc); @@ -921,8 +909,7 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) dmi = dev->mc_list; for (i = 0; i < dev->mc_count; i++) { - mac_add_multicast(smc, - dmi->dmi_addr, 1); + mac_add_multicast(smc, dmi->dmi_addr, 1); PRINTK(KERN_INFO "ENABLE MC ADDRESS:"); PRINTK(" %02x %02x %02x ", dmi->dmi_addr[0], diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c index bfb61dfe6b16..8301daf21e48 100644 --- a/drivers/net/skfp/smt.c +++ b/drivers/net/skfp/smt.c @@ -62,68 +62,63 @@ extern const struct fddi_addr fddi_broadcast ; /* * external functions */ -int pcm_status_twisted() ; -void pcm_status_state() ; -int pcm_status_type() ; +int pcm_status_twisted(struct s_smc *smc); -extern SMbuf *smt_get_mbuf() ; - -#define EXPORT_PMF /* * function prototypes */ -u_long smt_get_tid() ; -EXPORT_PMF SMbuf *smt_build_frame() ; -EXPORT_PMF void *sm_to_para() ; #ifdef LITTLE_ENDIAN -static int smt_swap_short() ; +static int smt_swap_short(u_short s); #endif -static int mac_index() ; -static int phy_index() ; -static int mac_con_resource_index() ; -static int phy_con_resource_index() ; -EXPORT_PMF void smt_send_frame() ; -EXPORT_PMF void smt_set_timestamp() ; -static void smt_send_rdf() ; -static void smt_send_nif() ; -static void smt_send_ecf() ; -static void smt_echo_test() ; -static void smt_send_sif_config() ; -static void smt_send_sif_operation() ; -EXPORT_PMF void smt_swap_para() ; +static int mac_index(struct s_smc *smc, int mac); +static int phy_index(struct s_smc *smc, int phy); +static int mac_con_resource_index(struct s_smc *smc, int mac); +static int phy_con_resource_index(struct s_smc *smc, int phy); +static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, + int local); +static void smt_send_nif(struct s_smc *smc, struct fddi_addr *dest, int fc, + u_long tid, int type, int local); +static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, + u_long tid, int type, int len); +static void smt_echo_test(struct s_smc *smc, int dna); +static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, + u_long tid, int local); +static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, + u_long tid, int local); #ifdef LITTLE_ENDIAN -static void smt_string_swap() ; +static void smt_string_swap(void); #endif -static void smt_add_frame_len() ; -static void smt_fill_una() ; -static void smt_fill_sde() ; -static void smt_fill_state() ; -static void smt_fill_timestamp() ; -static void smt_fill_policy() ; -static void smt_fill_latency() ; -static void smt_fill_neighbor() ; -static int smt_fill_path() ; -static void smt_fill_mac_status() ; -static void smt_fill_lem() ; -static void smt_fill_version() ; -static void smt_fill_fsc() ; -static void smt_fill_mac_counter() ; -static void smt_fill_mac_fnc() ; -static void smt_fill_manufacturer() ; -static void smt_fill_user() ; -static void smt_fill_setcount() ; -static void smt_fill_echo() ; -int smt_check_para() ; - -void smt_clear_una_dna() ; -static void smt_clear_old_una_dna() ; +static void smt_add_frame_len(SMbuf *mb, int len); +static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una); +static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde); +static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state); +static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts); +static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy); +static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency); +static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor); +static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path); +static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st); +static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy); +static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers); +static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc); +static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc); +static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc); +static void smt_fill_manufacturer(struct s_smc *smc, + struct smp_p_manufacturer *man); +static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user); +static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount); +static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, + int len); + +void smt_clear_una_dna(struct s_smc *smc); +static void smt_clear_old_una_dna(struct s_smc *smc); #ifdef CONCENTRATOR -static int entity_to_index() ; +static int entity_to_index(void); #endif -static void update_dac() ; -static int div_ratio() ; +static void update_dac(struct s_smc *smc, int report); +static int div_ratio(u_long upper, u_long lower); #ifdef USE_CAN_ADDR -void hwm_conv_can() ; +void hwm_conv_can(struct s_smc *smc, char *data, int len); #else #define hwm_conv_can(smc,data,len) #endif @@ -136,8 +131,7 @@ static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ; /* * init SMT agent */ -void smt_agent_init(smc) -struct s_smc *smc ; +void smt_agent_init(struct s_smc *smc) { int i ; @@ -183,17 +177,16 @@ struct s_smc *smc ; * check tvu & tvd * end */ -void smt_agent_task(smc) -struct s_smc *smc ; +void smt_agent_task(struct s_smc *smc) { smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, EV_TOKEN(EVENT_SMT,SM_TIMER)) ; DB_SMT("SMT agent task\n",0,0) ; } -void smt_please_reconnect(smc,reconn_time) -struct s_smc *smc ; /* Pointer to SMT context */ -int reconn_time ; /* Wait for reconnect time in seconds */ +void smt_please_reconnect(struct s_smc *smc, int reconn_time) +/* struct s_smc *smc; Pointer to SMT context */ +/* int reconn_time; Wait for reconnect time in seconds */ { /* * The please reconnect variable is used as a timer. @@ -210,9 +203,7 @@ int reconn_time ; /* Wait for reconnect time in seconds */ } #ifndef SMT_REAL_TOKEN_CT -void smt_emulate_token_ct(smc, mac_index) -struct s_smc *smc; -int mac_index; +void smt_emulate_token_ct(struct s_smc *smc, int mac_index) { u_long count; u_long time; @@ -239,9 +230,7 @@ int mac_index; #endif /*ARGSUSED1*/ -void smt_event(smc,event) -struct s_smc *smc ; -int event ; +void smt_event(struct s_smc *smc, int event) { u_long time ; #ifndef SMT_REAL_TOKEN_CT @@ -457,9 +446,7 @@ int event ; EV_TOKEN(EVENT_SMT,SM_TIMER)) ; } -static int div_ratio(upper,lower) -u_long upper ; -u_long lower ; +static int div_ratio(u_long upper, u_long lower) { if ((upper<<16L) < upper) upper = 0xffff0000L ; @@ -475,10 +462,8 @@ u_long lower ; /* * receive packet handler */ -void smt_received_pack(smc,mb,fs) -struct s_smc *smc ; -SMbuf *mb ; -int fs ; /* frame status */ +void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs) +/* int fs; frame status */ { struct smt_header *sm ; int local ; @@ -823,9 +808,7 @@ int fs ; /* frame status */ smt_free_mbuf(smc,mb) ; } -static void update_dac(smc,report) -struct s_smc *smc ; -int report ; +static void update_dac(struct s_smc *smc, int report) { int cond ; @@ -843,11 +826,9 @@ int report ; * set station ID * send frame */ -EXPORT_PMF void smt_send_frame(smc,mb,fc,local) -struct s_smc *smc ; -SMbuf *mb ; /* buffer to send */ -int fc ; /* FC value */ -int local ; +void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local) +/* SMbuf *mb; buffer to send */ +/* int fc; FC value */ { struct smt_header *sm ; @@ -868,12 +849,11 @@ int local ; /* * generate and send RDF */ -static void smt_send_rdf(smc,rej,fc,reason,local) -struct s_smc *smc ; -SMbuf *rej ; /* mbuf of offending frame */ -int fc ; /* FC of denied frame */ -int reason ; /* reason code */ -int local ; +static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, + int local) +/* SMbuf *rej; mbuf of offending frame */ +/* int fc; FC of denied frame */ +/* int reason; reason code */ { SMbuf *mb ; struct smt_header *sm ; /* header of offending frame */ @@ -946,13 +926,12 @@ int local ; /* * generate and send NIF */ -static void smt_send_nif(smc,dest,fc,tid,type,local) -struct s_smc *smc ; -struct fddi_addr *dest ; /* dest address */ -int fc ; /* frame control */ -u_long tid ; /* transaction id */ -int type ; /* frame type */ -int local ; +static void smt_send_nif(struct s_smc *smc, struct fddi_addr *dest, int fc, + u_long tid, int type, int local) +/* struct fddi_addr *dest; dest address */ +/* int fc; frame control */ +/* u_long tid; transaction id */ +/* int type; frame type */ { struct smt_nif *nif ; SMbuf *mb ; @@ -976,9 +955,7 @@ int local ; /* * send NIF request (test purpose) */ -static void smt_send_nif_request(smc,dest) -struct s_smc *smc ; -struct fddi_addr *dest ; +static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest) { smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ; smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST], @@ -988,10 +965,8 @@ struct fddi_addr *dest ; /* * send ECF request (test purpose) */ -static void smt_send_ecf_request(smc,dest,len) -struct s_smc *smc ; -struct fddi_addr *dest ; -int len ; +static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest, + int len) { smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ; smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF], @@ -1002,9 +977,7 @@ int len ; /* * echo test */ -static void smt_echo_test(smc,dna) -struct s_smc *smc ; -int dna ; +static void smt_echo_test(struct s_smc *smc, int dna) { u_long tid ; @@ -1019,13 +992,13 @@ int dna ; /* * generate and send ECF */ -static void smt_send_ecf(smc,dest,fc,tid,type,len) -struct s_smc *smc ; -struct fddi_addr *dest ; /* dest address */ -int fc ; /* frame control */ -u_long tid ; /* transaction id */ -int type ; /* frame type */ -int len ; /* frame length */ +static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, + u_long tid, int type, int len) +/* struct fddi_addr *dest; dest address */ +/* int fc; frame control */ +/* u_long tid; transaction id */ +/* int type; frame type */ +/* int len; frame length */ { struct smt_ecf *ecf ; SMbuf *mb ; @@ -1045,11 +1018,10 @@ int len ; /* frame length */ * generate and send SIF config response */ -static void smt_send_sif_config(smc,dest,tid,local) -struct s_smc *smc ; -struct fddi_addr *dest ; /* dest address */ -u_long tid ; /* transaction id */ -int local ; +static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, + u_long tid, int local) +/* struct fddi_addr *dest; dest address */ +/* u_long tid; transaction id */ { struct smt_sif_config *sif ; SMbuf *mb ; @@ -1079,11 +1051,10 @@ int local ; * generate and send SIF operation response */ -static void smt_send_sif_operation(smc,dest,tid,local) -struct s_smc *smc ; -struct fddi_addr *dest ; /* dest address */ -u_long tid ; /* transaction id */ -int local ; +static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, + u_long tid, int local) +/* struct fddi_addr *dest; dest address */ +/* u_long tid; transaction id */ { struct smt_sif_operation *sif ; SMbuf *mb ; @@ -1128,11 +1099,8 @@ int local ; /* * get and initialize SMT frame */ -EXPORT_PMF SMbuf *smt_build_frame(smc,class,type,length) -struct s_smc *smc ; -int class ; -int type ; -int length ; +SMbuf *smt_build_frame(struct s_smc *smc, int class, int type, + int length) { SMbuf *mb ; struct smt_header *smt ; @@ -1167,9 +1135,7 @@ int length ; return(mb) ; } -static void smt_add_frame_len(mb,len) -SMbuf *mb ; -int len ; +static void smt_add_frame_len(SMbuf *mb, int len) { struct smt_header *smt ; @@ -1183,9 +1149,7 @@ int len ; /* * fill values in UNA parameter */ -static void smt_fill_una(smc,una) -struct s_smc *smc ; -struct smt_p_una *una ; +static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una) { SMTSETPARA(una,SMT_P_UNA) ; una->una_pad = 0 ; @@ -1195,9 +1159,7 @@ struct smt_p_una *una ; /* * fill values in SDE parameter */ -static void smt_fill_sde(smc,sde) -struct s_smc *smc ; -struct smt_p_sde *sde ; +static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde) { SMTSETPARA(sde,SMT_P_SDE) ; sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ; @@ -1213,9 +1175,7 @@ struct smt_p_sde *sde ; /* * fill in values in station state parameter */ -static void smt_fill_state(smc,state) -struct s_smc *smc ; -struct smt_p_state *state ; +static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state) { int top ; int twist ; @@ -1255,18 +1215,14 @@ struct smt_p_state *state ; /* * fill values in timestamp parameter */ -static void smt_fill_timestamp(smc,ts) -struct s_smc *smc ; -struct smt_p_timestamp *ts ; +static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts) { SMTSETPARA(ts,SMT_P_TIMESTAMP) ; smt_set_timestamp(smc,ts->ts_time) ; } -EXPORT_PMF void smt_set_timestamp(smc,p) -struct s_smc *smc ; -u_char *p ; +void smt_set_timestamp(struct s_smc *smc, u_char *p) { u_long time ; u_long utime ; @@ -1300,9 +1256,7 @@ u_char *p ; /* * fill values in station policy parameter */ -static void smt_fill_policy(smc,policy) -struct s_smc *smc ; -struct smt_p_policy *policy ; +static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy) { int i ; u_char *map ; @@ -1333,9 +1287,7 @@ struct smt_p_policy *policy ; /* * fill values in latency equivalent parameter */ -static void smt_fill_latency(smc,latency) -struct s_smc *smc ; -struct smt_p_latency *latency ; +static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency) { SMTSETPARA(latency,SMT_P_LATENCY) ; @@ -1358,9 +1310,7 @@ struct smt_p_latency *latency ; /* * fill values in MAC neighbors parameter */ -static void smt_fill_neighbor(smc,neighbor) -struct s_smc *smc ; -struct smt_p_neighbor *neighbor ; +static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor) { SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ; @@ -1379,9 +1329,7 @@ struct smt_p_neighbor *neighbor ; #define ALLPHYS ((smc->s.sas == SMT_SAS) ? 1 : 2) #endif -static int smt_fill_path(smc,path) -struct s_smc *smc ; -struct smt_p_path *path ; +static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path) { SK_LOC_DECL(int,type) ; SK_LOC_DECL(int,state) ; @@ -1429,9 +1377,7 @@ struct smt_p_path *path ; /* * fill values in mac status */ -static void smt_fill_mac_status(smc,st) -struct s_smc *smc ; -struct smt_p_mac_status *st ; +static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st) { SMTSETPARA(st,SMT_P_MAC_STATUS) ; @@ -1458,11 +1404,7 @@ struct smt_p_mac_status *st ; /* * fill values in LEM status */ - -static void smt_fill_lem(smc,lem,phy) -struct s_smc *smc ; -struct smt_p_lem *lem ; -int phy ; +static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy) { struct fddi_mib_p *mib ; @@ -1484,9 +1426,7 @@ int phy ; /* * fill version parameter */ -static void smt_fill_version(smc,vers) -struct s_smc *smc ; -struct smt_p_version *vers ; +static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers) { SK_UNUSED(smc) ; SMTSETPARA(vers,SMT_P_VERSION) ; @@ -1505,9 +1445,7 @@ struct smt_p_version *vers ; * note: this para 200B is NOT in swap table, because it's also set in * PMF add_para */ -static void smt_fill_fsc(smc,fsc) -struct s_smc *smc ; -struct smt_p_fsc *fsc ; +static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc) { SK_UNUSED(smc) ; SMTSETPARA(fsc,SMT_P_FSC) ; @@ -1527,9 +1465,7 @@ struct smt_p_fsc *fsc ; /* * fill mac counter field */ -static void smt_fill_mac_counter(smc,mc) -struct s_smc *smc ; -struct smt_p_mac_counter *mc ; +static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc) { SMTSETPARA(mc,SMT_P_MAC_COUNTER) ; mc->mc_mib_index = INDEX_MAC ; @@ -1541,9 +1477,7 @@ struct smt_p_mac_counter *mc ; /* * fill mac frame not copied counter */ -static void smt_fill_mac_fnc(smc,fnc) -struct s_smc *smc ; -struct smt_p_mac_fnc *fnc ; +static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc) { SMTSETPARA(fnc,SMT_P_MAC_FNC) ; fnc->nc_mib_index = INDEX_MAC ; @@ -1555,9 +1489,8 @@ struct smt_p_mac_fnc *fnc ; /* * fill manufacturer field */ -static void smt_fill_manufacturer(smc,man) -struct s_smc *smc ; -struct smp_p_manufacturer *man ; +static void smt_fill_manufacturer(struct s_smc *smc, + struct smp_p_manufacturer *man) { SMTSETPARA(man,SMT_P_MANUFACTURER) ; memcpy((char *) man->mf_data, @@ -1568,9 +1501,7 @@ struct smp_p_manufacturer *man ; /* * fill user field */ -static void smt_fill_user(smc,user) -struct s_smc *smc ; -struct smp_p_user *user ; +static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user) { SMTSETPARA(user,SMT_P_USER) ; memcpy((char *) user->us_data, @@ -1578,14 +1509,10 @@ struct smp_p_user *user ; sizeof(user->us_data)) ; } - - /* * fill set count */ -static void smt_fill_setcount(smc,setcount) -struct s_smc *smc ; -struct smt_p_setcount *setcount ; +static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount) { SK_UNUSED(smc) ; SMTSETPARA(setcount,SMT_P_SETCOUNT) ; @@ -1597,13 +1524,9 @@ struct smt_p_setcount *setcount ; /* * fill echo data */ -static void smt_fill_echo(smc,echo,seed,len) -struct s_smc *smc ; -struct smt_p_echo *echo ; -u_long seed ; -int len ; +static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, + int len) { - u_char *p ; SK_UNUSED(smc) ; @@ -1619,22 +1542,19 @@ int len ; * clear DNA and UNA * called from CFM if configuration changes */ -void smt_clear_una_dna(smc) -struct s_smc *smc ; +void smt_clear_una_dna(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; } -static void smt_clear_old_una_dna(smc) -struct s_smc *smc ; +static void smt_clear_old_una_dna(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ; smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ; } -u_long smt_get_tid(smc) -struct s_smc *smc ; +u_long smt_get_tid(struct s_smc *smc) { u_long tid ; while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0) @@ -1723,10 +1643,8 @@ static const struct smt_pdef { #define N_SMT_PLEN (sizeof(smt_pdef)/sizeof(smt_pdef[0])) -int smt_check_para(smc,sm,list) -struct s_smc *smc ; -struct smt_header *sm ; -const u_short list[] ; +int smt_check_para(struct s_smc *smc, struct smt_header *sm, + const u_short list[]) { const u_short *p = list ; while (*p) { @@ -1739,10 +1657,7 @@ const u_short list[] ; return(0) ; } -EXPORT_PMF void *sm_to_para(smc,sm,para) -struct s_smc *smc ; -struct smt_header *sm ; -int para ; +void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para) { char *p ; int len ; @@ -1773,9 +1688,7 @@ int para ; return(0) ; } -int is_my_addr(smc,addr) -struct s_smc *smc ; -struct fddi_addr *addr ; +int is_my_addr(struct s_smc *smc, struct fddi_addr *addr) { return(*(short *)(&addr->a[0]) == *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0]) @@ -1785,31 +1698,26 @@ struct fddi_addr *addr ; *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ; } -int is_zero(addr) -struct fddi_addr *addr ; +int is_zero(struct fddi_addr *addr) { return(*(short *)(&addr->a[0]) == 0 && *(short *)(&addr->a[2]) == 0 && *(short *)(&addr->a[4]) == 0 ) ; } -int is_broadcast(addr) -struct fddi_addr *addr ; +int is_broadcast(struct fddi_addr *addr) { return(*(u_short *)(&addr->a[0]) == 0xffff && *(u_short *)(&addr->a[2]) == 0xffff && *(u_short *)(&addr->a[4]) == 0xffff ) ; } -int is_individual(addr) -struct fddi_addr *addr ; +int is_individual(struct fddi_addr *addr) { return(!(addr->a[0] & GROUP_ADDR)) ; } -int is_equal(addr1,addr2) -struct fddi_addr *addr1 ; -struct fddi_addr *addr2 ; +int is_equal(struct fddi_addr *addr1, struct fddi_addr *addr2) { return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) && *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) && @@ -1821,9 +1729,7 @@ struct fddi_addr *addr2 ; /* * send ANTC data test frame */ -void fddi_send_antc(smc,dest) -struct s_smc *smc ; -struct fddi_addr *dest ; +void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest) { SK_UNUSED(smc) ; SK_UNUSED(dest) ; @@ -1850,8 +1756,7 @@ struct fddi_addr *dest ; #ifdef DEBUG #define hextoasc(x) "0123456789abcdef"[x] -char *addr_to_string(addr) -struct fddi_addr *addr ; +char *addr_to_string(struct fddi_addr *addr) { int i ; static char string[6*3] = "****" ; @@ -1867,9 +1772,7 @@ struct fddi_addr *addr ; #endif #ifdef AM29K -smt_ifconfig(argc,argv) -int argc ; -char *argv[] ; +smt_ifconfig(int argc, char *argv[]) { if (argc >= 2 && !strcmp(argv[0],"opt_bypass") && !strcmp(argv[1],"yes")) { @@ -1883,9 +1786,7 @@ char *argv[] ; /* * return static mac index */ -static int mac_index(smc,mac) -struct s_smc *smc ; -int mac ; +static int mac_index(struct s_smc *smc, int mac) { SK_UNUSED(mac) ; #ifdef CONCENTRATOR @@ -1899,9 +1800,7 @@ int mac ; /* * return static phy index */ -static int phy_index(smc,phy) -struct s_smc *smc ; -int phy ; +static int phy_index(struct s_smc *smc, int phy) { SK_UNUSED(smc) ; return(phy+1); @@ -1910,9 +1809,7 @@ int phy ; /* * return dynamic mac connection resource index */ -static int mac_con_resource_index(smc,mac) -struct s_smc *smc ; -int mac ; +static int mac_con_resource_index(struct s_smc *smc, int mac) { #ifdef CONCENTRATOR SK_UNUSED(smc) ; @@ -1936,9 +1833,7 @@ int mac ; /* * return dynamic phy connection resource index */ -static int phy_con_resource_index(smc,phy) -struct s_smc *smc ; -int phy ; +static int phy_con_resource_index(struct s_smc *smc, int phy) { #ifdef CONCENTRATOR return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_PHY(phy)))) ; @@ -1960,9 +1855,7 @@ int phy ; } #ifdef CONCENTRATOR -static int entity_to_index(smc,e) -struct s_smc *smc ; -int e ; +static int entity_to_index(struct s_smc *smc, int e) { if (e == ENTITY_MAC) return(mac_index(smc,1)) ; @@ -1972,16 +1865,13 @@ int e ; #endif #ifdef LITTLE_ENDIAN -static int smt_swap_short(s) -u_short s ; +static int smt_swap_short(u_short s) { return(((s>>8)&0xff)|((s&0xff)<<8)) ; } -void smt_swap_para(sm,len,direction) -struct smt_header *sm ; -int len ; -int direction ; /* 0 encode 1 decode */ +void smt_swap_para(struct smt_header *sm, int len, int direction) +/* int direction; 0 encode 1 decode */ { struct smt_para *pa ; const struct smt_pdef *pd ; @@ -2027,10 +1917,7 @@ int direction ; /* 0 encode 1 decode */ } } -static void smt_string_swap(data,format,len) -char *data ; -const char *format ; -int len ; +static void smt_string_swap(char *data, const char *format, int len) { const char *open_paren = 0 ; int x ; @@ -2081,10 +1968,8 @@ int len ; } } #else -void smt_swap_para(sm,len,direction) -struct smt_header *sm ; -int len ; -int direction ; /* 0 encode 1 decode */ +void smt_swap_para(struct smt_header *sm, int len, int direction) +/* int direction; 0 encode 1 decode */ { SK_UNUSED(sm) ; SK_UNUSED(len) ; @@ -2095,11 +1980,7 @@ int direction ; /* 0 encode 1 decode */ /* * PMF actions */ -int smt_action(smc,class,code,index) -struct s_smc *smc ; -int class ; -int code ; -int index ; +int smt_action(struct s_smc *smc, int class, int code, int index) { int event ; int port ; @@ -2190,9 +2071,7 @@ int index ; * set reconnect * end */ -void smt_change_t_neg(smc,tneg) -struct s_smc *smc ; -u_long tneg ; +void smt_change_t_neg(struct s_smc *smc, u_long tneg) { smc->mib.a[PATH0].fddiPATHMaxT_Req = tneg ; @@ -2207,10 +2086,7 @@ u_long tneg ; * canonical conversion of <len> bytes beginning form *data */ #ifdef USE_CAN_ADDR -void hwm_conv_can(smc,data,len) -struct s_smc *smc ; -char *data ; -int len ; +void hwm_conv_can(struct s_smc *smc, char *data, int len) { int i ; @@ -2223,3 +2099,4 @@ int len ; #endif #endif /* no SLIM_SMT */ + diff --git a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c index beaed26b5d19..91fa855e3300 100644 --- a/drivers/net/skfp/smtdef.c +++ b/drivers/net/skfp/smtdef.c @@ -72,13 +72,11 @@ static const char ID_sccs[] = "@(#)smtdef.c 2.53 99/08/11 (C) SK " ; #define DEFAULT_LCT_EXTEND 50 /* Forward declarations */ -extern void smt_reset_defaults (); -static void smt_init_mib (); +void smt_reset_defaults(struct s_smc *smc, int level); +static void smt_init_mib(struct s_smc *smc, int level); +static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper); -static int set_min_max() ; - -void smt_set_defaults(smc) -struct s_smc *smc ; +void smt_set_defaults(struct s_smc *smc) { smt_reset_defaults(smc,0) ; } @@ -86,9 +84,7 @@ struct s_smc *smc ; #define MS2BCLK(x) ((x)*12500L) #define US2BCLK(x) ((x)*1250L) -void smt_reset_defaults(smc,level) -struct s_smc *smc ; -int level ; +void smt_reset_defaults(struct s_smc *smc, int level) { struct smt_config *smt ; int i ; @@ -170,9 +166,7 @@ static const char man_data[32] = /* 01234567890123456789012345678901 */ "xxxSK-NET FDDI SMT 7.3 - V2.8.8" ; -static void smt_init_mib(smc,level) -struct s_smc *smc ; -int level ; +static void smt_init_mib(struct s_smc *smc, int level) { struct fddi_mib *mib ; struct fddi_mib_p *pm ; @@ -292,8 +286,7 @@ int level ; (void) smt_set_mac_opvalues(smc) ; } -int smt_set_mac_opvalues(smc) -struct s_smc *smc ; +int smt_set_mac_opvalues(struct s_smc *smc) { int st ; int st2 ; @@ -318,8 +311,7 @@ struct s_smc *smc ; return(st) ; } -void smt_fixup_mib(smc) -struct s_smc *smc ; +void smt_fixup_mib(struct s_smc *smc) { #ifdef CONCENTRATOR switch (smc->s.sas) { @@ -355,11 +347,7 @@ struct s_smc *smc ; * use mib * NOTE : numbers are negative, negate comparison ! */ -static int set_min_max(maxflag,mib,limit,oper) -int maxflag ; -u_long mib ; -u_long limit ; -u_long *oper ; +static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper) { u_long old ; old = *oper ; @@ -369,3 +357,4 @@ u_long *oper ; *oper = mib ; return(old != *oper) ; } + diff --git a/drivers/net/skfp/smtinit.c b/drivers/net/skfp/smtinit.c index c4b5af9b502b..3c8964ce1837 100644 --- a/drivers/net/skfp/smtinit.c +++ b/drivers/net/skfp/smtinit.c @@ -27,7 +27,7 @@ static const char ID_sccs[] = "@(#)smtinit.c 1.15 97/05/06 (C) SK " ; #endif -extern void init_fddi_driver() ; +void init_fddi_driver(struct s_smc *smc, u_char *mac_addr); /* define global debug variable */ #if defined(DEBUG) && !defined(DEBUG_BRD) @@ -48,8 +48,7 @@ struct smt_debug debug; * Can not be called in smt_reset_defaults, because it is not sure that * the OEM ID is already defined. */ -static void set_oem_spec_val(smc) -struct s_smc *smc ; +static void set_oem_spec_val(struct s_smc *smc) { struct fddi_mib *mib ; @@ -66,9 +65,8 @@ struct s_smc *smc ; /* * Init SMT */ -int init_smt(smc,mac_addr) -struct s_smc *smc ; -u_char *mac_addr ; /* canonical address or NULL */ +int init_smt(struct s_smc *smc, u_char *mac_addr) +/* u_char *mac_addr; canonical address or NULL */ { int p ; @@ -124,3 +122,4 @@ u_char *mac_addr ; /* canonical address or NULL */ return(0) ; } + diff --git a/drivers/net/skfp/smtparse.c b/drivers/net/skfp/smtparse.c index 0b4a2274d055..0be1158ab9a0 100644 --- a/drivers/net/skfp/smtparse.c +++ b/drivers/net/skfp/smtparse.c @@ -82,8 +82,9 @@ static struct s_ptab { /* * local function declarations */ -static u_long parse_num() ; -static int parse_word() ; +static u_long parse_num(int type, char _far *value, char *v, u_long mn, + u_long mx, int scale); +static int parse_word(char *buf, char _far *text); #ifdef SIM #define DB_MAIN(a,b,c) printf(a,b,c) @@ -117,11 +118,8 @@ static int parse_word() ; * * END_MANUAL_ENTRY() */ -int smt_parse_arg(smc,keyword,type,value) -struct s_smc *smc ; -char _far *keyword ; -int type ; -char _far *value ; +int smt_parse_arg(struct s_smc *smc, char _far *keyword, int type, + char _far *value) { char keybuf[MAX_VAL+1]; char valbuf[MAX_VAL+1]; @@ -287,9 +285,7 @@ char _far *value ; return(0) ; } -static int parse_word(buf,text) -char *buf ; -char _far *text ; +static int parse_word(char *buf, char _far *text) { char c ; char *p ; @@ -364,13 +360,8 @@ char _far *text ; return(0) ; } -static u_long parse_num(type,value,v,mn,mx,scale) -int type ; -char _far *value ; -char *v ; -u_long mn ; -u_long mx ; -int scale ; +static u_long parse_num(int type, char _far *value, char *v, u_long mn, + u_long mx, int scale) { u_long x = 0 ; char c ; @@ -473,3 +464,4 @@ main() exit(0) ; } #endif + diff --git a/drivers/net/skfp/smttimer.c b/drivers/net/skfp/smttimer.c index 9d7b71e265c3..a82649b3598d 100644 --- a/drivers/net/skfp/smttimer.c +++ b/drivers/net/skfp/smttimer.c @@ -26,18 +26,9 @@ static const char ID_sccs[] = "@(#)smttimer.c 2.4 97/08/04 (C) SK " ; #endif -/* - * external function declarations - */ -extern u_long hwt_read() ; -extern void hwt_stop() ; -extern void hwt_start() ; - -static void timer_done() ; +static void timer_done(struct s_smc *smc, int restart); - -void smt_timer_init(smc) -struct s_smc *smc ; +void smt_timer_init(struct s_smc *smc) { smc->t.st_queue = 0 ; smc->t.st_fast.tm_active = FALSE ; @@ -45,9 +36,7 @@ struct s_smc *smc ; hwt_init(smc) ; } -void smt_timer_stop(smc,timer) -struct s_smc *smc ; -struct smt_timer *timer ; +void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer) { struct smt_timer **prev ; struct smt_timer *tm ; @@ -70,11 +59,8 @@ struct smt_timer *timer ; } } -void smt_timer_start(smc,timer,time,token) -struct s_smc *smc ; -struct smt_timer *timer ; -u_long time ; -u_long token ; +void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time, + u_long token) { struct smt_timer **prev ; struct smt_timer *tm ; @@ -121,21 +107,17 @@ u_long token ; hwt_start(smc,smc->t.st_queue->tm_delta) ; } -void smt_force_irq(smc) -struct s_smc *smc ; +void smt_force_irq(struct s_smc *smc) { smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); } -void smt_timer_done(smc) -struct s_smc *smc ; +void smt_timer_done(struct s_smc *smc) { timer_done(smc,1) ; } -static void timer_done(smc,restart) -struct s_smc *smc ; -int restart ; +static void timer_done(struct s_smc *smc, int restart) { u_long delta ; struct smt_timer *tm ; @@ -171,3 +153,4 @@ int restart ; if (restart && smc->t.st_queue) hwt_start(smc,smc->t.st_queue->tm_delta) ; } + diff --git a/drivers/net/skfp/srf.c b/drivers/net/skfp/srf.c index ce757a19f361..f5b380b95db6 100644 --- a/drivers/net/skfp/srf.c +++ b/drivers/net/skfp/srf.c @@ -38,10 +38,10 @@ static const char ID_sccs[] = "@(#)srf.c 1.18 97/08/04 (C) SK " ; /* * function declarations */ -static void clear_all_rep() ; -static void clear_reported() ; -static void smt_send_srf() ; -static struct s_srf_evc *smt_get_evc() ; +static void clear_all_rep(struct s_smc *smc); +static void clear_reported(struct s_smc *smc); +static void smt_send_srf(struct s_smc *smc); +static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index); #define MAX_EVCS (sizeof(smc->evcs)/sizeof(smc->evcs[0])) @@ -69,8 +69,7 @@ static const struct evc_init evc_inits[] = { #define MAX_INIT_EVC (sizeof(evc_inits)/sizeof(evc_inits[0])) -void smt_init_evc(smc) -struct s_smc *smc ; +void smt_init_evc(struct s_smc *smc) { struct s_srf_evc *evc ; const struct evc_init *init ; @@ -159,10 +158,7 @@ struct s_smc *smc ; smc->srf.sr_state = SR0_WAIT ; } -static struct s_srf_evc *smt_get_evc(smc,code,index) -struct s_smc *smc ; -int code ; -int index ; +static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index) { int i ; struct s_srf_evc *evc ; @@ -188,11 +184,7 @@ static const char * const srf_names[] = { } ; #endif -void smt_srf_event(smc,code,index,cond) -struct s_smc *smc ; -int code ; -int index ; -int cond ; +void smt_srf_event(struct s_smc *smc, int code, int index, int cond) { struct s_srf_evc *evc ; int cond_asserted = 0 ; @@ -340,8 +332,7 @@ int cond ; } } -static void clear_all_rep(smc) -struct s_smc *smc ; +static void clear_all_rep(struct s_smc *smc) { struct s_srf_evc *evc ; int i ; @@ -354,8 +345,7 @@ struct s_smc *smc ; smc->srf.any_report = FALSE ; } -static void clear_reported(smc) -struct s_smc *smc ; +static void clear_reported(struct s_smc *smc) { struct s_srf_evc *evc ; int i ; @@ -375,13 +365,10 @@ struct s_smc *smc ; } } -extern SMbuf *smt_build_frame() ; - /* * build and send SMT SRF frame */ -static void smt_send_srf(smc) -struct s_smc *smc ; +static void smt_send_srf(struct s_smc *smc) { struct smt_header *smt ; @@ -439,3 +426,4 @@ struct s_smc *smc ; #endif /* no BOOT */ #endif /* no SLIM_SMT */ + diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index a82734927305..8ee249a3871e 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -96,16 +96,51 @@ static const char version[] = #define USE_32_BIT 1 #endif +#if defined(__H8300H__) || defined(__H8300S__) +#define NO_AUTOPROBE +#undef insl +#undef outsl +#define insl(a,b,l) io_insl_noswap(a,b,l) +#define outsl(a,b,l) io_outsl_noswap(a,b,l) +#endif + /* .the SMC9194 can be at any of the following port addresses. To change, .for a slightly different card, you can add it to the array. Keep in .mind that the array must end in zero. */ -static unsigned int smc_portlist[] __initdata = { - 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, - 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0 + +struct devlist { + unsigned int port; + unsigned int irq; }; +#if defined(CONFIG_H8S_EDOSK2674) +static struct devlist smc_devlist[] __initdata = { + {.port = 0xf80000, .irq = 16}, + {.port = 0, .irq = 0 }, +}; +#else +static struct devlist smc_devlist[] __initdata = { + {.port = 0x200, .irq = 0}, + {.port = 0x220, .irq = 0}, + {.port = 0x240, .irq = 0}, + {.port = 0x260, .irq = 0}, + {.port = 0x280, .irq = 0}, + {.port = 0x2A0, .irq = 0}, + {.port = 0x2C0, .irq = 0}, + {.port = 0x2E0, .irq = 0}, + {.port = 0x300, .irq = 0}, + {.port = 0x320, .irq = 0}, + {.port = 0x340, .irq = 0}, + {.port = 0x360, .irq = 0}, + {.port = 0x380, .irq = 0}, + {.port = 0x3A0, .irq = 0}, + {.port = 0x3C0, .irq = 0}, + {.port = 0x3E0, .irq = 0}, + {.port = 0, .irq = 0}, +}; +#endif /* . Wait time for memory to be free. This probably shouldn't be . tuned that much, as waiting for this means nothing else happens @@ -468,7 +503,7 @@ static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev ) { struct smc_local *lp = netdev_priv(dev); - unsigned short ioaddr = dev->base_addr; + unsigned int ioaddr = dev->base_addr; word length; unsigned short numPages; word time_out; @@ -582,7 +617,7 @@ static void smc_hardware_send_packet( struct net_device * dev ) byte packet_no; struct sk_buff * skb = lp->saved_skb; word length; - unsigned short ioaddr; + unsigned int ioaddr; byte * buf; ioaddr = dev->base_addr; @@ -637,7 +672,11 @@ static void smc_hardware_send_packet( struct net_device * dev ) #ifdef USE_32_BIT if ( length & 0x2 ) { outsl(ioaddr + DATA_1, buf, length >> 2 ); +#if !defined(__H8300H__) && !defined(__H8300S__) outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1); +#else + ctrl_outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1); +#endif } else outsl(ioaddr + DATA_1, buf, length >> 2 ); @@ -693,9 +732,12 @@ static int ifport; struct net_device * __init smc_init(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct smc_local)); - unsigned *port; + static struct devlist *smcdev = smc_devlist; int err = 0; +#ifndef NO_AUTOPROBE + smcdev = smc_devlist; +#endif if (!dev) return ERR_PTR(-ENODEV); @@ -713,11 +755,11 @@ struct net_device * __init smc_init(int unit) } else if (io != 0) { /* Don't probe at all. */ err = -ENXIO; } else { - for (port = smc_portlist; *port; port++) { - if (smc_probe(dev, *port) == 0) + for (;smcdev->port; smcdev++) { + if (smc_probe(dev, smcdev->port) == 0) break; } - if (!*port) + if (!smcdev->port) err = -ENODEV; } if (err) @@ -743,6 +785,7 @@ out: */ int __init smc_findirq( int ioaddr ) { +#ifndef NO_AUTOPROBE int timeout = 20; unsigned long cookie; @@ -797,6 +840,14 @@ int __init smc_findirq( int ioaddr ) /* and return what I found */ return probe_irq_off(cookie); +#else /* NO_AUTOPROBE */ + struct devlist *smcdev; + for (smcdev = smc_devlist; smcdev->port; smcdev++) { + if (smcdev->port == ioaddr) + return smcdev->irq; + } + return 0; +#endif } /*---------------------------------------------------------------------- @@ -865,6 +916,7 @@ static int __init smc_probe(struct net_device *dev, int ioaddr) retval = -ENODEV; goto err_out; } +#if !defined(CONFIG_H8S_EDOSK2674) /* well, we've already written once, so hopefully another time won't hurt. This time, I need to switch the bank register to bank 1, so I can access the base address register */ @@ -879,6 +931,10 @@ static int __init smc_probe(struct net_device *dev, int ioaddr) retval = -ENODEV; goto err_out; } +#else + (void)base_address_register; /* Warning suppression */ +#endif + /* check if the revision register is something that I recognize. These might need to be added to later, as future revisions diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index c56a4baaf0ac..6d2c87dcae1c 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2922,7 +2922,8 @@ static int is_quattro_p(struct pci_dev *pdev) struct list_head *tmp; int n_hmes; - if (busdev->vendor != PCI_VENDOR_ID_DEC || + if (busdev == NULL || + busdev->vendor != PCI_VENDOR_ID_DEC || busdev->device != PCI_DEVICE_ID_DEC_21153) return 0; diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index cd494d3d1c12..952ef81775fb 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1717,7 +1717,7 @@ tc35815_killall(void) } static struct pci_driver tc35815_driver = { - .name =TC35815_MODULE_NAME, + .name = TC35815_MODULE_NAME, .probe = tc35815_probe, .remove = NULL, .id_table = tc35815_pci_tbl, diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 4d5844f75b5f..03eeaebbf5d1 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -248,7 +248,7 @@ config WANXL config WANXL_BUILD_FIRMWARE bool "rebuild wanXL firmware" - depends on WANXL + depends on WANXL && !PREVENT_FIRMWARE_BUILD help Allows you to rebuild firmware run by the QUICC processor. It requires as68k, ld68k and hexdump programs. diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index d805ac786778..543ac790072b 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -1636,7 +1636,7 @@ fst_intr(int irq, void *dev_id, struct pt_regs *regs) */ dbg(DBG_TX, "Tx underflow port %d\n", port->index); hdlc_stats(port_to_dev(port))->tx_errors++; - hdlc_stats(port_to_dev(port))->tx_fifo_errors; + hdlc_stats(port_to_dev(port))->tx_fifo_errors++; dbg(DBG_ASS, "Tx underflow on card %d port %d\n", card->card_no, port->index); break; diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 57ef2ac7297a..302654d7fb71 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1209,6 +1209,7 @@ struct airo_info { SsidRid *SSID; APListRid *APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE + u32 pci_state[16]; }; static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, @@ -1963,7 +1964,7 @@ static int mpi_send_packet (struct net_device *dev) if ((skb = skb_dequeue(&ai->txq)) == 0) { printk (KERN_ERR - "airo_mpi: %s: Dequeue'd zero in send_packet()\n", + "airo: %s: Dequeue'd zero in send_packet()\n", __FUNCTION__); return 0; } @@ -2745,6 +2746,9 @@ struct net_device *_init_airo_card( unsigned short irq, int port, SET_NETDEV_DEV(dev, &pci->dev); } + if (test_bit(FLAG_MPI,&ai->flags)) + reset_card (dev, 1); + rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev ); if (rc) { printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc ); @@ -4047,7 +4051,8 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, Resp rsp; if (test_bit(FLAG_ENABLED, &ai->flags)) - printk(KERN_ERR "%s: MAC should be disabled (rid=%d)\n", + printk(KERN_ERR + "%s: MAC should be disabled (rid=%04x)\n", __FUNCTION__, rid); memset(&cmd, 0, sizeof(cmd)); memset(&rsp, 0, sizeof(rsp)); @@ -4500,6 +4505,8 @@ static ssize_t proc_read( struct file *file, len = priv->readlen - pos; if (copy_to_user(buffer, priv->rbuffer + pos, len)) return -EFAULT; + if (pos + len > priv->writelen) + priv->writelen = pos + len; *offset = pos + len; return len; } @@ -4527,6 +4534,8 @@ static ssize_t proc_write( struct file *file, len = priv->maxwritelen - pos; if (copy_from_user(priv->wbuffer + pos, buffer, len)) return -EFAULT; + if ( pos + len > priv->writelen ) + priv->writelen = len + file->f_pos; *offset = pos + len; return len; } @@ -5470,9 +5479,6 @@ static int airo_pci_suspend(struct pci_dev *pdev, u32 state) Cmd cmd; Resp rsp; - printk(KERN_DEBUG "%s: airo_mpi entering sleep mode (state=%d)\n", - dev->name, state); - if ((ai->APList == NULL) && (ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL) return -ENOMEM; @@ -5490,7 +5496,10 @@ static int airo_pci_suspend(struct pci_dev *pdev, u32 state) ai->power = state; cmd.cmd=HOSTSLEEP; issuecommand(ai, &cmd, &rsp); - return 0; + + pci_enable_wake(pdev, state, 1); + pci_save_state(pdev, ai->pci_state); + return pci_set_power_state(pdev, state); } static int airo_pci_resume(struct pci_dev *pdev) @@ -5499,12 +5508,12 @@ static int airo_pci_resume(struct pci_dev *pdev) struct airo_info *ai = dev->priv; Resp rsp; - printk(KERN_DEBUG "%s: airo_mpi waking up\n", dev->name); - - if (!ai->power) - return 0; + pci_set_power_state(pdev, 0); + pci_restore_state(pdev, ai->pci_state); + pci_enable_wake(pdev, ai->power, 0); if (ai->power > 1) { + reset_card(dev, 0); mpi_init_descriptors(ai); setup_card(ai, dev->dev_addr, 0); clear_bit(FLAG_RADIO_OFF, &ai->flags); @@ -7166,6 +7175,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { unsigned char *iobuf; int len; struct airo_info *ai = dev->priv; + Resp rsp; if (test_bit(FLAG_FLASHING, &ai->flags)) return -EIO; @@ -7173,8 +7183,11 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { switch(comp->command) { case AIROGCAP: ridcode = RID_CAPABILITIES; break; - case AIROGCFG: writeConfigRid (ai, 1); - ridcode = RID_CONFIG; break; + case AIROGCFG: ridcode = RID_CONFIG; + disable_MAC (ai, 1); + writeConfigRid (ai, 1); + enable_MAC (ai, &rsp, 1); + break; case AIROGSLIST: ridcode = RID_SSID; break; case AIROGVLIST: ridcode = RID_APLIST; break; case AIROGDRVNAM: ridcode = RID_DRVNAME; break; @@ -7562,6 +7575,11 @@ int flashrestart(struct airo_info *ai,struct net_device *dev){ set_current_state (TASK_UNINTERRUPTIBLE); schedule_timeout (HZ); /* Added 12/7/00 */ clear_bit (FLAG_FLASHING, &ai->flags); + if (test_bit(FLAG_MPI, &ai->flags)) { + status = mpi_init_descriptors(ai); + if (status != SUCCESS) + return status; + } status = setup_card(ai, dev->dev_addr, 1); if (!test_bit(FLAG_MPI,&ai->flags)) diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 11af4300ae8f..8161a1c00949 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -1519,7 +1519,8 @@ static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw) static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) { - printk(KERN_WARNING "%s: Information frame lost.\n", dev->name); + if (net_ratelimit()) + printk(KERN_WARNING "%s: Information frame lost.\n", dev->name); } static void print_linkstatus(struct net_device *dev, u16 status) diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 120569b1f12e..57de3c08f4e0 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -65,7 +65,6 @@ #include "cirrus.h" #include "vg468.h" #include "ricoh.h" -#include "o2micro.h" #ifdef DEBUG static const char version[] = diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h index f4ccd8454bb0..adbe8a724e0a 100644 --- a/drivers/pcmcia/o2micro.h +++ b/drivers/pcmcia/o2micro.h @@ -120,4 +120,30 @@ #define O2_MODE_E_LED_OUT 0x08 #define O2_MODE_E_SKTA_ACTV 0x10 +static int o2micro_override(struct yenta_socket *socket) +{ + /* + * 'reserved' register at 0x94/D4. chaning it to 0xCA (8 bit) enables + * read prefetching which for example makes the RME Hammerfall DSP + * working. for some bridges it is at 0x94, for others at 0xD4. it's + * ok to write to both registers on all O2 bridges. + * from Eric Still, 02Micro. + */ + if (PCI_FUNC(socket->dev->devfn) == 0) { + config_writeb(socket, 0x94, 0xCA); + config_writeb(socket, 0xD4, 0xCA); + } + + return 0; +} + +static void o2micro_restore_state(struct yenta_socket *socket) +{ + /* + * as long as read prefetch is the only thing in + * o2micro_override, it's safe to call it from here + */ + o2micro_override(socket); +} + #endif /* _LINUX_O2MICRO_H */ diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 767b2c1a23b4..10a0166d50b5 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -668,6 +668,7 @@ static struct pccard_operations yenta_socket_operations = { #include "ti113x.h" #include "ricoh.h" #include "topic.h" +#include "o2micro.h" enum { CARDBUS_TYPE_DEFAULT = -1, @@ -676,7 +677,8 @@ enum { CARDBUS_TYPE_TI12XX, CARDBUS_TYPE_TI1250, CARDBUS_TYPE_RICOH, - CARDBUS_TYPE_TOPIC97 + CARDBUS_TYPE_TOPIC97, + CARDBUS_TYPE_O2MICRO, }; /* @@ -716,6 +718,10 @@ struct cardbus_type cardbus_type[] = { [CARDBUS_TYPE_TOPIC97] = { .override = topic97_override, }, + [CARDBUS_TYPE_O2MICRO] = { + .override = o2micro_override, + .restore_state = o2micro_restore_state, + }, }; @@ -1100,6 +1106,8 @@ static struct pci_device_id yenta_table [] = { CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), + CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO), + /* match any cardbus bridge */ CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), { /* all zeroes */ } diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 082e1b552cad..e83bb0728a37 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -571,14 +571,9 @@ serial_pxa_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; - if (state) { - /* sleep */ - CKEN &= ~up->cken; - } else { - /* wake */ - CKEN |= up->cken; + pxa_set_cken(up->cken, !state); + if (!state) udelay(1); - } } static void serial_pxa_release_port(struct uart_port *port) diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 4ad4d2f7fd95..a74d64c00a9c 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -1406,7 +1406,7 @@ static void udc_disable(struct pxa2xx_udc *dev) #ifdef CONFIG_ARCH_PXA /* Disable clock for USB device */ - CKEN &= ~CKEN11_USB; + pxa_set_cken(CKEN11_USB, 0); #endif ep0_idle (dev); @@ -1452,7 +1452,7 @@ static void udc_enable (struct pxa2xx_udc *dev) #ifdef CONFIG_ARCH_PXA /* Enable clock for USB device */ - CKEN |= CKEN11_USB; + pxa_set_cken(CKEN11_USB, 1); #endif /* try to clear these bits before we enable the udc */ diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 7ded3f7c9dd5..05d8ad2a61c1 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -1016,7 +1016,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) struct pxafb_mach_info *inf = dev->platform_data; /* Alloc the pxafb_info and pseudo_palette in one step */ - fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 17, GFP_KERNEL); + fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL); if (!fbi) return NULL; @@ -1237,7 +1237,6 @@ int __init pxafb_probe(struct device *dev) { struct pxafb_info *fbi; struct pxafb_mach_info *inf; - unsigned long flags; int ret; dev_dbg(dev, "pxafb_probe\n"); @@ -1301,9 +1300,7 @@ int __init pxafb_probe(struct device *dev) goto failed; } /* enable LCD controller clock */ - local_irq_save(flags); - CKEN |= CKEN16_LCD; - local_irq_restore(flags); + pxa_set_cken(CKEN16_LCD, 1); ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); if (ret) { diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 4006cf72e596..f3aa37ea0596 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1101,7 +1101,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) */ u8 *cursorbase = (u8 *) info->cursor.image.data; char *bitmap = (char *)cursor->image.data; - char *mask = cursor->mask; + const char *mask = cursor->mask; int i, j, k, h = 0; for (i = 0; i < 64; i++) { diff --git a/fs/Kconfig b/fs/Kconfig index 27c9018674e8..f0502fffa128 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -672,6 +672,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 @@ -1562,7 +1581,7 @@ config SMB_NLS_REMOTE smbmount from samba 2.2.0 or later supports this. config CIFS - tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)(EXPERIMENTAL)" + tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)" depends on INET select NLS help @@ -1592,7 +1611,16 @@ config CIFS_STATS depends on CIFS help Enabling this option will cause statistics for each server share - mounted by the cifs client to be displayed in /proc/fs/cifs/DebugData + mounted by the cifs client to be displayed in /proc/fs/cifs/Stats + +config CIFS_POSIX + bool "CIFS POSIX Extensions (EXPERIMENTAL)" + depends on CIFS + help + Enabling this option will cause the cifs client to attempt to + negotiate a newer dialect with servers, such as Samba 3.0.5 + or later, that optionally can handle more POSIX like (rather + than Windows like) file behavior. If unsure, say N. config NCP_FS tristate "NCP file system support (to mount NetWare volumes)" diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index b5d1aabf1c05..ddd53ec12a92 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -458,7 +458,6 @@ affs_error(struct super_block *sb, const char *function, const char *fmt, ...) if (!(sb->s_flags & MS_RDONLY)) printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n"); sb->s_flags |= MS_RDONLY; - AFFS_SB(sb)->s_flags |= SF_READONLY; /* Don't allow to remount rw */ } void diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index 095ef77a407e..93d32d18e97f 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c @@ -272,8 +272,7 @@ err_full: return 0; } -int -affs_init_bitmap(struct super_block *sb) +int affs_init_bitmap(struct super_block *sb, int *flags) { struct affs_bm_info *bm; struct buffer_head *bmap_bh = NULL, *bh = NULL; @@ -282,13 +281,13 @@ affs_init_bitmap(struct super_block *sb) int i, res = 0; struct affs_sb_info *sbi = AFFS_SB(sb); - if (sb->s_flags & MS_RDONLY) + if (*flags & MS_RDONLY) return 0; if (!AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag) { printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n", sb->s_id); - sb->s_flags |= MS_RDONLY; + *flags |= MS_RDONLY; return 0; } @@ -301,7 +300,7 @@ affs_init_bitmap(struct super_block *sb) bm = sbi->s_bitmap = kmalloc(size, GFP_KERNEL); if (!sbi->s_bitmap) { printk(KERN_ERR "AFFS: Bitmap allocation failed\n"); - return 1; + return -ENOMEM; } memset(sbi->s_bitmap, 0, size); @@ -316,13 +315,13 @@ affs_init_bitmap(struct super_block *sb) bh = affs_bread(sb, bm->bm_key); if (!bh) { printk(KERN_ERR "AFFS: Cannot read bitmap\n"); - res = 1; + res = -EIO; goto out; } if (affs_checksum_block(sb, bh)) { printk(KERN_WARNING "AFFS: Bitmap %u invalid - mounting %s read only.\n", bm->bm_key, sb->s_id); - sb->s_flags |= MS_RDONLY; + *flags |= MS_RDONLY; goto out; } pr_debug("AFFS: read bitmap block %d: %d\n", blk, bm->bm_key); @@ -338,7 +337,7 @@ affs_init_bitmap(struct super_block *sb) bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk])); if (!bmap_bh) { printk(KERN_ERR "AFFS: Cannot read bitmap extension\n"); - res = 1; + res = -EIO; goto out; } bmap_blk = (u32 *)bmap_bh->b_data; @@ -383,3 +382,17 @@ out: affs_brelse(bmap_bh); return res; } + +void affs_free_bitmap(struct super_block *sb) +{ + struct affs_sb_info *sbi = AFFS_SB(sb); + + if (!sbi->s_bitmap) + return; + + affs_brelse(sbi->s_bmap_bh); + sbi->s_bmap_bh = NULL; + sbi->s_last_bmap = ~0; + kfree(sbi->s_bitmap); + sbi->s_bitmap = NULL; +} diff --git a/fs/affs/super.c b/fs/affs/super.c index ad83ec3a9a45..f4ebbd27ef1b 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -51,10 +51,9 @@ affs_put_super(struct super_block *sb) mark_buffer_dirty(sbi->s_root_bh); } - affs_brelse(sbi->s_bmap_bh); if (sbi->s_prefix) kfree(sbi->s_prefix); - kfree(sbi->s_bitmap); + affs_free_bitmap(sb); affs_brelse(sbi->s_root_bh); kfree(sbi); sb->s_fs_info = NULL; @@ -288,6 +287,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) gid_t gid; int reserved; unsigned long mount_flags; + int tmp_flags; /* fix remount prototype... */ pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options"); @@ -399,7 +399,6 @@ got_root: printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", sb->s_id); sb->s_flags |= MS_RDONLY; - sbi->s_flags |= SF_READONLY; } switch (chksum) { case MUFS_FS: @@ -455,8 +454,10 @@ got_root: sbi->s_root_bh = root_bh; /* N.B. after this point s_root_bh must be released */ - if (affs_init_bitmap(sb)) + tmp_flags = sb->s_flags; + if (affs_init_bitmap(sb, &tmp_flags)) goto out_error; + sb->s_flags = tmp_flags; /* set up enough so that it can read an inode */ @@ -498,7 +499,7 @@ affs_remount(struct super_block *sb, int *flags, char *data) int reserved; int root_block; unsigned long mount_flags; - unsigned long read_only = sbi->s_flags & SF_READONLY; + int res = 0; pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data); @@ -507,7 +508,7 @@ affs_remount(struct super_block *sb, int *flags, char *data) if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block, &blocksize,&sbi->s_prefix,sbi->s_volume,&mount_flags)) return -EINVAL; - sbi->s_flags = mount_flags | read_only; + sbi->s_flags = mount_flags; sbi->s_mode = mode; sbi->s_uid = uid; sbi->s_gid = gid; @@ -518,14 +519,11 @@ affs_remount(struct super_block *sb, int *flags, char *data) sb->s_dirt = 1; while (sb->s_dirt) affs_write_super(sb); - sb->s_flags |= MS_RDONLY; - } else if (!(sbi->s_flags & SF_READONLY)) { - sb->s_flags &= ~MS_RDONLY; - } else { - affs_warning(sb,"remount","Cannot remount fs read/write because of errors"); - return -EINVAL; - } - return 0; + affs_free_bitmap(sb); + } else + res = affs_init_bitmap(sb, flags); + + return res; } static int @@ -116,6 +116,8 @@ inline void bio_init(struct bio *bio) bio->bi_idx = 0; bio->bi_phys_segments = 0; bio->bi_hw_segments = 0; + bio->bi_hw_front_size = 0; + bio->bi_hw_back_size = 0; bio->bi_size = 0; bio->bi_max_vecs = 0; bio->bi_end_io = NULL; @@ -304,14 +306,15 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page * make this too complex. */ - while (bio_phys_segments(q, bio) >= q->max_phys_segments - || bio_hw_segments(q, bio) >= q->max_hw_segments) { + while (bio->bi_phys_segments >= q->max_phys_segments + || bio->bi_hw_segments >= q->max_hw_segments + || BIOVEC_VIRT_OVERSIZE(bio->bi_size)) { if (retried_segments) return 0; - bio->bi_flags &= ~(1 << BIO_SEG_VALID); retried_segments = 1; + blk_recount_segments(q, bio); } /* @@ -341,6 +344,11 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page } } + /* If we may be able to merge these biovecs, force a recount */ + if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec) || + BIOVEC_VIRT_MERGEABLE(bvec-1, bvec))) + bio->bi_flags &= ~(1 << BIO_SEG_VALID); + bio->bi_vcnt++; bio->bi_phys_segments++; bio->bi_hw_segments++; diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS index ac239020fbc7..43a7b6534506 100644 --- a/fs/cifs/AUTHORS +++ b/fs/cifs/AUTHORS @@ -31,7 +31,7 @@ Thanks to those in the community who have submitted detailed bug reports and debug of problems they have found: Jochen Dolze, David Blaine, Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori, Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, -Olaf Kirch, Kieron Briggs and others. +Olaf Kirch, Kieron Briggs, Nick Millington and others. And thanks to the IBM LTC and Power test teams and SuSE testers for finding multiple bugs during excellent stress test runs. diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index cae2bfb9991f..2214ae4f9a7c 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,9 +1,21 @@ +Version 1.19 +------------ +Fix /proc/fs/cifs/Stats and DebugData display to handle larger +amounts of return data. Properly limit requests to MAX_REQ (50 +is the usual maximum active multiplex SMB/CIFS requests per server). +Do not kill cifsd (and thus hurt the other SMB session) when more than one +session to the same server (but with different userids) exists and one +of the two user's smb sessions is being removed while leaving the other. + + Version 1.18 ------------ Do not rename hardlinked files (since that should be a noop). Flush cached write behind data when reopening a file after session abend, except when already in write. Grab per socket sem during reconnect -to avoid oops in sendmsg if overlapping with reconnect. +to avoid oops in sendmsg if overlapping with reconnect. Do not +reset cached inode file size on readdir for files open for write on +client. Version 1.17 diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 2c3d9a867216..d3829b1c8629 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -62,12 +62,17 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, int count, int *eof, void *data) { struct list_head *tmp; + struct list_head *tmp1; + struct mid_q_entry * mid_entry; struct cifsSesInfo *ses; struct cifsTconInfo *tcon; int i; int length = 0; - char *buf_start = buf; + char * original_buf = buf; + *beginBuffer = buf + offset; + + length = sprintf(buf, "Display Internal CIFS Data Structures for Debugging\n" @@ -94,7 +99,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ses->server->secMode, atomic_read(&ses->server->inFlight)); - /* length = sprintf(buf, "\nMIDs: \n"); + length = sprintf(buf, "\nMIDs: \n"); buf += length; spin_lock(&GlobalMid_Lock); @@ -103,11 +108,11 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, mid_q_entry, qhead); if(mid_entry) { - length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk); + length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid); buf += length; } } - spin_unlock(&GlobalMid_Lock); */ + spin_unlock(&GlobalMid_Lock); } } @@ -152,19 +157,22 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, length = sprintf(buf, "\n"); buf += length; - *eof = 1; /* BB add code to dump additional info such as TCP session info now */ - /* - if (offset >= (buf - buf_start)) - { - *beginBuffer = buf; - return 0; - } - *beginBuffer = buf + offset; - if ((buf - buf_start - offset) > count) - return count; - else */ - return (buf - buf_start - offset); + /* Now calculate total size of returned data */ + length = buf - original_buf; + + if(offset + count >= length) + *eof = 1; + if(length < offset) { + *eof = 1; + return 0; + } else { + length = length - offset; + } + if (length > count) + length = count; + + return length; } int @@ -183,12 +191,14 @@ cifs_total_xid_read(char *buf, char **beginBuffer, off_t offset, #ifdef CONFIG_CIFS_STATS int cifs_stats_read(char *buf, char **beginBuffer, off_t offset, - int length, int *eof, void *data) + int count, int *eof, void *data) { - int item_length,i; + int item_length,i,length; struct list_head *tmp; struct cifsTconInfo *tcon; + *beginBuffer = buf + offset; + length = sprintf(buf, "Resources in use\nCIFS Session: %d\n", sesInfoAllocCount.counter); @@ -235,10 +245,12 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, atomic_read(&tcon->num_reads), (long long)(tcon->bytes_read)); buf += item_length; + length += item_length; item_length = sprintf(buf,"\nWrites: %d Bytes: %lld", atomic_read(&tcon->num_writes), (long long)(tcon->bytes_written)); buf += item_length; + length += item_length; item_length = sprintf(buf, "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d", atomic_read(&tcon->num_opens), @@ -247,10 +259,29 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, atomic_read(&tcon->num_rmdirs)); buf += item_length; length += item_length; + item_length = sprintf(buf, + "\nRenames: %d T2 Renames %d", + atomic_read(&tcon->num_renames), + atomic_read(&tcon->num_t2renames)); + buf += item_length; + length += item_length; } read_unlock(&GlobalSMBSeslock); + buf += sprintf(buf,"\n"); + length++; + if(offset + count >= length) + *eof = 1; + if(length < offset) { + *eof = 1; + return 0; + } else { + length = length - offset; + } + if (length > count) + length = count; + return length; } #endif diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index b8be30c09099..ea0d5b82d70d 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); -#define CIFS_VERSION "1.18" +#define CIFS_VERSION "1.19" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 427d9c9d5636..cfbfac7a74b6 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -211,6 +211,8 @@ struct cifsTconInfo { atomic_t num_deletes; atomic_t num_mkdirs; atomic_t num_rmdirs; + atomic_t num_renames; + atomic_t num_t2renames; __u64 bytes_read; __u64 bytes_written; spinlock_t stat_lock; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 420742abb8de..671517645a34 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -387,6 +387,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) spin_lock(&GlobalMid_Lock); ses->server->tcpStatus = CifsExiting; spin_unlock(&GlobalMid_Lock); + rc = -ESHUTDOWN; } } if (pSMB) @@ -819,14 +820,20 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, pSMB->AndXCommand = 0xFF; /* none */ pSMB->Fid = smb_file_id; /* netfid stays le */ - pSMB->Locks[0].Pid = cpu_to_le16(current->tgid); - temp = cpu_to_le64(len); - pSMB->Locks[0].LengthLow = (__u32)(len & 0xFFFFFFFF); - pSMB->Locks[0].LengthHigh = (__u32)(len>>32); - temp = cpu_to_le64(offset); - pSMB->Locks[0].OffsetLow = (__u32)(offset & 0xFFFFFFFF); - pSMB->Locks[0].OffsetHigh = (__u32)(offset>>32); - pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE); + if(numLock != 0) { + pSMB->Locks[0].Pid = cpu_to_le16(current->tgid); + /* BB where to store pid high? */ + temp = cpu_to_le64(len); + pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF); + pSMB->Locks[0].LengthHigh = (__u32)(temp>>32); + temp = cpu_to_le64(offset); + pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF); + pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32); + pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE); + } else { + /* oplock break */ + pSMB->ByteCount = 0; + } pSMB->hdr.smb_buf_length += pSMB->ByteCount; pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); @@ -941,7 +948,14 @@ renameRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Send error in rename = %d", rc)); + } + +#ifdef CONFIG_CIFS_STATS + else { + atomic_inc(&tcon->num_renames); } +#endif + if (pSMB) cifs_buf_release(pSMB); @@ -1017,7 +1031,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, if (rc) { cFYI(1,("Send error in Rename (by file handle) = %d", rc)); } - +#ifdef CONFIG_CIFS_STATS + else { + atomic_inc(&pTcon->num_t2renames); + } +#endif if (pSMB) cifs_buf_release(pSMB); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index befbff5d62aa..d12aaf9438e8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -175,7 +175,7 @@ cifs_reconnect(struct TCP_Server_Info *server) if(server->tcpStatus != CifsExiting) server->tcpStatus = CifsGood; spin_unlock(&GlobalMid_Lock); - atomic_set(&server->inFlight,0); + /* atomic_set(&server->inFlight,0);*/ wake_up(&server->response_q); } } @@ -453,7 +453,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) spin_unlock(&GlobalMid_Lock); read_unlock(&GlobalSMBSeslock); set_current_state(TASK_INTERRUPTIBLE); - /* 1/8th of sec should be more than enough time for them to exit */ + /* 1/8th of sec is more than enough time for them to exit */ schedule_timeout(HZ/8); } @@ -468,7 +468,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } kfree(server); - cFYI(1, ("About to exit from demultiplex thread")); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/4); return 0; } @@ -2769,6 +2770,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) int rc = 0; int xid; struct cifsSesInfo *ses = NULL; + struct task_struct *cifsd_task; xid = GetXid(); @@ -2781,19 +2783,25 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) } tconInfoFree(cifs_sb->tcon); if ((ses) && (ses->server)) { + /* save off task so we do not refer to ses later */ + cifsd_task = ses->server->tsk; cFYI(1, ("About to do SMBLogoff ")); rc = CIFSSMBLogoff(xid, ses); if (rc == -EBUSY) { FreeXid(xid); return 0; - } - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 4); /* give captive thread time to exit */ - if((ses->server) && (ses->server->ssocket)) { - cFYI(1,("Waking up socket by sending it signal ")); - send_sig(SIGKILL,ses->server->tsk,1); - } + } else if (rc == -ESHUTDOWN) { + /* should we add wake_up_all(&server->request_q); + and add a check in the check inFlight loop + for the session ending */ + set_current_state(TASK_INTERRUPTIBLE); + /* give captive thread time to exit */ + schedule_timeout(HZ / 4); + cFYI(1,("Waking up socket by sending it signal")); + send_sig(SIGKILL,cifsd_task,1); + rc = 0; + } /* else - we have an smb session + left on this socket do not kill cifsd */ } else cFYI(1, ("No session or bad tcon")); } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 7d0ac5104486..c8fbd381eba9 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -588,9 +588,10 @@ cifs_write(struct file * file, const char *write_data, if(file->f_dentry == NULL) return -EBADF; - xid = GetXid(); - cifs_sb = CIFS_SB(file->f_dentry->d_sb); + if(cifs_sb == NULL) { + return -EBADF; + } pTcon = cifs_sb->tcon; /*cFYI(1, @@ -598,11 +599,12 @@ cifs_write(struct file * file, const char *write_data, *poffset, file->f_dentry->d_name.name)); */ if (file->private_data == NULL) { - FreeXid(xid); return -EBADF; + } else { + open_file = (struct cifsFileInfo *) file->private_data; } - open_file = (struct cifsFileInfo *) file->private_data; - + + xid = GetXid(); if(file->f_dentry->d_inode == NULL) { FreeXid(xid); return -EBADF; @@ -620,10 +622,22 @@ cifs_write(struct file * file, const char *write_data, if(file->private_data == NULL) { /* file has been closed on us */ FreeXid(xid); + /* if we have gotten here we have written some data + and blocked, and the file has been freed on us + while we blocked so return what we managed to write */ return total_written; + } + open_file = (struct cifsFileInfo *) file->private_data; + if(open_file->closePend) { + FreeXid(xid); + if(total_written) + return total_written; + else + return -EBADF; } - if ((open_file->invalidHandle) && (!open_file->closePend)) { - if((file->f_dentry == NULL) || (file->f_dentry->d_inode == NULL)) { + if (open_file->invalidHandle) { + if((file->f_dentry == NULL) || + (file->f_dentry->d_inode == NULL)) { FreeXid(xid); return total_written; } diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 3668ab00b3ef..821c1711d597 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -200,23 +200,35 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, } /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ - - /* can not count locking commands against the total since - they are allowed to block on server */ - if(long_op < 3) { - /* update # of requests on the wire to this server */ - atomic_inc(&ses->server->inFlight); - } - - if(atomic_read(&ses->server->inFlight) > CIFS_MAX_REQ) { - wait_event(ses->server->request_q,atomic_read(&ses->server->inFlight) <= CIFS_MAX_REQ); + to the same server. We may make this configurable later or + use ses->maxReq */ + if(long_op == -1) { + /* oplock breaks must not be held up */ + atomic_inc(&ses->server->inFlight); + } else { + spin_lock(&GlobalMid_Lock); + while(1) { + if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){ + spin_unlock(&GlobalMid_Lock); + wait_event(ses->server->request_q, + atomic_read(&ses->server->inFlight) + < CIFS_MAX_REQ); + spin_lock(&GlobalMid_Lock); + } else { + /* can not count locking commands against total since + they are allowed to block on server */ + if(long_op < 3) { + /* update # of requests on the wire to server */ + atomic_inc(&ses->server->inFlight); + } + spin_unlock(&GlobalMid_Lock); + break; + } + } } - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ down(&ses->server->tcpSem); diff --git a/fs/dcache.c b/fs/dcache.c index 613ff66dacde..4c632e1261dc 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -30,6 +30,7 @@ #include <linux/security.h> #include <linux/seqlock.h> #include <linux/swap.h> +#include <linux/bootmem.h> #define DCACHE_PARANOIA 1 /* #define DCACHE_DEBUG 1 */ @@ -1561,13 +1562,25 @@ static int __init set_dhash_entries(char *str) } __setup("dhash_entries=", set_dhash_entries); -static void __init dcache_init(unsigned long mempages) +static void __init dcache_init_early(void) { - struct hlist_head *d; - unsigned long order; - unsigned int nr_hash; - int i; + int loop; + + dentry_hashtable = + alloc_large_system_hash("Dentry cache", + sizeof(struct hlist_head), + dhash_entries, + 13, + 0, + &d_hash_shift, + &d_hash_mask); + + for (loop = 0; loop < (1 << d_hash_shift); loop++) + INIT_HLIST_HEAD(&dentry_hashtable[loop]); +} +static void __init dcache_init(unsigned long mempages) +{ /* * A constructor could be added for stable state like the lists, * but it is probably not worth it because of the cache nature @@ -1580,45 +1593,6 @@ static void __init dcache_init(unsigned long mempages) NULL, NULL); set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory); - - if (!dhash_entries) - dhash_entries = PAGE_SHIFT < 13 ? - mempages >> (13 - PAGE_SHIFT) : - mempages << (PAGE_SHIFT - 13); - - dhash_entries *= sizeof(struct hlist_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < dhash_entries; order++) - ; - - do { - unsigned long tmp; - - nr_hash = (1UL << order) * PAGE_SIZE / - sizeof(struct hlist_head); - d_hash_mask = (nr_hash - 1); - - tmp = nr_hash; - d_hash_shift = 0; - while ((tmp >>= 1UL) != 0UL) - d_hash_shift++; - - dentry_hashtable = (struct hlist_head *) - __get_free_pages(GFP_ATOMIC, order); - } while (dentry_hashtable == NULL && --order >= 0); - - printk(KERN_INFO "Dentry cache hash table entries: %d (order: %ld, %ld bytes)\n", - nr_hash, order, (PAGE_SIZE << order)); - - if (!dentry_hashtable) - panic("Failed to allocate dcache hash table\n"); - - d = dentry_hashtable; - i = nr_hash; - do { - INIT_HLIST_HEAD(d); - d++; - i--; - } while (i); } /* SLAB cache for __getname() consumers */ @@ -1632,6 +1606,12 @@ EXPORT_SYMBOL(d_genocide); extern void bdev_cache_init(void); extern void chrdev_init(void); +void __init vfs_caches_init_early(void) +{ + dcache_init_early(); + inode_init_early(); +} + void __init vfs_caches_init(unsigned long mempages) { unsigned long reserve; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 0da65be3231b..2362582a19cc 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,20 +174,17 @@ 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; } - /* - * Note: the iocharset option might have been specified - * without enabling nls_io, so check for it here. - */ - 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; kfree(sbi); } @@ -196,11 +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) + if (sbi->nls_disk && opts->codepage != fat_default_codepage) seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); if (isvfat) { - if (sbi->nls_io - && strcmp(sbi->nls_io->charset, CONFIG_NLS_DEFAULT)) + if (sbi->nls_io && + strcmp(opts->iocharset, fat_default_iocharset)) seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); switch (opts->shortname) { @@ -331,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 @@ -351,7 +357,7 @@ static int parse_options(char *options, int is_vfat, int *debug, *debug = 0; if (!options) - return 1; + return 0; while ((p = strsep(&options, ",")) != NULL) { int token; @@ -437,10 +443,12 @@ static int parse_options(char *options, int is_vfat, int *debug, /* vfat specific */ case Opt_charset: - kfree(opts->iocharset); - opts->iocharset = match_strdup(&args[0]); - if (!opts->iocharset) - return 0; + if (opts->iocharset != fat_default_iocharset) + kfree(opts->iocharset); + iocharset = match_strdup(&args[0]); + if (!iocharset) + return -ENOMEM; + opts->iocharset = iocharset; break; case Opt_shortname_lower: opts->shortname = VFAT_SFN_DISPLAY_LOWER @@ -486,14 +494,20 @@ static int parse_options(char *options, int is_vfat, int *debug, default: printk(KERN_ERR "FAT: Unrecognized mount option \"%s\" " "or missing value\n", p); - return 0; + return -EINVAL; } } + /* UTF8 doesn't provide FAT semantics */ + if (!strcmp(opts->iocharset, "utf8")) { + printk(KERN_ERR "FAT: utf8 is not a valid IO charset" + " for FAT filesystems\n"); + return -EINVAL; + } if (opts->unicode_xlate) opts->utf8 = 0; - return 1; + return 0; } static int fat_calc_dir_size(struct inode *inode) @@ -784,7 +798,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, struct msdos_sb_info *sbi; u16 logical_sector_size; u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors; - int debug, cp, first; + int debug, first; unsigned int media; long error; char buf[50]; @@ -801,8 +815,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, sb->s_export_op = &fat_export_ops; sbi->dir_ops = fs_dir_inode_ops; - error = -EINVAL; - if (!parse_options(data, isvfat, &debug, &sbi->options)) + error = parse_options(data, isvfat, &debug, &sbi->options); + if (error) goto out_fail; fat_cache_init(sb); @@ -1009,31 +1023,21 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, } error = -EINVAL; - cp = sbi->options.codepage ? sbi->options.codepage : 437; - sprintf(buf, "cp%d", cp); + sprintf(buf, "cp%d", sbi->options.codepage); sbi->nls_disk = load_nls(buf); if (!sbi->nls_disk) { - /* Fail only if explicit charset specified */ - if (sbi->options.codepage != 0) { - printk(KERN_ERR "FAT: codepage %s not found\n", buf); - goto out_fail; - } - sbi->options.codepage = 0; /* already 0?? */ - sbi->nls_disk = load_nls_default(); + 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) { - if (sbi->options.iocharset != NULL) { - 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; - } - } else - sbi->nls_io = load_nls_default(); + 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; @@ -1068,7 +1072,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/fcntl.c b/fs/fcntl.c index 13d351cba2e3..77cec9debe17 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -212,7 +212,7 @@ asmlinkage long sys_dup(unsigned int fildes) return ret; } -#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT) +#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME) static int setfl(int fd, struct file * filp, unsigned long arg) { @@ -223,6 +223,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) if (!(arg & O_APPEND) && IS_APPEND(inode)) return -EPERM; + /* O_NOATIME can only be set by the owner or superuser */ + if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME)) + if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) + return -EPERM; + /* required for strict SunOS emulation */ if (O_NONBLOCK != O_NDELAY) if (arg & O_NDELAY) diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c index 565d2b8b4b2e..72ea1412b467 100644 --- a/fs/hpfs/alloc.c +++ b/fs/hpfs/alloc.c @@ -79,11 +79,11 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne } else { if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) goto uls; } - /*if (!tstbits(bmp, nr + n, n + forward)) { + if (!tstbits(bmp, nr, n + forward)) { ret = bs + nr; goto rt; } - if (!tstbits(bmp, nr + 2*n, n + forward)) { + /*if (!tstbits(bmp, nr + n, n + forward)) { ret = bs + nr + n; goto rt; }*/ @@ -103,9 +103,11 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne goto rt; } nr >>= 5; - for (i = nr + 1; i != nr; i++, i &= 0x1ff) { - if (!bmp[i]) continue; - if (n + forward >= 0x3f && bmp[i] != -1) continue; + /*for (i = nr + 1; i != nr; i++, i &= 0x1ff) {*/ + i = nr; + do { + if (!bmp[i]) goto cont; + if (n + forward >= 0x3f && bmp[i] != -1) goto cont; q = i<<5; if (i > 0) { unsigned k = bmp[i-1]; @@ -123,7 +125,9 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne ret = bs + q; goto rt; } - } + cont: + i++, i &= 0x1ff; + } while (i != nr); rt: if (ret) { if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (bmp[(ret & 0x3fff) >> 5] | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) { @@ -152,46 +156,57 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward, int lock) { secno sec; - unsigned i; + int i; unsigned n_bmps; struct hpfs_sb_info *sbi = hpfs_sb(s); - int b = sbi->sb_c_bitmap; int f_p = 0; + int near_bmp; if (forward < 0) { forward = -forward; f_p = 1; } if (lock) hpfs_lock_creation(s); - if (near && near < sbi->sb_fs_size) + n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14; + if (near && near < sbi->sb_fs_size) { if ((sec = alloc_in_bmp(s, near, n, f_p ? forward : forward/4))) goto ret; + near_bmp = near >> 14; + } else near_bmp = n_bmps / 2; + /* if (b != -1) { if ((sec = alloc_in_bmp(s, b<<14, n, f_p ? forward : forward/2))) { b &= 0x0fffffff; goto ret; } if (b > 0x10000000) if ((sec = alloc_in_bmp(s, (b&0xfffffff)<<14, n, f_p ? forward : 0))) goto ret; - } - n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14; - for (i = 0; i < n_bmps / 2; i++) { - if ((sec = alloc_in_bmp(s, (n_bmps/2+i) << 14, n, forward))) { - sbi->sb_c_bitmap = n_bmps/2+i; + */ + if (!f_p) if (forward > sbi->sb_max_fwd_alloc) forward = sbi->sb_max_fwd_alloc; + less_fwd: + for (i = 0; i < n_bmps; i++) { + if (near_bmp+i < n_bmps && ((sec = alloc_in_bmp(s, (near_bmp+i) << 14, n, forward)))) { + sbi->sb_c_bitmap = near_bmp+i; goto ret; } - if ((sec = alloc_in_bmp(s, (n_bmps/2-i-1) << 14, n, forward))) { - sbi->sb_c_bitmap = n_bmps/2-i-1; + if (!forward) { + if (near_bmp-i-1 >= 0 && ((sec = alloc_in_bmp(s, (near_bmp-i-1) << 14, n, forward)))) { + sbi->sb_c_bitmap = near_bmp-i-1; + goto ret; + } + } else { + if (near_bmp+i >= n_bmps && ((sec = alloc_in_bmp(s, (near_bmp+i-n_bmps) << 14, n, forward)))) { + sbi->sb_c_bitmap = near_bmp+i-n_bmps; + goto ret; + } + } + if (i == 1 && sbi->sb_c_bitmap != -1 && ((sec = alloc_in_bmp(s, (sbi->sb_c_bitmap) << 14, n, forward)))) { goto ret; } } - if ((sec = alloc_in_bmp(s, (n_bmps-1) << 14, n, forward))) { - sbi->sb_c_bitmap = n_bmps-1; - goto ret; - } if (!f_p) { - for (i = 0; i < n_bmps; i++) - if ((sec = alloc_in_bmp(s, i << 14, n, 0))) { - sbi->sb_c_bitmap = 0x10000000 + i; - goto ret; - } + if (forward) { + sbi->sb_max_fwd_alloc = forward * 3 / 4; + forward /= 2; + goto less_fwd; + } } sec = 0; ret: @@ -262,6 +277,7 @@ void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n) { struct quad_buffer_head qbh; unsigned *bmp; + struct hpfs_sb_info *sbi = hpfs_sb(s); /*printk("2 - ");*/ if (!n) return; if (sec < 0x12) { @@ -269,6 +285,8 @@ void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n) return; } lock_super(s); + sbi->sb_max_fwd_alloc += n > 0xffff ? 0xffff : n; + if (sbi->sb_max_fwd_alloc > 0xffffff) sbi->sb_max_fwd_alloc = 0xffffff; new_map: if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "free"))) { unlock_super(s); @@ -321,7 +339,7 @@ int hpfs_check_free_dnodes(struct super_block *s, int n) } hpfs_brelse4(&qbh); i = 0; - if (hpfs_sb(s)->sb_c_bitmap != -1 ) { + if (hpfs_sb(s)->sb_c_bitmap != -1) { bmp = hpfs_map_bitmap(s, b, &qbh, "chkdn1"); goto chk_bmp; } diff --git a/fs/hpfs/anode.c b/fs/hpfs/anode.c index 1b6d1f820360..1aa88c4e0964 100644 --- a/fs/hpfs/anode.c +++ b/fs/hpfs/anode.c @@ -113,7 +113,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi brelse(bh); return -1; } - se = node; + se = !fnod ? node : (node + 16384) & ~16383; } if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M, 1))) { brelse(bh); @@ -192,7 +192,6 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi } up = up != node ? anode->up : -1; btree->u.internal[btree->n_used_nodes - 1].file_secno = /*fs*/-1; - if (up == -1) anode->up = ra; mark_buffer_dirty(bh); brelse(bh); a = na; diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 77cd01ced013..2d5c84455b5d 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c @@ -31,6 +31,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head { struct buffer_head *bh; + cond_resched(); + *bhp = bh = sb_bread(s, secno); if (bh != NULL) return bh->b_data; @@ -47,6 +49,8 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head struct buffer_head *bh; /*return hpfs_map_sector(s, secno, bhp, 0);*/ + cond_resched(); + if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { if (!buffer_uptodate(bh)) wait_on_buffer(bh); set_buffer_uptodate(bh); @@ -65,6 +69,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe struct buffer_head *bh; char *data; + cond_resched(); + if (secno & 3) { printk("HPFS: hpfs_map_4sectors: unaligned read\n"); return 0; @@ -116,6 +122,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe void *hpfs_get_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh) { + cond_resched(); + if (secno & 3) { printk("HPFS: hpfs_get_4sectors: unaligned read\n"); return 0; diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index 11057ec800f5..66339dc030e4 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c @@ -234,7 +234,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data } pos += ea->namelen + ea->valuelen + 5; } - if (!fnode->ea_size_s) { + if (!fnode->ea_offs) { /*if (fnode->ea_size_s) { hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0", inode->i_ino, fnode->ea_size_s); @@ -242,15 +242,13 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data }*/ fnode->ea_offs = 0xc4; } - if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->ea_size_s > 0x200) { + if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200) { hpfs_error(s, "fnode %08x: ea_offs == %03x, ea_size_s == %03x", inode->i_ino, fnode->ea_offs, fnode->ea_size_s); return; } if ((fnode->ea_size_s || !fnode->ea_size_l) && - fnode->ea_offs + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) { - /* I'm not sure ... maybe we overwrite ACL here. I have no info - on it right now :-( */ + fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) { ea = fnode_end_ea(fnode); *(char *)ea = 0; ea->namelen = strlen(key); diff --git a/fs/hpfs/hpfs.h b/fs/hpfs/hpfs.h index 4d342db5fdf9..da40420c781c 100644 --- a/fs/hpfs/hpfs.h +++ b/fs/hpfs/hpfs.h @@ -408,7 +408,7 @@ struct fnode unsigned file_size; /* file length, bytes */ unsigned n_needea; /* number of EA's with NEEDEA set */ char user_id[16]; /* unused */ - unsigned ea_offs; /* offset from start of fnode + unsigned short ea_offs; /* offset from start of fnode to first fnode-resident ea */ char dasd_limit_treshhold; char dasd_limit_delta; diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 0958e5cc519f..ebe670a02170 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h @@ -87,6 +87,7 @@ struct hpfs_sb_info { /* 128 bytes lowercasing table */ unsigned *sb_bmp_dir; /* main bitmap directory */ unsigned sb_c_bitmap; /* current bitmap */ + unsigned sb_max_fwd_alloc; /* max forwad allocation */ struct semaphore hpfs_creation_de; /* when creating dirents, nobody else can alloc blocks */ /*unsigned sb_mounting : 1;*/ @@ -141,12 +142,12 @@ static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de) static inline struct extended_attribute *fnode_ea(struct fnode *fnode) { - return (struct extended_attribute *)((char *)fnode + fnode->ea_offs); + return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s); } static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode) { - return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->ea_size_s); + return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s); } static inline struct extended_attribute *next_ea(struct extended_attribute *ea) diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index dec2ad61c355..28483e9e76dc 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -144,11 +144,11 @@ void hpfs_read_inode(struct inode *i) void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) { struct hpfs_inode_info *hpfs_inode = hpfs_i(i); - if (fnode->acl_size_l || fnode->acl_size_s) { - /* Some unknown structures like ACL may be in fnode, - we'd better not overwrite them */ + /*if (fnode->acl_size_l || fnode->acl_size_s) { + Some unknown structures like ACL may be in fnode, + we'd better not overwrite them hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino); - } else if (hpfs_sb(i->i_sb)->sb_eas >= 2) { + } else*/ if (hpfs_sb(i->i_sb)->sb_eas >= 2) { u32 ea; if ((i->i_uid != hpfs_sb(i->i_sb)->sb_uid) || hpfs_inode->i_ea_uid) { ea = cpu_to_le32(i->i_uid); @@ -218,16 +218,18 @@ void hpfs_write_inode_nolock(struct inode *i) struct hpfs_dirent *de; if (i->i_ino == hpfs_sb(i->i_sb)->sb_root) return; if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) return; - if (i->i_ino != hpfs_sb(i->i_sb)->sb_root) { + if (i->i_ino != hpfs_sb(i->i_sb)->sb_root && i->i_nlink) { if (!(de = map_fnode_dirent(i->i_sb, i->i_ino, fnode, &qbh))) { brelse(bh); return; } } else de = NULL; if (S_ISREG(i->i_mode)) { - fnode->file_size = de->file_size = i->i_size; + fnode->file_size = i->i_size; + if (de) de->file_size = i->i_size; } else if (S_ISDIR(i->i_mode)) { - fnode->file_size = de->file_size = 0; + fnode->file_size = 0; + if (de) de->file_size = 0; } hpfs_write_inode_ea(i, fnode); if (de) { diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c index 8f21356e99eb..0fecdac22e4e 100644 --- a/fs/hpfs/map.c +++ b/fs/hpfs/map.c @@ -142,7 +142,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea } } if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 || - (signed int)fnode->ea_offs + fnode->ea_size_s > 0x200)) { + (signed int)fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200)) { hpfs_error(s, "bad EA info in fnode %08x: ea_offs == %04x ea_size_s == %04x", ino, fnode->ea_offs, fnode->ea_size_s); goto bail; @@ -225,14 +225,16 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno, } for (p = 20; p < dnode->first_free; p += d[p] + (d[p+1] << 8)) { struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p); - if (de->length > 292 || (de->length < 32) || (de->length & 3)) { + if (de->length > 292 || (de->length < 32) || (de->length & 3) || p + de->length > 2048) { hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); goto bail; } if (((31 + de->namelen + de->down*4 + 3) & ~3) != de->length) { + if (((31 + de->namelen + de->down*4 + 3) & ~3) < de->length && s->s_flags & MS_RDONLY) goto ok; hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); goto bail; } + ok: if (hpfs_sb(s)->sb_chk >= 2) b |= 1 << de->down; if (de->down) if (de_down_pointer(de) < 0x10) { hpfs_error(s, "bad down pointer in dnode %08x, dirent %03x, last %03x", secno, p, pp); diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 0f61abb18a27..714f64447d6e 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -542,6 +542,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) sbi->sb_was_error = 0; sbi->sb_cp_table = NULL; sbi->sb_c_bitmap = -1; + sbi->sb_max_fwd_alloc = 0xffffff; /* Load bitmap directory */ if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, superblock->bitmaps))) diff --git a/fs/inode.c b/fs/inode.c index 042e3bb454dd..e802a3c35fd2 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -20,6 +20,7 @@ #include <linux/security.h> #include <linux/pagemap.h> #include <linux/cdev.h> +#include <linux/bootmem.h> /* * This is needed for the following functions: @@ -1345,55 +1346,30 @@ __setup("ihash_entries=", set_ihash_entries); /* * Initialize the waitqueues and inode hash table. */ +void __init inode_init_early(void) +{ + int loop; + + inode_hashtable = + alloc_large_system_hash("Inode-cache", + sizeof(struct hlist_head), + ihash_entries, + 14, + 0, + &i_hash_shift, + &i_hash_mask); + + for (loop = 0; loop < (1 << i_hash_shift); loop++) + INIT_HLIST_HEAD(&inode_hashtable[loop]); +} + void __init inode_init(unsigned long mempages) { - struct hlist_head *head; - unsigned long order; - unsigned int nr_hash; int i; for (i = 0; i < ARRAY_SIZE(i_wait_queue_heads); i++) init_waitqueue_head(&i_wait_queue_heads[i].wqh); - if (!ihash_entries) - ihash_entries = PAGE_SHIFT < 14 ? - mempages >> (14 - PAGE_SHIFT) : - mempages << (PAGE_SHIFT - 14); - - ihash_entries *= sizeof(struct hlist_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < ihash_entries; order++) - ; - - do { - unsigned long tmp; - - nr_hash = (1UL << order) * PAGE_SIZE / - sizeof(struct hlist_head); - i_hash_mask = (nr_hash - 1); - - tmp = nr_hash; - i_hash_shift = 0; - while ((tmp >>= 1UL) != 0UL) - i_hash_shift++; - - inode_hashtable = (struct hlist_head *) - __get_free_pages(GFP_ATOMIC, order); - } while (inode_hashtable == NULL && --order >= 0); - - printk("Inode-cache hash table entries: %d (order: %ld, %ld bytes)\n", - nr_hash, order, (PAGE_SIZE << order)); - - if (!inode_hashtable) - panic("Failed to allocate inode hash table\n"); - - head = inode_hashtable; - i = nr_hash; - do { - INIT_HLIST_HEAD(head); - head++; - i--; - } while (i); - /* inode slab cache */ inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, init_once, diff --git a/fs/ioctl.c b/fs/ioctl.c index aef5391e48a2..c84ce99576a8 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -4,11 +4,13 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include <linux/config.h> #include <linux/mm.h> #include <linux/smp_lock.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/security.h> +#include <linux/module.h> #include <asm/uaccess.h> #include <asm/ioctls.h> @@ -133,3 +135,11 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) out: return error; } + +/* + * Platforms implementing 32 bit compatibility ioctl handlers in + * modules need this exported + */ +#ifdef CONFIG_COMPAT +EXPORT_SYMBOL(sys_ioctl); +#endif diff --git a/fs/jfs/jfs_btree.h b/fs/jfs/jfs_btree.h index ba4fb09f5fa2..7f3e9ac454ff 100644 --- a/fs/jfs/jfs_btree.h +++ b/fs/jfs/jfs_btree.h @@ -147,7 +147,7 @@ static inline void BT_STACK_DUMP(struct btstack *btstack) printk("btstack dump:\n"); for (i = 0; i < MAXTREEHEIGHT; i++) printk(KERN_ERR "bn = %Lx, index = %d\n", - btstack->stack[i].bn, + (long long)btstack->stack[i].bn, btstack->stack[i].index); } diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 3c3140dd758f..dc749c2e6fa8 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -374,6 +374,8 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot) return index; } if (index == (MAX_INLINE_DIRTABLE_ENTRY + 1)) { + struct dir_table_slot temp_table[12]; + /* * It's time to move the inline table to an external * page and begin to build the xtree @@ -385,7 +387,6 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot) * Save the table, we're going to overwrite it with the * xtree root */ - struct dir_table_slot temp_table[12]; memcpy(temp_table, &jfs_ip->i_dirtable, sizeof(temp_table)); /* diff --git a/fs/namei.c b/fs/namei.c index 9828b94fe8bb..efaaf1dd1d7d 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1206,6 +1206,11 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) return -EPERM; } + /* O_NOATIME can only be set by the owner or superuser */ + if (flag & O_NOATIME) + if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) + return -EPERM; + /* * Ensure there are no outstanding leases on the file. */ diff --git a/fs/nls/Kconfig b/fs/nls/Kconfig index 21c2559ea4bd..0ab8f00bdbb2 100644 --- a/fs/nls/Kconfig +++ b/fs/nls/Kconfig @@ -332,6 +332,14 @@ config NLS_CODEPAGE_1251 say Y here if you want to include the DOS codepage for Russian and Bulgarian and Belarusian. +config NLS_ASCII + tristate "ASCII (United States)" + depends on NLS + help + An ASCII NLS module is needed if you want to override the + DEFAULT NLS with this very basic charset and don't want any + non-ASCII characters to be translated. + config NLS_ISO8859_1 tristate "NLS ISO 8859-1 (Latin 1; Western European Languages)" depends on NLS diff --git a/fs/nls/Makefile b/fs/nls/Makefile index 4548f2940327..a7ade138d684 100644 --- a/fs/nls/Makefile +++ b/fs/nls/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_NLS_CODEPAGE_949) += nls_cp949.o obj-$(CONFIG_NLS_CODEPAGE_950) += nls_cp950.o obj-$(CONFIG_NLS_CODEPAGE_1250) += nls_cp1250.o obj-$(CONFIG_NLS_CODEPAGE_1251) += nls_cp1251.o +obj-$(CONFIG_NLS_ASCII) += nls_ascii.o obj-$(CONFIG_NLS_ISO8859_1) += nls_iso8859-1.o obj-$(CONFIG_NLS_ISO8859_2) += nls_iso8859-2.o obj-$(CONFIG_NLS_ISO8859_3) += nls_iso8859-3.o diff --git a/fs/nls/nls_ascii.c b/fs/nls/nls_ascii.c new file mode 100644 index 000000000000..347487f24f97 --- /dev/null +++ b/fs/nls/nls_ascii.c @@ -0,0 +1,167 @@ +/* + * linux/fs/nls_ascii.c + * + * Charset ascii translation tables. + * Generated automatically from the Unicode and charset + * tables from the Unicode Organization (www.unicode.org). + * The Unicode to charset table has only exact mappings. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/nls.h> +#include <linux/errno.h> + +static wchar_t charset2uni[128] = { + /* 0x00*/ + 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, + 0x000c, 0x000d, 0x000e, 0x000f, + /* 0x10*/ + 0x0010, 0x0011, 0x0012, 0x0013, + 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, + 0x001c, 0x001d, 0x001e, 0x001f, + /* 0x20*/ + 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, + 0x002c, 0x002d, 0x002e, 0x002f, + /* 0x30*/ + 0x0030, 0x0031, 0x0032, 0x0033, + 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, + 0x003c, 0x003d, 0x003e, 0x003f, + /* 0x40*/ + 0x0040, 0x0041, 0x0042, 0x0043, + 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, + 0x004c, 0x004d, 0x004e, 0x004f, + /* 0x50*/ + 0x0050, 0x0051, 0x0052, 0x0053, + 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, + 0x005c, 0x005d, 0x005e, 0x005f, + /* 0x60*/ + 0x0060, 0x0061, 0x0062, 0x0063, + 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, + 0x006c, 0x006d, 0x006e, 0x006f, + /* 0x70*/ + 0x0070, 0x0071, 0x0072, 0x0073, + 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, + 0x007c, 0x007d, 0x007e, 0x007f, +}; + +static unsigned char page00[128] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */ + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */ + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */ + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */ + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */ + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */ + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */ + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */ +}; + +static unsigned char *page_uni2charset[128] = { + page00, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + +static unsigned char charset2lower[128] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */ + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */ + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */ + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */ + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */ + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */ + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */ + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */ + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */ +}; + +static unsigned char charset2upper[128] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */ + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */ + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */ + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */ + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */ + 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */ + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */ + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */ + 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */ +}; + +static int uni2char(wchar_t uni, unsigned char *out, int boundlen) +{ + unsigned char *uni2charset; + unsigned char cl = uni & 0x00ff; + unsigned char ch = (uni & 0xff00) >> 8; + + if (boundlen <= 0) + return -ENAMETOOLONG; + + uni2charset = page_uni2charset[ch]; + if (uni2charset && uni2charset[cl]) + out[0] = uni2charset[cl]; + else + return -EINVAL; + return 1; +} + +static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) +{ + *uni = charset2uni[*rawstring]; + if (*uni == 0x0000) + return -EINVAL; + return 1; +} + +static struct nls_table table = { + .charset = "ascii", + .uni2char = uni2char, + .char2uni = char2uni, + .charset2lower = charset2lower, + .charset2upper = charset2upper, + .owner = THIS_MODULE, +}; + +static int __init init_nls_ascii(void) +{ + return register_nls(&table); +} + +static void __exit exit_nls_ascii(void) +{ + unregister_nls(&table); +} + +module_init(init_nls_ascii) +module_exit(exit_nls_ascii) + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 2066d2551c9f..a46bd705e93b 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -66,9 +66,6 @@ extern int get_filesystem_list(char *); extern int get_exec_domain_list(char *); extern int get_dma_list(char *); extern int get_locks_status (char *, char **, off_t, int); -#ifdef CONFIG_SGI_DS1286 -extern int get_ds1286_status(char *); -#endif static int proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len) @@ -528,15 +525,6 @@ static int cmdline_read_proc(char *page, char **start, off_t off, return proc_calc_metrics(page, start, off, count, eof, len); } -#ifdef CONFIG_SGI_DS1286 -static int ds1286_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = get_ds1286_status(page); - return proc_calc_metrics(page, start, off, count, eof, len); -} -#endif - static int locks_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -670,9 +658,6 @@ void __init proc_misc_init(void) {"devices", devices_read_proc}, {"filesystems", filesystems_read_proc}, {"cmdline", cmdline_read_proc}, -#ifdef CONFIG_SGI_DS1286 - {"rtc", ds1286_read_proc}, -#endif {"locks", locks_read_proc}, {"execdomains", execdomains_read_proc}, {NULL,} diff --git a/fs/quota.c b/fs/quota.c index 867fe35e5433..680dd072a8c6 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -264,7 +264,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, cadd * calls. Maybe we need to add the process quotas etc. in the future, * but we probably should use rlimits for that. */ -asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr) +asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, caddr_t addr) { uint cmds, type; struct super_block *sb = NULL; diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index ac92dc59894e..b5e4498fcfeb 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -949,10 +949,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start hint->preallocate=hint->prealloc_size=0; } /* for unformatted nodes, force large allocations */ - bigalloc = amount_needed + hint->prealloc_size; - /* try to make things even */ - if (bigalloc & 1 && hint->prealloc_size) - bigalloc--; + bigalloc = amount_needed; } do { diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 1b1892c61428..363072cc4e51 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -131,7 +131,7 @@ int reiserfs_allocate_blocks_for_region( struct buffer_head *bh; // Buffer head that contains items that we are going to deal with __u32 * item; // pointer to item we are going to deal with INITIALIZE_PATH(path); // path to item, that we are going to deal with. - b_blocknr_t allocated_blocks[blocks_to_allocate]; // Pointer to a place where allocated blocknumbers would be stored. Right now statically allocated, later that will change. + b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored. reiserfs_blocknr_hint_t hint; // hint structure for block allocator. size_t res; // return value of various functions that we call. int curr_block; // current block used to keep track of unmapped blocks. @@ -144,10 +144,20 @@ int reiserfs_allocate_blocks_for_region( int modifying_this_item = 0; // Flag for items traversal code to keep track // of the fact that we already prepared // current block for journal - + int will_prealloc = 0; RFALSE(!blocks_to_allocate, "green-9004: tried to allocate zero blocks?"); + /* only preallocate if this is a small write */ + if (REISERFS_I(inode)->i_prealloc_count || + (!(write_bytes & (inode->i_sb->s_blocksize -1)) && + blocks_to_allocate < + REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize)) + will_prealloc = REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize; + + allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) * + sizeof(b_blocknr_t), GFP_NOFS); + /* First we compose a key to point at the writing position, we want to do that outside of any locking region. */ make_cpu_key (&key, inode, pos+1, TYPE_ANY, 3/*key length*/); @@ -174,15 +184,8 @@ int reiserfs_allocate_blocks_for_region( hint.key = key.on_disk_key; // on disk key of file. hint.block = inode->i_blocks>>(inode->i_sb->s_blocksize_bits-9); // Number of disk blocks this file occupies already. hint.formatted_node = 0; // We are allocating blocks for unformatted node. + hint.preallocate = will_prealloc; - /* only preallocate if this is a small write */ - if (REISERFS_I(inode)->i_prealloc_count || - (!(write_bytes & (inode->i_sb->s_blocksize -1)) && - blocks_to_allocate < - REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize)) - hint.preallocate = 1; - else - hint.preallocate = 0; /* Call block allocator to allocate blocks */ res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate); if ( res != CARRY_ON ) { @@ -511,6 +514,7 @@ retry: RFALSE( curr_block > blocks_to_allocate, "green-9007: Used too many blocks? weird"); + kfree(allocated_blocks); return 0; // Need to deal with transaction here. @@ -524,6 +528,7 @@ error_exit: reiserfs_update_sd(th, inode); // update any changes we made to blk count journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1); reiserfs_write_unlock(inode->i_sb); + kfree(allocated_blocks); return res; } diff --git a/include/asm-alpha/fcntl.h b/include/asm-alpha/fcntl.h index ad40d002f006..6b7d6c1649ce 100644 --- a/include/asm-alpha/fcntl.h +++ b/include/asm-alpha/fcntl.h @@ -21,6 +21,7 @@ #define O_NOFOLLOW 0200000 /* don't follow links */ #define O_LARGEFILE 0400000 /* will be set by the kernel on every open */ #define O_DIRECT 02000000 /* direct disk access - should check with OSF/1 */ +#define O_NOATIME 04000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-arm/arch-nexuspci/dma.h b/include/asm-arm/arch-nexuspci/dma.h deleted file mode 100644 index dee1ea2175c4..000000000000 --- a/include/asm-arm/arch-nexuspci/dma.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/dma.h - * - * Architecture DMA routines - * - * Copyright (C) 1998, 1999 Philip Blundell - */ - -/* - * 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. - */ - -/* - * This is the maximum DMA address that can be DMAd to. - */ -#define MAX_DMA_ADDRESS 0xffffffff -#define MAX_DMA_CHANNELS 0 diff --git a/include/asm-arm/arch-nexuspci/hardware.h b/include/asm-arm/arch-nexuspci/hardware.h deleted file mode 100644 index 303dc2c974ba..000000000000 --- a/include/asm-arm/arch-nexuspci/hardware.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/hardware.h - * - * Copyright (C) 1998, 1999, 2000 FutureTV Labs Ltd. - * - * This file contains the hardware definitions of the FTV PCI card. - */ - -/* - * 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. - */ - -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -/* Logical Physical - * 0xffe00000 0x20000000 INTCONT - * 0xffd00000 0x30000000 Status - * 0xffc00000 0x60000000 PLX registers - * 0xfe000000 0xC0000000 PCI I/O - * 0xfd000000 0x70000000 cache flush - * 0xfc000000 0x80000000 PCI/ISA memory - * 0xe0000000 0x10000000 SCC2691 DUART - */ - -/* - * Mapping areas - */ -#define INTCONT_BASE 0xffe00000 -#define STATUS_BASE 0xffd00000 -#define PLX_BASE 0xffc00000 -#define PCIO_BASE 0xfe000000 -#define FLUSH_BASE 0xfd000000 -#define DUART_BASE 0xe0000000 -#define PCIMEM_BASE 0xfc000000 - -#define PLX_IO_START 0xC0000000 -#define PLX_MEM_START 0x80000000 -#define PLX_START 0x60000000 -#define STATUS_START 0x30000000 -#define INTCONT_START 0x20000000 -#define DUART_START 0x10000000 - -/* - * RAM definitions - */ -#define RAM_BASE 0x40000000 -#define FLUSH_BASE_PHYS 0x70000000 - -/* - * Miscellaneous INTCONT bits - */ -#define INTCONT_FIQ_PLX 0x00 -#define INTCONT_FIQ_D 0x02 -#define INTCONT_FIQ_C 0x04 -#define INTCONT_FIQ_B 0x06 -#define INTCONT_FIQ_A 0x08 -#define INTCONT_FIQ_SYSERR 0x0a -#define INTCONT_IRQ_DUART 0x0c -#define INTCONT_IRQ_PLX 0x0e -#define INTCONT_IRQ_D 0x10 -#define INTCONT_IRQ_C 0x12 -#define INTCONT_IRQ_B 0x14 -#define INTCONT_IRQ_A 0x16 -#define INTCONT_IRQ_SYSERR 0x1e - -#define INTCONT_WATCHDOG 0x18 -#define INTCONT_LED 0x1a -#define INTCONT_PCI_RESET 0x1c - -#define UNCACHEABLE_ADDR STATUS_BASE - -#endif diff --git a/include/asm-arm/arch-nexuspci/io.h b/include/asm-arm/arch-nexuspci/io.h deleted file mode 100644 index 181bdb5988df..000000000000 --- a/include/asm-arm/arch-nexuspci/io.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/io.h - * - * Copyright (C) 1997-1999 Russell King - * Copyright (C) 2000 FutureTV Labs Ltd. - */ -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H - -#define IO_SPACE_LIMIT 0xffff - -/* - * Translation of various region addresses to virtual addresses - */ -#define __io(a) (PCIO_BASE + (a)) -#if 1 -#define __mem_pci(a) ((unsigned long)(a)) -#define __mem_isa(a) (PCIMEM_BASE + (unsigned long)(a)) -#else - -static inline unsigned long ___mem_pci(unsigned long a) -{ - /* PCI addresses must have been ioremapped */ - if (a <= 0xc0000000 || a >= 0xe0000000) - *((int *)0) = 0; - return a; -} - -static inline unsigned long ___mem_isa(unsigned long a) -{ - BUG_ON(a >= 16*1048576); - return PCIMEM_BASE + a; -} -#define __mem_pci(a) ___mem_pci((unsigned long)(a)) -#define __mem_isa(a) ___mem_isa((unsigned long)(a)) -#endif - -/* - * ioremap support - validate a PCI memory address, - * and convert a PCI memory address to a physical - * address for the page tables. - */ -#define iomem_valid_addr(iomem,sz) \ - ((iomem) < 0x80000000 && (iomem) + (sz) <= 0x80000000) -#define iomem_to_phys(iomem) ((iomem) + PLX_MEM_START) - -#define __arch_ioremap(off,sz,nocache) \ - ({ \ - unsigned long _off = (off), _size = (sz); \ - void *_ret = (void *)0; \ - if (iomem_valid_addr(_off, _size)) \ - _ret = __ioremap(iomem_to_phys(_off),_size,0); \ - _ret; \ - }) - -#define __arch_iounmap __iounmap - -#endif diff --git a/include/asm-arm/arch-nexuspci/irqs.h b/include/asm-arm/arch-nexuspci/irqs.h deleted file mode 100644 index 006c14b96b36..000000000000 --- a/include/asm-arm/arch-nexuspci/irqs.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/irqs.h - * - * Copyright (C) 1997, 1998, 2000 Philip Blundell - */ - -/* - * 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. - */ - -/* - * The hardware is capable of routing any interrupt source (except the - * DUART) to either IRQ or FIQ. We ignore FIQ and use IRQ exclusively - * for simplicity. - */ - -#define IRQ_DUART 0 -#define IRQ_PLX 1 -#define IRQ_PCI_D 2 -#define IRQ_PCI_C 3 -#define IRQ_PCI_B 4 -#define IRQ_PCI_A 5 -#define IRQ_SYSERR 6 /* only from IOSLAVE rev B */ - -#define FIRST_IRQ IRQ_DUART -#define LAST_IRQ IRQ_SYSERR - -/* timer is part of the DUART */ -#define IRQ_TIMER IRQ_DUART - -#define irq_canonicalize(i) (i) diff --git a/include/asm-arm/arch-nexuspci/memory.h b/include/asm-arm/arch-nexuspci/memory.h deleted file mode 100644 index 85d7c45055f7..000000000000 --- a/include/asm-arm/arch-nexuspci/memory.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/memory.h - * - * Copyright (c) 1997, 1998, 2000 FutureTV Labs Ltd. - * Copyright (c) 1999 Russell King - * - */ -#ifndef __ASM_ARCH_MEMORY_H -#define __ASM_ARCH_MEMORY_H - -/* - * Physical DRAM offset. - */ -#define PHYS_OFFSET (0x40000000UL) -#define BUS_OFFSET (0xe0000000UL) - -/* - * On the PCI bus the DRAM appears at address 0xe0000000 - */ -#define __virt_to_bus(x) ((unsigned long)(x) - PAGE_OFFSET + BUS_OFFSET) -#define __bus_to_virt(x) ((unsigned long)(x) + PAGE_OFFSET - BUS_OFFSET) - -#endif diff --git a/include/asm-arm/arch-nexuspci/param.h b/include/asm-arm/arch-nexuspci/param.h deleted file mode 100644 index d57753d8f1b8..000000000000 --- a/include/asm-arm/arch-nexuspci/param.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/param.h - */ diff --git a/include/asm-arm/arch-nexuspci/system.h b/include/asm-arm/arch-nexuspci/system.h deleted file mode 100644 index 824a1d7ad403..000000000000 --- a/include/asm-arm/arch-nexuspci/system.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/system.h - * - * Copyright (c) 1996, 97, 98, 99, 2000 FutureTV Labs Ltd. - */ - -/* - * 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. - */ - -#ifndef __ASM_ARCH_SYSTEM_H -#define __ASM_ARCH_SYSTEM_H - -static inline void arch_idle(void) -{ - cpu_do_idle(); -} - -#define arch_reset(mode) do { } while (0) - -#endif diff --git a/include/asm-arm/arch-nexuspci/time.h b/include/asm-arm/arch-nexuspci/time.h deleted file mode 100644 index c0fd0cdc9cb0..000000000000 --- a/include/asm-arm/arch-nexuspci/time.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/time.h - * - * Copyright (c) 1997, 1998, 1999, 2000 FutureTV Labs Ltd. - * - * The FTV PCI card has no real-time clock. We get timer ticks from the - * SCC chip. - */ - -/* - * 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. - */ - -static irqreturn_t -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - static int count = 25; - unsigned char stat = __raw_readb(DUART_BASE + 0x14); - if (!(stat & 0x10)) - return; /* Not for us */ - - /* Reset counter */ - __raw_writeb(0x90, DUART_BASE + 8); - - if (--count == 0) { - static int state = 1; - state ^= 1; - __raw_writeb(0x1a + state, INTCONT_BASE); - __raw_writeb(0x18 + state, INTCONT_BASE); - count = 50; - } - - /* Wait for slow rise time */ - __raw_readb(DUART_BASE + 0x14); - __raw_readb(DUART_BASE + 0x14); - __raw_readb(DUART_BASE + 0x14); - __raw_readb(DUART_BASE + 0x14); - __raw_readb(DUART_BASE + 0x14); - __raw_readb(DUART_BASE + 0x14); - - do_timer(regs); - - return IRQ_HANDLED; -} - -void __init time_init(void) -{ - int tick = 3686400 / 16 / 2 / 100; - - __raw_writeb(tick & 0xff, DUART_BASE + 0x1c); - __raw_writeb(tick >> 8, DUART_BASE + 0x18); - __raw_writeb(0x80, DUART_BASE + 8); - __raw_writeb(0x10, DUART_BASE + 0x14); - - timer_irq.handler = timer_interrupt; - timer_irq.flags = SA_SHIRQ; - - setup_irq(IRQ_TIMER, &timer_irq); -} diff --git a/include/asm-arm/arch-nexuspci/timex.h b/include/asm-arm/arch-nexuspci/timex.h deleted file mode 100644 index 63d4e2cd1938..000000000000 --- a/include/asm-arm/arch-nexuspci/timex.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/timex.h - * - * NexusPCI StrongARM card timex specifications - * - * Copyright (C) 1998 Philip Blundell - */ - diff --git a/include/asm-arm/arch-nexuspci/uncompress.h b/include/asm-arm/arch-nexuspci/uncompress.h deleted file mode 100644 index dd697a92466c..000000000000 --- a/include/asm-arm/arch-nexuspci/uncompress.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/uncompress.h - * - * Copyright (C) 1998, 1999, 2000 Philip Blundell - */ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <asm/hardware.h> -#include <asm/io.h> - -/* - * Write a character to the UART - */ -void _ll_write_char(char c) -{ - while (!(__raw_readb(DUART_START + 0x4) & 0x4)) - ; - __raw_writeb(c, DUART_START + 0xc); -} - -/* - * This does not append a newline - */ -static void puts(const char *s) -{ - while (*s) { - if (*s == '\n') - _ll_write_char('\r'); - _ll_write_char(*(s++)); - } -} - -/* - * Set up for decompression - */ -static void arch_decomp_setup(void) -{ - /* LED off */ - __raw_writel(INTCONT_LED, INTCONT_START); - - /* Set up SCC */ - __raw_writeb(42, DUART_START + 8); - __raw_writeb(48, DUART_START + 8); - __raw_writeb(16, DUART_START + 8); - __raw_writeb(0x93, DUART_START); - __raw_writeb(0x17, DUART_START); - __raw_writeb(0xbb, DUART_START + 4); - __raw_writeb(0x78, DUART_START + 16); - __raw_writeb(0xa0, DUART_START + 8); - __raw_writeb(5, DUART_START + 8); -} - -/* - * Stroke the watchdog so we don't get reset during decompression. - */ -static inline void arch_decomp_wdog(void) -{ - __raw_writel(INTCONT_WATCHDOG, INTCONT_START); - __raw_writel(INTCONT_WATCHDOG | 1, INTCONT_START); -} diff --git a/include/asm-arm/arch-nexuspci/vmalloc.h b/include/asm-arm/arch-nexuspci/vmalloc.h deleted file mode 100644 index 7e93df2307fc..000000000000 --- a/include/asm-arm/arch-nexuspci/vmalloc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/vmalloc.h - */ - -/* - * Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_END (PAGE_OFFSET + 0x20000000) diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h index 106af7555813..4f9e8c842d6d 100644 --- a/include/asm-arm/arch-omap/memory.h +++ b/include/asm-arm/arch-omap/memory.h @@ -57,12 +57,28 @@ /* * OMAP-1510 bus address is translated into a Local Bus address if the - * OMAP bus type is lbus. See dmadev_uses_omap_lbus(). + * OMAP bus type is lbus. We do the address translation based on the + * device overriding the defaults used in the dma-mapping API. */ #ifdef CONFIG_ARCH_OMAP1510 -#define bus_to_lbus(x) ((x) + (OMAP1510_LB_OFFSET - PHYS_OFFSET)) -#define lbus_to_bus(x) ((x) - (OMAP1510_LB_OFFSET - PHYS_OFFSET)) -#endif + +#define virt_to_lbus(x) ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET) +#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET) +#define is_lbus_device(dev) (cpu_is_omap1510() && dev->coherent_dma_mask == 0x0fffffff) + +#define __arch_page_to_dma(dev, page) ({is_lbus_device(dev) ? \ + (dma_addr_t)virt_to_lbus(page_address(page)) : \ + (dma_addr_t)__virt_to_bus(page_address(page));}) + +#define __arch_dma_to_virt(dev, addr) ({is_lbus_device(dev) ? \ + lbus_to_virt(addr) : \ + __bus_to_virt(addr);}) + +#define __arch_virt_to_dma(dev, addr) ({is_lbus_device(dev) ? \ + virt_to_lbus(addr) : \ + __virt_to_bus(addr);}) + +#endif /* CONFIG_ARCH_OMAP1510 */ #define PHYS_TO_NID(addr) (0) #endif diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h index ffd2fa2eb502..127fc1af12c0 100644 --- a/include/asm-arm/arch-pxa/hardware.h +++ b/include/asm-arm/arch-pxa/hardware.h @@ -83,6 +83,11 @@ typedef struct { volatile u32 offset[4096]; } __regbase; extern void pxa_gpio_mode( int gpio_mode ); /* + * Routine to enable or disable CKEN + */ +extern void pxa_set_cken(int clock, int enable); + +/* * return current memory and LCD clock frequency in units of 10kHz */ extern unsigned int get_memclk_frequency_10khz(void); diff --git a/include/asm-arm/arch-tbox/dma.h b/include/asm-arm/arch-tbox/dma.h deleted file mode 100644 index 1d5d39175671..000000000000 --- a/include/asm-arm/arch-tbox/dma.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/dma.h - * - * Architecture DMA routines. We have to contend with the bizarre DMA - * machine built into the Tbox hardware. - * - * Copyright (C) 1998 Philip Blundell - */ - -/* - * 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. - */ - -/* - * DMA channel definitions. Some of these are physically strange but - * we sort it out inside dma.c so the user never has to care. The - * exception is the double-buffering which we can't really abstract - * away sensibly. - */ -#define DMA_VIDEO 0 -#define DMA_MPEG_B 1 -#define DMA_AUDIO_B 2 -#define DMA_ASHRX_B 3 -#define DMA_ASHTX 4 -#define DMA_MPEG 5 -#define DMA_AUDIO 6 -#define DMA_ASHRX 7 - -#define MAX_DMA_CHANNELS 0 /* XXX */ - -/* - * This is the maximum DMA address that can be DMAd to. - */ -#define MAX_DMA_ADDRESS 0xffffffff diff --git a/include/asm-arm/arch-tbox/hardware.h b/include/asm-arm/arch-tbox/hardware.h deleted file mode 100644 index 9aa3f4508b46..000000000000 --- a/include/asm-arm/arch-tbox/hardware.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/hardware.h - * - * Copyright (C) 1998, 1999, 2000 Philip Blundell - * Copyright (C) 2000 FutureTV Labs Ltd - * - * This file contains the hardware definitions of the Tbox - */ - -/* - * 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. - */ - -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -/* Logical Physical - * 0xfff00000 0x00100000 I/O - * 0xfff00000 0x00100000 Expansion CS0 - * 0xfff10000 0x00110000 DMA - * 0xfff20000 0x00120000 C-Cube - * 0xfff30000 0x00130000 FPGA 1 - * 0xfff40000 0x00140000 UART 2 - * 0xfff50000 0x00150000 UART 1 - * 0xfff60000 0x00160000 CS8900 - * 0xfff70000 0x00170000 INTCONT - * 0xfff80000 0x00180000 RAMDAC - * 0xfff90000 0x00190000 Control 0 - * 0xfffa0000 0x001a0000 Control 1 - * 0xfffb0000 0x001b0000 Control 2 - * 0xfffc0000 0x001c0000 FPGA 2 - * 0xfffd0000 0x001d0000 INTRESET - * 0xfffe0000 0x001e0000 C-Cube DMA throttle - * 0xffff0000 0x001f0000 Expansion CS1 - * 0xffe00000 0x82000000 cache flush - */ - -/* - * Mapping areas - */ -#define IO_BASE 0xfff00000 -#define IO_START 0x00100000 -#define FLUSH_BASE 0xffe00000 - -#define INTCONT 0xfff70000 - -#define FPGA1CONT 0xffff3000 - -/* - * RAM definitions - */ -#define RAM_BASE 0x80000000 -#define FLUSH_BASE_PHYS 0x82000000 - -#define UNCACHEABLE_ADDR INTCONT - -#endif diff --git a/include/asm-arm/arch-tbox/io.h b/include/asm-arm/arch-tbox/io.h deleted file mode 100644 index 869798595c94..000000000000 --- a/include/asm-arm/arch-tbox/io.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/io.h - * - * Copyright (C) 1996-1999 Russell King - * Copyright (C) 1998, 1999 Philip Blundell - * - */ -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H - -#define IO_SPACE_LIMIT 0xffffffff - -#define __io(_x) ((_x) << 2) - -/* - * Generic virtual read/write - */ -static inline unsigned int __arch_getw(unsigned long a) -{ - unsigned int value; - __asm__ __volatile__("ldr%?h %0, [%1, #0] @ getw" - : "=&r" (value) - : "r" (a)); - return value; -} - -static inline void __arch_putw(unsigned int value, unsigned long a) -{ - __asm__ __volatile__("str%?h %0, [%1, #0] @ putw" - : : "r" (value), "r" (a)); -} - -/* Idem, for devices on the upper byte lanes */ -#define inb_u(p) __arch_getb(__io_pc(p) + 2) -#define inw_u(p) __arch_getw(__io_pc(p) + 2) - -#define outb_u(v,p) __arch_putb(v,__io_pc(p) + 2) -#define outw_u(v,p) __arch_putw(v,__io_pc(p) + 2) - -#endif diff --git a/include/asm-arm/arch-tbox/irqs.h b/include/asm-arm/arch-tbox/irqs.h deleted file mode 100644 index 1ee5eba6ea9d..000000000000 --- a/include/asm-arm/arch-tbox/irqs.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/irqs.h - * - * Copyright (C) 1998, 2000 Philip Blundell - */ - -/* - * 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. - */ - -#define IRQ_MPEGDMA 0 -#define IRQ_ASHTX 1 -#define IRQ_ASHRX 2 -#define IRQ_VSYNC 3 -#define IRQ_HSYNC 4 -#define IRQ_MPEG 5 -#define IRQ_UART2 6 -#define IRQ_UART1 7 -#define IRQ_ETHERNET 8 -#define IRQ_TIMER 9 -#define IRQ_AUDIODMA 10 -/* bit 11 used for video field ident */ -#define IRQ_EXPMODCS0 12 -#define IRQ_EXPMODCS1 13 - -#define irq_canonicalize(i) (i) diff --git a/include/asm-arm/arch-tbox/memory.h b/include/asm-arm/arch-tbox/memory.h deleted file mode 100644 index a20479487c9d..000000000000 --- a/include/asm-arm/arch-tbox/memory.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/memory.h - * - * Copyright (c) 1996-1999 Russell King. - * Copyright (c) 1998-1999 Phil Blundell - */ -#ifndef __ASM_ARCH_MEMORY_H -#define __ASM_ARCH_MEMORY_H - -/* - * Physical DRAM offset. - */ -#define PHYS_OFFSET (0x80000000UL) - -/* - * Bus view is the same as physical view - */ -#define __virt_to_bus(x) __virt_to_phys(x) -#define __bus_to_virt(x) __phys_to_virt(x) - -#endif diff --git a/include/asm-arm/arch-tbox/param.h b/include/asm-arm/arch-tbox/param.h deleted file mode 100644 index 4b47fe32b7c6..000000000000 --- a/include/asm-arm/arch-tbox/param.h +++ /dev/null @@ -1,4 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/param.h - */ -#define __KERNEL_HZ 1000 diff --git a/include/asm-arm/arch-tbox/serial.h b/include/asm-arm/arch-tbox/serial.h deleted file mode 100644 index 7e4aff996fd8..000000000000 --- a/include/asm-arm/arch-tbox/serial.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/serial.h - * - * Copyright (c) 1996 Russell King. - * Copyright (c) 1998 Phil Blundell - * - * Changelog: - * 15-10-1996 RMK Created - * 09-06-1998 PJB tbox version - */ -#ifndef __ASM_ARCH_SERIAL_H -#define __ASM_ARCH_SERIAL_H - -/* - * This assumes you have a 1.8432 MHz clock for your UART. - * - * It'd be nice if someone built a serial card with a 24.576 MHz - * clock, since the 16550A is capable of handling a top speed of 1.5 - * megabits/second; but this requires the faster clock. - */ -#define BASE_BAUD (1843200 / 16) - -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) - - /* UART CLK PORT IRQ FLAGS */ -#define STD_SERIAL_PORT_DEFNS \ - { 0, BASE_BAUD, 0xffff4000 >> 2, 6, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0xffff5000 >> 2, 7, STD_COM_FLAGS }, /* ttyS1 */ - -#define EXTRA_SERIAL_PORT_DEFNS - -#endif diff --git a/include/asm-arm/arch-tbox/system.h b/include/asm-arm/arch-tbox/system.h deleted file mode 100644 index da2cb88acb0c..000000000000 --- a/include/asm-arm/arch-tbox/system.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/system.h - * - * Copyright (c) 1996-1999 Russell King. - */ -#ifndef __ASM_ARCH_SYSTEM_H -#define __ASM_ARCH_SYSTEM_H - -static inline void arch_idle(void) -{ - cpu_do_idle(); -} - -#define arch_reset(mode) do { } while (0) - -#endif diff --git a/include/asm-arm/arch-tbox/time.h b/include/asm-arm/arch-tbox/time.h deleted file mode 100644 index 461787189e1e..000000000000 --- a/include/asm-arm/arch-tbox/time.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/time.h - * - * Copyright (c) 1997, 1999 Phil Blundell. - * Copyright (c) 2000 FutureTV Labs Ltd - * - * Tbox has no real-time clock -- we get millisecond ticks to update - * our soft copy. - */ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <asm/io.h> -#include <asm/hardware.h> - -#define update_rtc() - -static irqreturn_t -timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) -{ - /* Clear irq */ - __raw_writel(1, FPGA1CONT + 0xc); - __raw_writel(0, FPGA1CONT + 0xc); - - do_timer(regs); - - return IRQ_HANDLED; -} - -void __init time_init(void) -{ - timer_irq.handler = timer_interrupt; - setup_irq(IRQ_TIMER, &timer_irq); -} diff --git a/include/asm-arm/arch-tbox/timex.h b/include/asm-arm/arch-tbox/timex.h deleted file mode 100644 index c5489cd66ce7..000000000000 --- a/include/asm-arm/arch-tbox/timex.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/timex.h - * - * Tbox timex specifications - * - * Copyright (C) 1999 Philip Blundell - */ - diff --git a/include/asm-arm/arch-tbox/uncompress.h b/include/asm-arm/arch-tbox/uncompress.h deleted file mode 100644 index 17a5034e7812..000000000000 --- a/include/asm-arm/arch-tbox/uncompress.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * linux/include/asm-arm/arch-nexuspci/uncompress.h - * from linux/include/asm-arm/arch-ebsa110/uncompress.h - * - * Copyright (C) 1996,1997,1998 Russell King - * Copyright (C) 1998, 1999 Phil Blundell - */ - -#include <asm/io.h> - -#define UARTBASE 0x00400000 - -/* - * This does not append a newline - */ -static void puts(const char *s) -{ - while (*s) - { - char c = *(s++); - while (!(__raw_readb(UARTBASE + 0x14) & 0x20)); - __raw_writeb(c, UARTBASE); - if (c == 10) { - while (!(__raw_readb(UARTBASE + 0x14) & 0x20)); - __raw_writeb(13, UARTBASE); - } - } -} - -/* - * nothing to do - */ -#define arch_decomp_setup() - -/* - * Stroke the watchdog so we don't get reset during decompression. - */ -#define arch_decomp_wdog() \ - do { \ - __raw_writel(1, 0xa00000); \ - __raw_writel(0, 0xa00000); \ - } while (0) diff --git a/include/asm-arm/arch-tbox/vmalloc.h b/include/asm-arm/arch-tbox/vmalloc.h deleted file mode 100644 index da4a5c04f193..000000000000 --- a/include/asm-arm/arch-tbox/vmalloc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * linux/include/asm-arm/arch-tbox/vmalloc.h - */ - -/* - * Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h index 011c539c7449..b8750631dd09 100644 --- a/include/asm-arm/dma-mapping.h +++ b/include/asm-arm/dma-mapping.h @@ -124,7 +124,7 @@ dma_map_single(struct device *dev, void *cpu_addr, size_t size, enum dma_data_direction dir) { consistent_sync(cpu_addr, size, dir); - return __virt_to_bus((unsigned long)cpu_addr); + return virt_to_dma(dev, (unsigned long)cpu_addr); } #else extern dma_addr_t dma_map_single(struct device *,void *, size_t, enum dma_data_direction); @@ -231,7 +231,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, for (i = 0; i < nents; i++, sg++) { char *virt; - sg->dma_address = page_to_bus(sg->page) + sg->offset; + sg->dma_address = page_to_dma(dev, sg->page) + sg->offset; virt = page_address(sg->page) + sg->offset; consistent_sync(virt, sg->length, dir); } @@ -288,14 +288,14 @@ static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size, enum dma_data_direction dir) { - consistent_sync((void *)__bus_to_virt(handle), size, dir); + consistent_sync((void *)dma_to_virt(dev, handle), size, dir); } static inline void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size, enum dma_data_direction dir) { - consistent_sync((void *)__bus_to_virt(handle), size, dir); + consistent_sync((void *)dma_to_virt(dev, handle), size, dir); } #else extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction); diff --git a/include/asm-arm/fcntl.h b/include/asm-arm/fcntl.h index da2861ca37b0..485b6bdf4d7a 100644 --- a/include/asm-arm/fcntl.h +++ b/include/asm-arm/fcntl.h @@ -20,6 +20,7 @@ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ #define O_LARGEFILE 0400000 +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index 75da0b9c4960..91dee4da45ce 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h @@ -159,9 +159,18 @@ static inline void *phys_to_virt(unsigned long x) #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) /* + * Optional device DMA address remapping. Do _not_ use directly! * We should really eliminate virt_to_bus() here - it's deprecated. */ -#define page_to_bus(page) (virt_to_bus(page_address(page))) +#ifndef __arch_page_to_dma +#define page_to_dma(dev, page) ((dma_addr_t)__virt_to_bus(page_address(page))) +#define dma_to_virt(dev, addr) (__bus_to_virt(addr)) +#define virt_to_dma(dev, addr) (__virt_to_bus(addr)) +#else +#define page_to_dma(dev, page) (__arch_page_to_dma(dev, page)) +#define dma_to_virt(dev, addr) (__arch_dma_to_virt(dev, addr)) +#define virt_to_dma(dev, addr) (__arch_virt_to_dma(dev, addr)) +#endif #endif diff --git a/include/asm-arm26/fcntl.h b/include/asm-arm26/fcntl.h index da2861ca37b0..485b6bdf4d7a 100644 --- a/include/asm-arm26/fcntl.h +++ b/include/asm-arm26/fcntl.h @@ -20,6 +20,7 @@ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ #define O_LARGEFILE 0400000 +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-cris/fcntl.h b/include/asm-cris/fcntl.h index a68e2886e0c1..61c563242b51 100644 --- a/include/asm-cris/fcntl.h +++ b/include/asm-cris/fcntl.h @@ -22,6 +22,7 @@ #define O_LARGEFILE 0100000 #define O_DIRECTORY 0200000 /* must be a directory */ #define O_NOFOLLOW 0400000 /* don't follow links */ +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ diff --git a/include/asm-h8300/fcntl.h b/include/asm-h8300/fcntl.h index a7e7ac01d0d7..355350a57bf9 100644 --- a/include/asm-h8300/fcntl.h +++ b/include/asm-h8300/fcntl.h @@ -20,6 +20,7 @@ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ #define O_LARGEFILE 0400000 +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-i386/fcntl.h b/include/asm-i386/fcntl.h index 41e3c4d9144e..511cde94a3ed 100644 --- a/include/asm-i386/fcntl.h +++ b/include/asm-i386/fcntl.h @@ -20,6 +20,7 @@ #define O_LARGEFILE 0100000 #define O_DIRECTORY 0200000 /* must be a directory */ #define O_NOFOLLOW 0400000 /* don't follow links */ +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-i386/mach-default/setup_arch_post.h b/include/asm-i386/mach-default/setup_arch_post.h index 43b3b2d1fa11..2fc4888721f6 100644 --- a/include/asm-i386/mach-default/setup_arch_post.h +++ b/include/asm-i386/mach-default/setup_arch_post.h @@ -6,7 +6,7 @@ * use of all of the static functions. **/ -static inline char * __init machine_specific_memory_setup(void) +static char * __init machine_specific_memory_setup(void) { char *who; diff --git a/include/asm-i386/mach-visws/setup_arch_post.h b/include/asm-i386/mach-visws/setup_arch_post.h index 2857daf5af40..cdbd895a54b1 100644 --- a/include/asm-i386/mach-visws/setup_arch_post.h +++ b/include/asm-i386/mach-visws/setup_arch_post.h @@ -10,7 +10,7 @@ unsigned long sgivwfb_mem_size; long long mem_size __initdata = 0; -static inline char * __init machine_specific_memory_setup(void) +static char * __init machine_specific_memory_setup(void) { long long gfx_mem_size = 8 * MB; diff --git a/include/asm-i386/mach-voyager/setup_arch_post.h b/include/asm-i386/mach-voyager/setup_arch_post.h index 4c7cef49b8b2..f6f6c2cbc75c 100644 --- a/include/asm-i386/mach-voyager/setup_arch_post.h +++ b/include/asm-i386/mach-voyager/setup_arch_post.h @@ -3,7 +3,7 @@ * This is included late in kernel/setup.c so that it can make use of all of * the static functions. */ -static inline char * __init machine_specific_memory_setup(void) +static char * __init machine_specific_memory_setup(void) { char *who; diff --git a/include/asm-ia64/fcntl.h b/include/asm-ia64/fcntl.h index 697dd0bc0a8e..d193981bb1d8 100644 --- a/include/asm-ia64/fcntl.h +++ b/include/asm-ia64/fcntl.h @@ -28,6 +28,7 @@ #define O_LARGEFILE 0100000 #define O_DIRECTORY 0200000 /* must be a directory */ #define O_NOFOLLOW 0400000 /* don't follow links */ +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h index d3d94e85c8eb..7d2b1e4cd0f9 100644 --- a/include/asm-ia64/gcc_intrin.h +++ b/include/asm-ia64/gcc_intrin.h @@ -489,10 +489,16 @@ register unsigned long ia64_r13 asm ("r13") __attribute_used__; #define ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr)) #define ia64_ptcga(addr, size) \ - asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory") +do { \ + asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory"); \ + ia64_dv_serialize_data(); \ +} while (0) -#define ia64_ptcl(addr, size) \ - asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory") +#define ia64_ptcl(addr, size) \ +do { \ + asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory"); \ + ia64_dv_serialize_data(); \ +} while (0) #define ia64_ptri(addr, size) \ asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory") @@ -581,7 +587,7 @@ register unsigned long ia64_r13 asm ("r13") __attribute_used__; #define ia64_intrin_local_irq_restore(x) \ do { \ - asm volatile (" cmp.ne p6,p7=%0,r0;;" \ + asm volatile (";; cmp.ne p6,p7=%0,r0;;" \ "(p6) ssm psr.i;" \ "(p7) rsm psr.i;;" \ "(p6) srlz.d" \ diff --git a/include/asm-ia64/ia32.h b/include/asm-ia64/ia32.h index 75dd0d334b99..4fa4b8e12000 100644 --- a/include/asm-ia64/ia32.h +++ b/include/asm-ia64/ia32.h @@ -6,7 +6,8 @@ #include <asm/ptrace.h> #include <asm/signal.h> -#define IA32_NR_syscalls 283 /* length of syscall table */ +#define IA32_NR_syscalls 283 /* length of syscall table */ +#define IA32_PAGE_SHIFT 12 /* 4KB pages */ #ifndef __ASSEMBLY__ @@ -24,6 +25,13 @@ extern int ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs) /* Declare this unconditionally, so we don't get warnings for unreachable code. */ extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs); +#if PAGE_SHIFT > IA32_PAGE_SHIFT +extern int ia32_copy_partial_page_list (struct task_struct *, unsigned long); +extern void ia32_drop_partial_page_list (struct task_struct *); +#else +# define ia32_copy_partial_page_list(a1, a2) 0 +# define ia32_drop_partial_page_list(a1) do { ; } while (0) +#endif #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h index 5d930fdc0bea..bd07d11d9f37 100644 --- a/include/asm-ia64/irq.h +++ b/include/asm-ia64/irq.h @@ -30,6 +30,12 @@ extern void disable_irq_nosync (unsigned int); extern void enable_irq (unsigned int); extern void set_irq_affinity_info (unsigned int irq, int dest, int redir); +#ifdef CONFIG_SMP +extern void move_irq(int irq); +#else +#define move_irq(irq) +#endif + struct irqaction; struct pt_regs; int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 8d727c6b7836..c30329a308b4 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -297,11 +297,7 @@ ia64_phys_addr_valid (unsigned long addr) * works bypasses the caches, but does allow for consecutive writes to * be combined into single (but larger) write transactions. */ -#ifdef CONFIG_MCKINLEY_A0_SPECIFIC -# define pgprot_writecombine(prot) prot -#else -# define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC) -#endif +#define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC) static inline unsigned long pgd_index (unsigned long address) diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 05e9913e03b8..dec7d3fb1ba7 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -230,6 +230,7 @@ struct desc_struct { #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8) +struct partial_page_list; #endif struct thread_struct { @@ -251,6 +252,7 @@ struct thread_struct { __u64 fdr; /* IA32 fp except. data reg */ __u64 old_k1; /* old value of ar.k1 */ __u64 old_iob; /* old IOBase value */ + struct partial_page_list *ppl; /* partial page list for 4K page size issue */ /* cached TLS descriptors. */ struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; @@ -260,7 +262,8 @@ struct thread_struct { .fir = 0, \ .fdr = 0, \ .old_k1 = 0, \ - .old_iob = 0, + .old_iob = 0, \ + .ppl = 0, #else # define INIT_THREAD_IA32 #endif /* CONFIG_IA32_SUPPORT */ diff --git a/include/asm-ia64/sn/module.h b/include/asm-ia64/sn/module.h index b7c7dd2aba2b..172f459fc01e 100644 --- a/include/asm-ia64/sn/module.h +++ b/include/asm-ia64/sn/module.h @@ -180,7 +180,7 @@ struct module_s { }; /* module.c */ -extern module_t *modules[MODULE_MAX]; /* Indexed by cmoduleid_t */ +extern module_t *sn_modules[MODULE_MAX]; /* Indexed by cmoduleid_t */ extern int nummodules; extern module_t *module_lookup(moduleid_t id); diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 0c2343152136..cc063429344f 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -33,6 +33,7 @@ #define SN_SAL_NO_FAULT_ZONE_VIRTUAL 0x02000010 #define SN_SAL_NO_FAULT_ZONE_PHYSICAL 0x02000011 #define SN_SAL_PRINT_ERROR 0x02000012 +#define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant #define SN_SAL_CONSOLE_PUTC 0x02000021 #define SN_SAL_CONSOLE_GETC 0x02000022 #define SN_SAL_CONSOLE_PUTS 0x02000023 @@ -92,6 +93,19 @@ #define SALRET_INVALID_ARG -2 #define SALRET_ERROR -3 +/* + * SN_SAL_SET_ERROR_HANDLING_FEATURES bit settings + */ +enum +{ + /* if "rz always" is set, have the mca slaves call os_init_slave */ + SN_SAL_EHF_MCA_SLV_TO_OS_INIT_SLV=0, + /* do not rz on tlb checks, even if "rz always" is set */ + SN_SAL_EHF_NO_RZ_TLBC, + /* do not rz on PIO reads to I/O space, even if "rz always" is set */ + SN_SAL_EHF_NO_RZ_IO_READ, +}; + /** * sn_sal_rev_major - get the major SGI SAL revision number @@ -670,4 +684,24 @@ ia64_sn_sysctl_iobrick_pci_op(nasid_t n, u64 connection_type, return 0; } +/* + * Tell the prom how the OS wants to handle specific error features. + * It takes an array of 7 u64. + */ +static inline u64 +ia64_sn_set_error_handling_features(const u64 *feature_bits) +{ + struct ia64_sal_retval rv = {0, 0, 0, 0}; + + SAL_CALL_REENTRANT(rv, SN_SAL_SET_ERROR_HANDLING_FEATURES, + feature_bits[0], + feature_bits[1], + feature_bits[2], + feature_bits[3], + feature_bits[4], + feature_bits[5], + feature_bits[6]); + return rv.status; +} + #endif /* _ASM_IA64_SN_SN_SAL_H */ diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index 57c7db10a42e..83b2c1bc0ffe 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h @@ -171,7 +171,7 @@ do { \ # define local_irq_restore(x) __local_irq_restore(x) #endif /* !CONFIG_IA64_DEBUG_IRQ */ -#define local_irq_enable() ({ ia64_ssm(IA64_PSR_I); ia64_srlz_d(); }) +#define local_irq_enable() ({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); }) #define local_save_flags(flags) ({ ia64_stop(); (flags) = ia64_getreg(_IA64_REG_PSR); }) #define irqs_disabled() \ diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index ca3c7b958b1e..d46f47f9707e 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h @@ -266,6 +266,8 @@ #define NR_syscalls 256 /* length of syscall table */ +#define __ARCH_WANT_SYS_RT_SIGACTION + #ifdef CONFIG_IA32_SUPPORT # define __ARCH_WANT_SYS_FADVISE64 # define __ARCH_WANT_SYS_GETPGRP @@ -275,7 +277,6 @@ # define __ARCH_WANT_SYS_OLDUMOUNT # define __ARCH_WANT_SYS_SIGPENDING # define __ARCH_WANT_SYS_SIGPROCMASK -# define __ARCH_WANT_SYS_RT_SIGACTION #endif #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) diff --git a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h index d7ef37661179..3f867738062a 100644 --- a/include/asm-m68k/atomic.h +++ b/include/asm-m68k/atomic.h @@ -1,6 +1,8 @@ #ifndef __ARCH_M68K_ATOMIC__ #define __ARCH_M68K_ATOMIC__ +#include <asm/system.h> /* local_irq_XXX() */ + /* * Atomic operations that C can't guarantee us. Useful for * resource counting etc.. @@ -16,38 +18,124 @@ typedef struct { int counter; } atomic_t; #define atomic_read(v) ((v)->counter) #define atomic_set(v, i) (((v)->counter) = i) -static __inline__ void atomic_add(int i, atomic_t *v) +static inline void atomic_add(int i, atomic_t *v) +{ + __asm__ __volatile__("addl %1,%0" : "+m" (*v) : "id" (i)); +} + +static inline void atomic_sub(int i, atomic_t *v) +{ + __asm__ __volatile__("subl %1,%0" : "+m" (*v) : "id" (i)); +} + +static inline void atomic_inc(atomic_t *v) +{ + __asm__ __volatile__("addql #1,%0" : "+m" (*v)); +} + +static inline void atomic_dec(atomic_t *v) +{ + __asm__ __volatile__("subql #1,%0" : "+m" (*v)); +} + +static inline int atomic_dec_and_test(atomic_t *v) +{ + char c; + __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v)); + return c != 0; +} + +static inline int atomic_inc_and_test(atomic_t *v) +{ + char c; + __asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v)); + return c != 0; +} + +#ifdef CONFIG_RMW_INSNS +static inline int atomic_add_return(int i, atomic_t *v) { - __asm__ __volatile__("addl %1,%0" : "=m" (*v) : "id" (i), "0" (*v)); + int t, tmp; + + __asm__ __volatile__( + "1: movel %2,%1\n" + " addl %3,%1\n" + " casl %2,%1,%0\n" + " jne 1b" + : "+m" (*v), "=&d" (t), "=&d" (tmp) + : "g" (i), "2" (atomic_read(v))); + return t; } -static __inline__ void atomic_sub(int i, atomic_t *v) +static inline int atomic_sub_return(int i, atomic_t *v) { - __asm__ __volatile__("subl %1,%0" : "=m" (*v) : "id" (i), "0" (*v)); + int t, tmp; + + __asm__ __volatile__( + "1: movel %2,%1\n" + " subl %3,%1\n" + " casl %2,%1,%0\n" + " jne 1b" + : "+m" (*v), "=&d" (t), "=&d" (tmp) + : "g" (i), "2" (atomic_read(v))); + return t; +} +#else /* !CONFIG_RMW_INSNS */ +static inline int atomic_add_return(int i, atomic_t * v) +{ + unsigned long flags; + int t; + + local_irq_save(flags); + t = atomic_read(v); + t += i; + atomic_set(v, t); + local_irq_restore(flags); + + return t; } -static __inline__ void atomic_inc(volatile atomic_t *v) +static inline int atomic_sub_return(int i, atomic_t * v) { - __asm__ __volatile__("addql #1,%0" : "=m" (*v): "0" (*v)); + unsigned long flags; + int t; + + local_irq_save(flags); + t = atomic_read(v); + t -= i; + atomic_set(v, t); + local_irq_restore(flags); + + return t; } +#endif /* !CONFIG_RMW_INSNS */ + +#define atomic_dec_return(v) atomic_sub_return(1, (v)) +#define atomic_inc_return(v) atomic_add_return(1, (v)) -static __inline__ void atomic_dec(volatile atomic_t *v) +static inline int atomic_sub_and_test(int i, atomic_t *v) { - __asm__ __volatile__("subql #1,%0" : "=m" (*v): "0" (*v)); + char c; + __asm__ __volatile__("subl %2,%1; seq %0" : "=d" (c), "+m" (*v): "g" (i)); + return c != 0; } -static __inline__ int atomic_dec_and_test(volatile atomic_t *v) +static inline int atomic_add_negative(int i, atomic_t *v) { char c; - __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "=m" (*v): "1" (*v)); + __asm__ __volatile__("addl %2,%1; smi %0" : "=d" (c), "+m" (*v): "g" (i)); return c != 0; } -#define atomic_clear_mask(mask, v) \ - __asm__ __volatile__("andl %1,%0" : "=m" (*v) : "id" (~(mask)),"0"(*v)) +static inline void atomic_clear_mask(unsigned long mask, unsigned long *v) +{ + __asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask))); +} -#define atomic_set_mask(mask, v) \ - __asm__ __volatile__("orl %1,%0" : "=m" (*v) : "id" (mask),"0"(*v)) +static inline void atomic_set_mask(unsigned long mask, unsigned long *v) +{ + __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask)); +} /* Atomic operations are already serializing */ #define smp_mb__before_atomic_dec() barrier() diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h index ec1e32ecb914..05ccc865d77b 100644 --- a/include/asm-m68k/bitops.h +++ b/include/asm-m68k/bitops.h @@ -23,25 +23,24 @@ #define __test_and_set_bit(nr,vaddr) test_and_set_bit(nr,vaddr) -static inline int __constant_test_and_set_bit(int nr, - volatile unsigned long *vaddr) +static inline int __constant_test_and_set_bit(int nr, unsigned long *vaddr) { + char *p = (char *)vaddr + (nr ^ 31) / 8; char retval; __asm__ __volatile__ ("bset %2,%1; sne %0" - : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) - : "di" (nr & 7)); + : "=d" (retval), "+m" (*p) + : "di" (nr & 7)); return retval; } -static inline int __generic_test_and_set_bit(int nr, - volatile unsigned long *vaddr) +static inline int __generic_test_and_set_bit(int nr, unsigned long *vaddr) { char retval; - __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); + __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory"); return retval; } @@ -53,16 +52,17 @@ static inline int __generic_test_and_set_bit(int nr, #define __set_bit(nr,vaddr) set_bit(nr,vaddr) -static inline void __constant_set_bit(int nr, volatile unsigned long *vaddr) +static inline void __constant_set_bit(int nr, unsigned long *vaddr) { + char *p = (char *)vaddr + (nr ^ 31) / 8; __asm__ __volatile__ ("bset %1,%0" - : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); + : "+m" (*p) : "di" (nr & 7)); } -static inline void __generic_set_bit(int nr, volatile unsigned long *vaddr) +static inline void __generic_set_bit(int nr, unsigned long *vaddr) { - __asm__ __volatile__ ("bfset %1@{%0:#1}" - : : "d" (nr^31), "a" (vaddr) : "memory"); + __asm__ __volatile__ ("bfset %1{%0:#1}" + : : "d" (nr^31), "o" (*vaddr) : "memory"); } #define test_and_clear_bit(nr,vaddr) \ @@ -72,25 +72,24 @@ static inline void __generic_set_bit(int nr, volatile unsigned long *vaddr) #define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr) -static inline int __constant_test_and_clear_bit(int nr, - volatile unsigned long *vaddr) +static inline int __constant_test_and_clear_bit(int nr, unsigned long *vaddr) { + char *p = (char *)vaddr + (nr ^ 31) / 8; char retval; __asm__ __volatile__ ("bclr %2,%1; sne %0" - : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) - : "di" (nr & 7)); + : "=d" (retval), "+m" (*p) + : "di" (nr & 7)); return retval; } -static inline int __generic_test_and_clear_bit(int nr, - volatile unsigned long *vaddr) +static inline int __generic_test_and_clear_bit(int nr, unsigned long *vaddr) { char retval; - __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); + __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory"); return retval; } @@ -107,16 +106,17 @@ static inline int __generic_test_and_clear_bit(int nr, __generic_clear_bit(nr, vaddr)) #define __clear_bit(nr,vaddr) clear_bit(nr,vaddr) -static inline void __constant_clear_bit(int nr, volatile unsigned long *vaddr) +static inline void __constant_clear_bit(int nr, unsigned long *vaddr) { + char *p = (char *)vaddr + (nr ^ 31) / 8; __asm__ __volatile__ ("bclr %1,%0" - : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); + : "+m" (*p) : "di" (nr & 7)); } -static inline void __generic_clear_bit(int nr, volatile unsigned long *vaddr) +static inline void __generic_clear_bit(int nr, unsigned long *vaddr) { - __asm__ __volatile__ ("bfclr %1@{%0:#1}" - : : "d" (nr^31), "a" (vaddr) : "memory"); + __asm__ __volatile__ ("bfclr %1{%0:#1}" + : : "d" (nr^31), "o" (*vaddr) : "memory"); } #define test_and_change_bit(nr,vaddr) \ @@ -127,25 +127,24 @@ static inline void __generic_clear_bit(int nr, volatile unsigned long *vaddr) #define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr) #define __change_bit(nr,vaddr) change_bit(nr,vaddr) -static inline int __constant_test_and_change_bit(int nr, - volatile unsigned long *vaddr) +static inline int __constant_test_and_change_bit(int nr, unsigned long *vaddr) { + char *p = (char *)vaddr + (nr ^ 31) / 8; char retval; __asm__ __volatile__ ("bchg %2,%1; sne %0" - : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) - : "di" (nr & 7)); + : "=d" (retval), "+m" (*p) + : "di" (nr & 7)); return retval; } -static inline int __generic_test_and_change_bit(int nr, - volatile unsigned long *vaddr) +static inline int __generic_test_and_change_bit(int nr, unsigned long *vaddr) { char retval; - __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); + __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory"); return retval; } @@ -155,21 +154,22 @@ static inline int __generic_test_and_change_bit(int nr, __constant_change_bit(nr, vaddr) : \ __generic_change_bit(nr, vaddr)) -static inline void __constant_change_bit(int nr, volatile unsigned long *vaddr) +static inline void __constant_change_bit(int nr, unsigned long *vaddr) { + char *p = (char *)vaddr + (nr ^ 31) / 8; __asm__ __volatile__ ("bchg %1,%0" - : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); + : "+m" (*p) : "di" (nr & 7)); } -static inline void __generic_change_bit(int nr, volatile unsigned long *vaddr) +static inline void __generic_change_bit(int nr, unsigned long *vaddr) { - __asm__ __volatile__ ("bfchg %1@{%0:#1}" - : : "d" (nr^31), "a" (vaddr) : "memory"); + __asm__ __volatile__ ("bfchg %1{%0:#1}" + : : "d" (nr^31), "o" (*vaddr) : "memory"); } -static inline int test_bit(int nr, const volatile unsigned long *vaddr) +static inline int test_bit(int nr, const unsigned long *vaddr) { - return ((1UL << (nr & 31)) & (((const volatile unsigned long *) vaddr)[nr >> 5])) != 0; + return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0; } static inline int find_first_zero_bit(const unsigned long *vaddr, @@ -364,76 +364,27 @@ static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size) return ((p - addr) << 4) + (res ^ 31); } -static inline int minix_test_and_set_bit(int nr, volatile void *vaddr) -{ - char retval; - - __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *)vaddr) : "memory"); - - return retval; -} - -#define minix_set_bit(nr,addr) ((void)minix_test_and_set_bit(nr,addr)) +#define minix_test_and_set_bit(nr, addr) test_and_set_bit((nr) ^ 16, (unsigned long *)(addr)) +#define minix_set_bit(nr,addr) set_bit((nr) ^ 16, (unsigned long *)(addr)) +#define minix_test_and_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 16, (unsigned long *)(addr)) -static inline int minix_test_and_clear_bit(int nr, volatile void *vaddr) +static inline int minix_test_bit(int nr, const void *vaddr) { - char retval; - - __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *) vaddr) : "memory"); - - return retval; -} - -static inline int minix_test_bit(int nr, const volatile void *vaddr) -{ - return ((1U << (nr & 15)) & (((const volatile unsigned short *) vaddr)[nr >> 4])) != 0; + const unsigned short *p = vaddr; + return (p[nr >> 4] & (1U << (nr & 15))) != 0; } /* Bitmap functions for the ext2 filesystem. */ -static inline int ext2_set_bit(int nr, volatile void *vaddr) -{ - char retval; - - __asm__ __volatile__ ("bfset %2{%1,#1}; sne %0" - : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory"); - - return retval; -} - -static inline int ext2_clear_bit(int nr, volatile void *vaddr) -{ - char retval; - - __asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0" - : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory"); - - return retval; -} +#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 24, (unsigned long *)(addr)) +#define ext2_set_bit_atomic(lock, nr, addr) test_and_set_bit((nr) ^ 24, (unsigned long *)(addr)) +#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr)) +#define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr)) -#define ext2_set_bit_atomic(lock, nr, addr) \ - ({ \ - int ret; \ - spin_lock(lock); \ - ret = ext2_set_bit((nr), (addr)); \ - spin_unlock(lock); \ - ret; \ - }) - -#define ext2_clear_bit_atomic(lock, nr, addr) \ - ({ \ - int ret; \ - spin_lock(lock); \ - ret = ext2_clear_bit((nr), (addr)); \ - spin_unlock(lock); \ - ret; \ - }) - -static inline int ext2_test_bit(int nr, const volatile void *vaddr) +static inline int ext2_test_bit(int nr, const void *vaddr) { - return ((1U << (nr & 7)) & (((const volatile unsigned char *) vaddr)[nr >> 3])) != 0; + const unsigned char *p = vaddr; + return (p[nr >> 3] & (1U << (nr & 7))) != 0; } static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size) diff --git a/include/asm-m68k/fcntl.h b/include/asm-m68k/fcntl.h index c0b273f68f05..0d4212983a33 100644 --- a/include/asm-m68k/fcntl.h +++ b/include/asm-m68k/fcntl.h @@ -20,6 +20,7 @@ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ #define O_LARGEFILE 0400000 +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-m68k/io.h b/include/asm-m68k/io.h index aa6fffff2084..d32a489f4800 100644 --- a/include/asm-m68k/io.h +++ b/include/asm-m68k/io.h @@ -120,7 +120,7 @@ extern int isa_sex; * be compiled in so the case statement will be optimised away */ -static inline u8 *isa_itb(long addr) +static inline u8 *isa_itb(unsigned long addr) { switch(ISA_TYPE) { @@ -136,7 +136,7 @@ static inline u8 *isa_itb(long addr) default: return 0; /* avoid warnings, just in case */ } } -static inline u16 *isa_itw(long addr) +static inline u16 *isa_itw(unsigned long addr) { switch(ISA_TYPE) { @@ -152,7 +152,7 @@ static inline u16 *isa_itw(long addr) default: return 0; /* avoid warnings, just in case */ } } -static inline u8 *isa_mtb(long addr) +static inline u8 *isa_mtb(unsigned long addr) { switch(ISA_TYPE) { @@ -168,7 +168,7 @@ static inline u8 *isa_mtb(long addr) default: return 0; /* avoid warnings, just in case */ } } -static inline u16 *isa_mtw(long addr) +static inline u16 *isa_mtw(unsigned long addr) { switch(ISA_TYPE) { @@ -191,10 +191,14 @@ static inline u16 *isa_mtw(long addr) #define isa_outb(val,port) out_8(isa_itb(port),(val)) #define isa_outw(val,port) (ISA_SEX ? out_be16(isa_itw(port),(val)) : out_le16(isa_itw(port),(val))) -#define isa_readb(p) in_8(isa_mtb(p)) -#define isa_readw(p) (ISA_SEX ? in_be16(isa_mtw(p)) : in_le16(isa_mtw(p))) -#define isa_writeb(val,p) out_8(isa_mtb(p),(val)) -#define isa_writew(val,p) (ISA_SEX ? out_be16(isa_mtw(p),(val)) : out_le16(isa_mtw(p),(val))) +#define isa_readb(p) in_8(isa_mtb((unsigned long)(p))) +#define isa_readw(p) \ + (ISA_SEX ? in_be16(isa_mtw((unsigned long)(p))) \ + : in_le16(isa_mtw((unsigned long)(p)))) +#define isa_writeb(val,p) out_8(isa_mtb((unsigned long)(p)),(val)) +#define isa_writew(val,p) \ + (ISA_SEX ? out_be16(isa_mtw((unsigned long)(p)),(val)) \ + : out_le16(isa_mtw((unsigned long)(p)),(val))) static inline void isa_delay(void) { @@ -215,17 +219,21 @@ static inline void isa_delay(void) #define isa_inb_p(p) ({u8 v=isa_inb(p);isa_delay();v;}) #define isa_outb_p(v,p) ({isa_outb((v),(p));isa_delay();}) +#define isa_inw_p(p) ({u16 v=isa_inw(p);isa_delay();v;}) +#define isa_outw_p(v,p) ({isa_outw((v),(p));isa_delay();}) +#define isa_inl_p(p) ({u32 v=isa_inl(p);isa_delay();v;}) +#define isa_outl_p(v,p) ({isa_outl((v),(p));isa_delay();}) -#define isa_insb(port, buf, nr) raw_insb(isa_itb(port), (buf), (nr)) -#define isa_outsb(port, buf, nr) raw_outsb(isa_itb(port), (buf), (nr)) +#define isa_insb(port, buf, nr) raw_insb(isa_itb(port), (u8 *)(buf), (nr)) +#define isa_outsb(port, buf, nr) raw_outsb(isa_itb(port), (u8 *)(buf), (nr)) #define isa_insw(port, buf, nr) \ - (ISA_SEX ? raw_insw(isa_itw(port), (buf), (nr)) : \ - raw_insw_swapw(isa_itw(port), (buf), (nr))) + (ISA_SEX ? raw_insw(isa_itw(port), (u16 *)(buf), (nr)) : \ + raw_insw_swapw(isa_itw(port), (u16 *)(buf), (nr))) #define isa_outsw(port, buf, nr) \ - (ISA_SEX ? raw_outsw(isa_itw(port), (buf), (nr)) : \ - raw_outsw_swapw(isa_itw(port), (buf), (nr))) + (ISA_SEX ? raw_outsw(isa_itw(port), (u16 *)(buf), (nr)) : \ + raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr))) #endif /* CONFIG_ISA */ @@ -235,9 +243,13 @@ static inline void isa_delay(void) #define outb isa_outb #define outb_p isa_outb_p #define inw isa_inw +#define inw_p isa_inw_p #define outw isa_outw +#define outw_p isa_outw_p #define inl isa_inw +#define inl_p isa_inw_p #define outl isa_outw +#define outl_p isa_outw_p #define insb isa_insb #define insw isa_insw #define outsb isa_outsb @@ -281,10 +293,16 @@ static inline void isa_delay(void) #define inb(port) ((port)<1024 ? isa_inb(port) : in_8(port)) #define inb_p(port) ((port)<1024 ? isa_inb_p(port) : in_8(port)) #define inw(port) ((port)<1024 ? isa_inw(port) : in_le16(port)) +#define inw_p(port) ((port)<1024 ? isa_inw_p(port) : in_le16(port)) +#define inl(port) ((port)<1024 ? isa_inl(port) : in_le32(port)) +#define inl_p(port) ((port)<1024 ? isa_inl_p(port) : in_le32(port)) #define outb(val,port) ((port)<1024 ? isa_outb((val),(port)) : out_8((port),(val))) #define outb_p(val,port) ((port)<1024 ? isa_outb_p((val),(port)) : out_8((port),(val))) #define outw(val,port) ((port)<1024 ? isa_outw((val),(port)) : out_le16((port),(val))) +#define outw_p(val,port) ((port)<1024 ? isa_outw_p((val),(port)) : out_le16((port),(val))) +#define outl(val,port) ((port)<1024 ? isa_outl((val),(port)) : out_le32((port),(val))) +#define outl_p(val,port) ((port)<1024 ? isa_outl_p((val),(port)) : out_le32((port),(val))) #endif #endif /* CONFIG_PCI */ diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h index 6b7d6a040b49..99a516709210 100644 --- a/include/asm-m68k/page.h +++ b/include/asm-m68k/page.h @@ -52,15 +52,13 @@ static inline void copy_page(void *to, void *from) static inline void clear_page(void *page) { - unsigned long data, tmp; - void *sp = page; + unsigned long tmp; + unsigned long *sp = page; - data = 0; - - *((unsigned long *)(page))++ = 0; - *((unsigned long *)(page))++ = 0; - *((unsigned long *)(page))++ = 0; - *((unsigned long *)(page))++ = 0; + *sp++ = 0; + *sp++ = 0; + *sp++ = 0; + *sp++ = 0; __asm__ __volatile__("1:\t" ".chip 68040\n\t" @@ -69,8 +67,8 @@ static inline void clear_page(void *page) "subqw #8,%2\n\t" "subqw #8,%2\n\t" "dbra %1,1b\n\t" - : "=a" (page), "=d" (tmp) - : "a" (sp), "0" (page), + : "=a" (sp), "=d" (tmp) + : "a" (page), "0" (sp), "1" ((PAGE_SIZE - 16) / 16 - 1)); } diff --git a/include/asm-m68k/string.h b/include/asm-m68k/string.h index 7ea5dc8e78db..44def078132a 100644 --- a/include/asm-m68k/string.h +++ b/include/asm-m68k/string.h @@ -290,9 +290,7 @@ static inline void * __memset_g(void * s, int c, size_t count) static inline void * __memset_page(void * s,int c,size_t count) { unsigned long data, tmp; - void *xs, *sp; - - xs = sp = s; + void *xs = s; c = c & 255; data = c | (c << 8); @@ -303,10 +301,11 @@ static inline void * __memset_page(void * s,int c,size_t count) if (((unsigned long) s) & 0x0f) __memset_g(s, c, count); else{ - *((unsigned long *)(s))++ = data; - *((unsigned long *)(s))++ = data; - *((unsigned long *)(s))++ = data; - *((unsigned long *)(s))++ = data; + unsigned long *sp = s; + *sp++ = data; + *sp++ = data; + *sp++ = data; + *sp++ = data; __asm__ __volatile__("1:\t" ".chip 68040\n\t" @@ -315,8 +314,8 @@ static inline void * __memset_page(void * s,int c,size_t count) "subqw #8,%2\n\t" "subqw #8,%2\n\t" "dbra %1,1b\n\t" - : "=a" (s), "=d" (tmp) - : "a" (sp), "0" (s), "1" ((count - 16) / 16 - 1) + : "=a" (sp), "=d" (tmp) + : "a" (s), "0" (sp), "1" ((count - 16) / 16 - 1) ); } diff --git a/include/asm-m68k/ucontext.h b/include/asm-m68k/ucontext.h index fb6d732ad7b2..e4e22669edc0 100644 --- a/include/asm-m68k/ucontext.h +++ b/include/asm-m68k/ucontext.h @@ -6,10 +6,8 @@ typedef int greg_t; typedef greg_t gregset_t[NGREG]; typedef struct fpregset { - int f_pcr; - int f_psr; - int f_fpiaddr; - int f_fpregs[8][3]; + int f_fpcntl[3]; + int f_fpregs[8*3]; } fpregset_t; struct mcontext { diff --git a/include/asm-mips/fcntl.h b/include/asm-mips/fcntl.h index e2b9c0a2537b..2436392e7990 100644 --- a/include/asm-mips/fcntl.h +++ b/include/asm-mips/fcntl.h @@ -26,6 +26,7 @@ #define O_DIRECT 0x8000 /* direct disk access hint */ #define O_DIRECTORY 0x10000 /* must be a directory */ #define O_NOFOLLOW 0x20000 /* don't follow links */ +#define O_NOATIME 0x40000 #define O_NDELAY O_NONBLOCK diff --git a/include/asm-parisc/fcntl.h b/include/asm-parisc/fcntl.h index 01fe48b0ba9d..def35230716a 100644 --- a/include/asm-parisc/fcntl.h +++ b/include/asm-parisc/fcntl.h @@ -19,6 +19,7 @@ #define O_NOCTTY 00400000 /* not fcntl */ #define O_DSYNC 01000000 /* HPUX only */ #define O_RSYNC 02000000 /* HPUX only */ +#define O_NOATIME 04000000 #define FASYNC 00020000 /* fcntl, for BSD compatibility */ #define O_DIRECT 00040000 /* direct disk access hint - currently ignored */ diff --git a/include/asm-ppc/fcntl.h b/include/asm-ppc/fcntl.h index 27ae7d2f6af2..5e28e41fb29f 100644 --- a/include/asm-ppc/fcntl.h +++ b/include/asm-ppc/fcntl.h @@ -20,6 +20,7 @@ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_LARGEFILE 0200000 #define O_DIRECT 0400000 /* direct disk access hint */ +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h index 928dc5e39df5..3ca700cb04bc 100644 --- a/include/asm-ppc64/eeh.h +++ b/include/asm-ppc64/eeh.h @@ -55,6 +55,7 @@ void __init pci_addr_cache_build(void); * device (including config space i/o). Call eeh_add_device_late * to finish the eeh setup for this device. */ +struct device_node; void eeh_add_device_early(struct device_node *); void eeh_add_device_late(struct pci_dev *); diff --git a/include/asm-ppc64/fcntl.h b/include/asm-ppc64/fcntl.h index 1ef83570b4e4..842560d50656 100644 --- a/include/asm-ppc64/fcntl.h +++ b/include/asm-ppc64/fcntl.h @@ -27,6 +27,7 @@ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_LARGEFILE 0200000 #define O_DIRECT 0400000 /* direct disk access hint */ +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h index 8d8a6f89c740..67ac484a14cd 100644 --- a/include/asm-ppc64/system.h +++ b/include/asm-ppc64/system.h @@ -112,13 +112,21 @@ extern int _get_PVR(void); extern void giveup_fpu(struct task_struct *); extern void disable_kernel_fp(void); extern void flush_fp_to_thread(struct task_struct *); -extern void flush_altivec_to_thread(struct task_struct *); extern void enable_kernel_fp(void); extern void giveup_altivec(struct task_struct *); extern void disable_kernel_altivec(void); extern void enable_kernel_altivec(void); extern void cvt_fd(float *from, double *to, unsigned long *fpscr); extern void cvt_df(double *from, float *to, unsigned long *fpscr); + +#ifdef CONFIG_ALTIVEC +extern void flush_altivec_to_thread(struct task_struct *); +#else +static inline void flush_altivec_to_thread(struct task_struct *t) +{ +} +#endif + extern int abs(int); extern struct task_struct *__switch_to(struct task_struct *, diff --git a/include/asm-s390/fcntl.h b/include/asm-s390/fcntl.h index 307c01b45213..48f692b45732 100644 --- a/include/asm-s390/fcntl.h +++ b/include/asm-s390/fcntl.h @@ -27,6 +27,7 @@ #define O_LARGEFILE 0100000 #define O_DIRECTORY 0200000 /* must be a directory */ #define O_NOFOLLOW 0400000 /* don't follow links */ +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-sh/fcntl.h b/include/asm-sh/fcntl.h index 21e39b7cc05a..0b3ae524e34c 100644 --- a/include/asm-sh/fcntl.h +++ b/include/asm-sh/fcntl.h @@ -20,6 +20,7 @@ #define O_LARGEFILE 0100000 #define O_DIRECTORY 0200000 /* must be a directory */ #define O_NOFOLLOW 0400000 /* don't follow links */ +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-sparc/fcntl.h b/include/asm-sparc/fcntl.h index aa64cfc1df2e..df9c75d41d68 100644 --- a/include/asm-sparc/fcntl.h +++ b/include/asm-sparc/fcntl.h @@ -21,6 +21,7 @@ #define O_NOFOLLOW 0x20000 /* don't follow links */ #define O_LARGEFILE 0x40000 #define O_DIRECT 0x100000 /* direct disk access hint */ +#define O_NOATIME 0x200000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-sparc64/fcntl.h b/include/asm-sparc64/fcntl.h index 0999d6d525c1..e36def0d0d80 100644 --- a/include/asm-sparc64/fcntl.h +++ b/include/asm-sparc64/fcntl.h @@ -21,6 +21,7 @@ #define O_NOFOLLOW 0x20000 /* don't follow links */ #define O_LARGEFILE 0x40000 #define O_DIRECT 0x100000 /* direct disk access hint */ +#define O_NOATIME 0x200000 #define F_DUPFD 0 /* dup */ diff --git a/include/asm-v850/fcntl.h b/include/asm-v850/fcntl.h index 42e358ff0752..31d4b5961221 100644 --- a/include/asm-v850/fcntl.h +++ b/include/asm-v850/fcntl.h @@ -20,6 +20,7 @@ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ #define O_LARGEFILE 0400000 +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/asm-x86_64/fcntl.h b/include/asm-x86_64/fcntl.h index aabf1a30a3b9..4411f221c037 100644 --- a/include/asm-x86_64/fcntl.h +++ b/include/asm-x86_64/fcntl.h @@ -20,6 +20,7 @@ #define O_LARGEFILE 0100000 #define O_DIRECTORY 0200000 /* must be a directory */ #define O_NOFOLLOW 0400000 /* don't follow links */ +#define O_NOATIME 01000000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff --git a/include/linux/affs_fs.h b/include/linux/affs_fs.h index c849309b1131..5ba9d6205dc0 100644 --- a/include/linux/affs_fs.h +++ b/include/linux/affs_fs.h @@ -36,7 +36,8 @@ extern u32 affs_count_free_bits(u32 blocksize, const void *data); extern u32 affs_count_free_blocks(struct super_block *s); extern void affs_free_block(struct super_block *sb, u32 block); extern u32 affs_alloc_block(struct inode *inode, u32 goal); -extern int affs_init_bitmap(struct super_block *sb); +extern int affs_init_bitmap(struct super_block *sb, int *flags); +extern void affs_free_bitmap(struct super_block *sb); /* namei.c */ diff --git a/include/linux/affs_fs_sb.h b/include/linux/affs_fs_sb.h index d2f86715cf1c..d722befe1ced 100644 --- a/include/linux/affs_fs_sb.h +++ b/include/linux/affs_fs_sb.h @@ -47,7 +47,6 @@ struct affs_sb_info { #define SF_OFS 0x0200 /* Old filesystem */ #define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */ #define SF_VERBOSE 0x0800 /* Talk about fs when mounting */ -#define SF_READONLY 0x1000 /* Don't allow to remount rw */ /* short cut to get to the affs specific sb data */ static inline struct affs_sb_info *AFFS_SB(struct super_block *sb) diff --git a/include/linux/bio.h b/include/linux/bio.h index c4dd287dd1c8..601531cf4976 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -25,6 +25,15 @@ /* Platforms may set this to teach the BIO layer about IOMMU hardware. */ #include <asm/io.h> + +#if defined(BIO_VMERGE_MAX_SIZE) && defined(BIO_VMERGE_BOUNDARY) +#define BIOVEC_VIRT_START_SIZE(x) (bvec_to_phys(x) & (BIO_VMERGE_BOUNDARY - 1)) +#define BIOVEC_VIRT_OVERSIZE(x) ((x) > BIO_VMERGE_MAX_SIZE) +#else +#define BIOVEC_VIRT_START_SIZE(x) 0 +#define BIOVEC_VIRT_OVERSIZE(x) 0 +#endif + #ifndef BIO_VMERGE_BOUNDARY #define BIO_VMERGE_BOUNDARY 0 #endif @@ -81,6 +90,15 @@ struct bio { unsigned short bi_hw_segments; unsigned int bi_size; /* residual I/O count */ + + /* + * To keep track of the max hw size, we account for the + * sizes of the first and last virtually mergeable segments + * in this bio + */ + unsigned int bi_hw_front_size; + unsigned int bi_hw_back_size; + unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ struct bio_vec *bi_io_vec; /* the actual vec list */ diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 6902724691d2..e038f9a3d0ef 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -67,4 +67,12 @@ extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, __alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0) #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ +extern void *__init alloc_large_system_hash(const char *tablename, + unsigned long bucketsize, + unsigned long numentries, + int scale, + int consider_highmem, + unsigned int *_hash_shift, + unsigned int *_hash_mask); + #endif /* _LINUX_BOOTMEM_H */ diff --git a/include/linux/dmi.h b/include/linux/dmi.h new file mode 100644 index 000000000000..d2bcf556088b --- /dev/null +++ b/include/linux/dmi.h @@ -0,0 +1,47 @@ +#ifndef __DMI_H__ +#define __DMI_H__ + +enum dmi_field { + DMI_NONE, + DMI_BIOS_VENDOR, + DMI_BIOS_VERSION, + DMI_BIOS_DATE, + DMI_SYS_VENDOR, + DMI_PRODUCT_NAME, + DMI_PRODUCT_VERSION, + DMI_BOARD_VENDOR, + DMI_BOARD_NAME, + DMI_BOARD_VERSION, + DMI_STRING_MAX, +}; + +/* + * DMI callbacks for problem boards + */ +struct dmi_strmatch { + u8 slot; + char *substr; +}; + +struct dmi_system_id { + int (*callback)(struct dmi_system_id *); + char *ident; + struct dmi_strmatch matches[4]; + void *driver_data; +}; + +#define DMI_MATCH(a,b) { a, b } + +#if defined(CONFIG_X86) && !defined(CONFIG_X86_64) + +extern int dmi_check_system(struct dmi_system_id *list); +extern char * dmi_get_system_info(int field); + +#else + +static inline int dmi_check_system(struct dmi_system_id *list) { return 0; } +static inline char * dmi_get_system_info(int field) { return NULL; } + +#endif + +#endif /* __DMI_H__ */ diff --git a/include/linux/ds1286.h b/include/linux/ds1286.h new file mode 100644 index 000000000000..d8989860e4ce --- /dev/null +++ b/include/linux/ds1286.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 1998, 1999, 2003 Ralf Baechle + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __LINUX_DS1286_H +#define __LINUX_DS1286_H + +#include <asm/ds1286.h> + +/********************************************************************** + * register summary + **********************************************************************/ +#define RTC_HUNDREDTH_SECOND 0 +#define RTC_SECONDS 1 +#define RTC_MINUTES 2 +#define RTC_MINUTES_ALARM 3 +#define RTC_HOURS 4 +#define RTC_HOURS_ALARM 5 +#define RTC_DAY 6 +#define RTC_DAY_ALARM 7 +#define RTC_DATE 8 +#define RTC_MONTH 9 +#define RTC_YEAR 10 +#define RTC_CMD 11 +#define RTC_WHSEC 12 +#define RTC_WSEC 13 +#define RTC_UNUSED 14 + +/* RTC_*_alarm is always true if 2 MSBs are set */ +# define RTC_ALARM_DONT_CARE 0xC0 + + +/* + * Bits in the month register + */ +#define RTC_EOSC 0x80 +#define RTC_ESQW 0x40 + +/* + * Bits in the Command register + */ +#define RTC_TDF 0x01 +#define RTC_WAF 0x02 +#define RTC_TDM 0x04 +#define RTC_WAM 0x08 +#define RTC_PU_LVL 0x10 +#define RTC_IBH_LO 0x20 +#define RTC_IPSW 0x40 +#define RTC_TE 0x80 + +#endif /* __LINUX_DS1286_H */ diff --git a/include/linux/errqueue.h b/include/linux/errqueue.h index 0d87e62ec9e7..174582fedb8b 100644 --- a/include/linux/errqueue.h +++ b/include/linux/errqueue.h @@ -22,6 +22,10 @@ struct sock_extended_err #ifdef __KERNEL__ #include <linux/config.h> +#include <net/ip.h> +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#include <linux/ipv6.h> +#endif #define SKB_EXT_ERR(skb) ((struct sock_exterr_skb *) ((skb)->cb)) diff --git a/include/linux/fs.h b/include/linux/fs.h index 10a69a544045..88337ed4f4f2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -214,15 +214,17 @@ extern int leases_enable, dir_notify_enable, lease_break_time; #include <linux/list.h> #include <linux/radix-tree.h> #include <linux/audit.h> +#include <linux/init.h> #include <asm/semaphore.h> #include <asm/byteorder.h> /* Used to be a macro which just called the function, now just a function */ extern void update_atime (struct inode *); -extern void inode_init(unsigned long); -extern void mnt_init(unsigned long); -extern void files_init(unsigned long); +extern void __init inode_init(unsigned long); +extern void __init inode_init_early(void); +extern void __init mnt_init(unsigned long); +extern void __init files_init(unsigned long); struct buffer_head; typedef int (get_block_t)(struct inode *inode, sector_t iblock, @@ -977,7 +979,8 @@ static inline void touch_atime(struct vfsmount *mnt, struct dentry *dentry) static inline void file_accessed(struct file *file) { - touch_atime(file->f_vfsmnt, file->f_dentry); + if (!(file->f_flags & O_NOATIME)) + touch_atime(file->f_vfsmnt, file->f_dentry); } int sync_inode(struct inode *inode, struct writeback_control *wbc); @@ -1199,7 +1202,8 @@ extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char __user *); /* fs/dcache.c */ -extern void vfs_caches_init(unsigned long); +extern void __init vfs_caches_init_early(void); +extern void __init vfs_caches_init(unsigned long); #define __getname() kmem_cache_alloc(names_cachep, SLAB_KERNEL) #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) diff --git a/include/linux/idr.h b/include/linux/idr.h index 8e2618e3f334..f41128683d65 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -1,5 +1,5 @@ /* - * include/linux/id.h + * include/linux/idr.h * * 2002-10-18 written by Jim Houston jim.houston@ccur.com * Copyright (C) 2002 by Concurrent Computer Corporation diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 67da15c2e1e3..9eb023020b44 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -92,6 +92,15 @@ asmlinkage int printk(const char * fmt, ...) unsigned long int_sqrt(unsigned long); +static inline int __attribute_pure__ long_log2(unsigned long x) +{ + int r = 0; + for (x >>= 1; x > 0; x >>= 1) + r++; + return r; +} + + extern int printk_ratelimit(void); extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f1e1a727acb2..373a13ba6f3f 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -20,6 +20,18 @@ #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER #endif +/* + * system hash table size limits + * - on large memory machines, we may want to allocate a bigger hash than that + * permitted by MAX_ORDER, so we allocate with the bootmem allocator, and are + * limited to this size + */ +#if MAX_ORDER > 14 +#define MAX_SYS_HASH_TABLE_ORDER MAX_ORDER +#else +#define MAX_SYS_HASH_TABLE_ORDER 14 +#endif + struct free_area { struct list_head free_list; unsigned long *map; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a55f97a34035..97758cd8f50e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -405,6 +405,7 @@ struct net_device #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */ #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ #define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */ +#define NETIF_F_LLTX 4096 /* LockLess TX */ /* Called after device is detached from network. */ void (*uninit)(struct net_device *dev); diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index b20c79258825..83f9668653ca 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -10,6 +10,7 @@ #include <linux/wait.h> #include <linux/list.h> #endif +#include <linux/compiler.h> /* Responses from hook functions. */ #define NF_DROP 0 diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index 78c4f7142267..d6a7188b525c 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -16,7 +16,7 @@ #include <linux/if_arp.h> #include <linux/skbuff.h> #endif - +#include <linux/compiler.h> #include <linux/netfilter_arp.h> #define ARPT_FUNCTION_MAXNAMELEN 30 diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index f43f1dddebc4..dccc68052c88 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -22,6 +22,7 @@ #include <linux/ip.h> #include <linux/skbuff.h> #endif +#include <linux/compiler.h> #include <linux/netfilter_ipv4.h> #define IPT_FUNCTION_MAXNAMELEN 30 @@ -336,8 +337,8 @@ ipt_get_target(struct ipt_entry *e) /* * Main firewall chains definitions and global var's definitions. */ -static DECLARE_MUTEX(ipt_mutex); #ifdef __KERNEL__ +static DECLARE_MUTEX(ipt_mutex); #include <linux/init.h> extern void ipt_init(void) __init; diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index a0995271934a..f9983d16cc1c 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -22,6 +22,7 @@ #include <linux/ipv6.h> #include <linux/skbuff.h> #endif +#include <linux/compiler.h> #include <linux/netfilter_ipv6.h> #define IP6T_FUNCTION_MAXNAMELEN 30 @@ -106,7 +107,9 @@ struct ip6t_counters u_int64_t pcnt, bcnt; /* Packet and byte counters */ }; +#ifdef __KERNEL__ static DECLARE_MUTEX(ip6t_mutex); +#endif /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c0af91ff4b1e..1b33d607f276 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -27,6 +27,7 @@ #include <linux/highmem.h> #include <linux/poll.h> #include <linux/net.h> +#include <net/checksum.h> #define HAVE_ALLOC_SKB /* For the drivers to know */ #define HAVE_ALIGNABLE_SKB /* Ditto 8) */ @@ -995,6 +996,39 @@ static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len) return skb_pad(skb, len-size); } +static inline int skb_add_data(struct sk_buff *skb, + char __user *from, int copy) +{ + const int off = skb->len; + + if (skb->ip_summed == CHECKSUM_NONE) { + int err = 0; + unsigned int csum = csum_and_copy_from_user(from, + skb_put(skb, copy), + copy, 0, &err); + if (!err) { + skb->csum = csum_block_add(skb->csum, csum, off); + return 0; + } + } else if (!copy_from_user(skb_put(skb, copy), from, copy)) + return 0; + + __skb_trim(skb, off); + return -EFAULT; +} + +static inline int skb_can_coalesce(struct sk_buff *skb, int i, + struct page *page, int off) +{ + if (i) { + struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + + return page == frag->page && + off == frag->page_offset + frag->size; + } + return 0; +} + /** * skb_linearize - convert paged skb to linear one * @skb: buffer to linarize @@ -1058,6 +1092,8 @@ extern unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, int len, unsigned int csum); extern void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to); +extern void skb_split(struct sk_buff *skb, + struct sk_buff *skb1, const u32 len); extern void skb_init(void); extern void skb_add_mtu(int mtu); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a4ab8e826bbe..ab8727d92739 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -207,6 +207,9 @@ struct v4l2_pix_format #define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ +/* see http://www.siliconimaging.com/RGB%20Bayer.htm */ +#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ + /* compressed formats */ #define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */ #define V4L2_PIX_FMT_JPEG v4l2_fourcc('J','P','E','G') /* JFIF JPEG */ @@ -383,8 +386,8 @@ struct v4l2_buffer unsigned long userptr; } m; __u32 length; - - __u32 reserved[2]; + __u32 input; + __u32 reserved; }; /* Flags for 'flags' field */ @@ -395,6 +398,7 @@ struct v4l2_buffer #define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ #define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ #define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ +#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */ /* * O V E R L A Y P R E V I E W @@ -526,12 +530,13 @@ typedef __u64 v4l2_std_id; V4L2_STD_PAL_I) #define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ V4L2_STD_NTSC_M_JP) +#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ + V4L2_STD_SECAM_K |\ + V4L2_STD_SECAM_K1) #define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ - V4L2_STD_SECAM_D |\ V4L2_STD_SECAM_G |\ V4L2_STD_SECAM_H |\ - V4L2_STD_SECAM_K |\ - V4L2_STD_SECAM_K1 |\ + V4L2_STD_SECAM_DK |\ V4L2_STD_SECAM_L) #define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ @@ -541,6 +546,8 @@ typedef __u64 v4l2_std_id; V4L2_STD_PAL_N |\ V4L2_STD_PAL_Nc |\ V4L2_STD_SECAM) +#define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ + V4L2_STD_ATSC_16_VSB) #define V4L2_STD_UNKNOWN 0 #define V4L2_STD_ALL (V4L2_STD_525_60 |\ diff --git a/include/linux/wait.h b/include/linux/wait.h index 52edb1786b14..4a9f996bb6cc 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -200,7 +200,36 @@ do { \ __wait_event_interruptible_timeout(wq, condition, __ret); \ __ret; \ }) - + +#define __wait_event_interruptible_exclusive(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue_exclusive(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + schedule(); \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_exclusive(wq, condition) \ +({ \ + int __ret = 0; \ + if (!(condition)) \ + __wait_event_interruptible_exclusive(wq, condition, __ret);\ + __ret; \ +}) + /* * Must be called with the spinlock in the wait_queue_head_t held. */ diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 42206f88ff25..569f74839529 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -27,7 +27,7 @@ #define IR_TYPE_OTHER 99 #define IR_KEYTAB_TYPE u32 -#define IR_KEYTAB_SIZE 64 // enougth for rc5, probably need more some day ... +#define IR_KEYTAB_SIZE 128 // enougth for rc5, probably need more some day ... #define IR_KEYCODE(tab,code) (((unsigned)code < IR_KEYTAB_SIZE) \ ? tab[code] : KEY_RESERVED) diff --git a/include/media/ovcamchip.h b/include/media/ovcamchip.h new file mode 100644 index 000000000000..cb7c0aa96f22 --- /dev/null +++ b/include/media/ovcamchip.h @@ -0,0 +1,104 @@ +/* OmniVision* camera chip driver API + * + * Copyright (c) 1999-2004 Mark McClelland + * + * 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. NO WARRANTY OF ANY KIND is expressed or implied. + * + * * OmniVision is a trademark of OmniVision Technologies, Inc. This driver + * is not sponsored or developed by them. + */ + +#ifndef __LINUX_OVCAMCHIP_H +#define __LINUX_OVCAMCHIP_H + +#include <linux/videodev.h> +#include <linux/i2c.h> + +/* Remove these once they are officially defined */ +#ifndef I2C_DRIVERID_OVCAMCHIP + #define I2C_DRIVERID_OVCAMCHIP 0xf00f +#endif +#ifndef I2C_HW_SMBUS_OV511 + #define I2C_HW_SMBUS_OV511 0xfe +#endif +#ifndef I2C_HW_SMBUS_OV518 + #define I2C_HW_SMBUS_OV518 0xff +#endif +#ifndef I2C_HW_SMBUS_OVFX2 + #define I2C_HW_SMBUS_OVFX2 0xfd +#endif + +/* --------------------------------- */ +/* ENUMERATIONS */ +/* --------------------------------- */ + +/* Controls */ +enum { + OVCAMCHIP_CID_CONT, /* Contrast */ + OVCAMCHIP_CID_BRIGHT, /* Brightness */ + OVCAMCHIP_CID_SAT, /* Saturation */ + OVCAMCHIP_CID_HUE, /* Hue */ + OVCAMCHIP_CID_EXP, /* Exposure */ + OVCAMCHIP_CID_FREQ, /* Light frequency */ + OVCAMCHIP_CID_BANDFILT, /* Banding filter */ + OVCAMCHIP_CID_AUTOBRIGHT, /* Auto brightness */ + OVCAMCHIP_CID_AUTOEXP, /* Auto exposure */ + OVCAMCHIP_CID_BACKLIGHT, /* Back light compensation */ + OVCAMCHIP_CID_MIRROR, /* Mirror horizontally */ +}; + +/* Chip types */ +#define NUM_CC_TYPES 9 +enum { + CC_UNKNOWN, + CC_OV76BE, + CC_OV7610, + CC_OV7620, + CC_OV7620AE, + CC_OV6620, + CC_OV6630, + CC_OV6630AE, + CC_OV6630AF, +}; + +/* --------------------------------- */ +/* I2C ADDRESSES */ +/* --------------------------------- */ + +#define OV7xx0_SID (0x42 >> 1) +#define OV6xx0_SID (0xC0 >> 1) + +/* --------------------------------- */ +/* API */ +/* --------------------------------- */ + +struct ovcamchip_control { + __u32 id; + __s32 value; +}; + +struct ovcamchip_window { + int x; + int y; + int width; + int height; + int format; + int quarter; /* Scale width and height down 2x */ + + /* This stuff will be removed eventually */ + int clockdiv; /* Clock divisor setting */ +}; + +/* Commands */ +#define OVCAMCHIP_CMD_Q_SUBTYPE _IOR (0x88, 0x00, int) +#define OVCAMCHIP_CMD_INITIALIZE _IOW (0x88, 0x01, int) +/* You must call OVCAMCHIP_CMD_INITIALIZE before any of commands below! */ +#define OVCAMCHIP_CMD_S_CTRL _IOW (0x88, 0x02, struct ovcamchip_control) +#define OVCAMCHIP_CMD_G_CTRL _IOWR (0x88, 0x03, struct ovcamchip_control) +#define OVCAMCHIP_CMD_S_MODE _IOW (0x88, 0x04, struct ovcamchip_window) +#define OVCAMCHIP_MAX_CMD _IO (0x88, 0x3f) + +#endif diff --git a/include/media/video-buf.h b/include/media/video-buf.h index 41e9e58c434e..17b2ae290f13 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -18,6 +18,8 @@ #include <linux/videodev.h> +#define UNSET (-1U) + /* --------------------------------------------------------------------- */ /* @@ -34,8 +36,6 @@ struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); */ struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset); -int videobuf_lock(struct page **pages, int nr_pages); -int videobuf_unlock(struct page **pages, int nr_pages); /* --------------------------------------------------------------------- */ @@ -59,6 +59,8 @@ int videobuf_unlock(struct page **pages, int nr_pages); */ struct videobuf_dmabuf { + u32 magic; + /* for userland buffer */ int offset; struct page **pages; @@ -76,6 +78,7 @@ struct videobuf_dmabuf { int direction; }; +void videobuf_dma_init(struct videobuf_dmabuf *dma); int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, unsigned long data, unsigned long size); int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, @@ -134,12 +137,14 @@ enum videobuf_state { struct videobuf_buffer { unsigned int i; + u32 magic; /* info about the buffer */ unsigned int width; unsigned int height; unsigned int bytesperline; /* use only if != 0 */ unsigned long size; + unsigned int input; enum v4l2_field field; enum videobuf_state state; struct videobuf_dmabuf dma; @@ -174,9 +179,10 @@ struct videobuf_queue { struct pci_dev *pci; enum v4l2_buf_type type; + unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ unsigned int msize; enum v4l2_field field; - enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ + enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; struct videobuf_queue_ops *ops; diff --git a/include/net/checksum.h b/include/net/checksum.h index cd3c52a594e4..43f40235114e 100644 --- a/include/net/checksum.h +++ b/include/net/checksum.h @@ -16,83 +16,15 @@ * 2 of the License, or (at your option) any later version. */ -/* - * Fixes: - * - * Ralf Baechle : generic ipv6 checksum - * <ralf@waldorf-gmbh.de> - */ - #ifndef _CHECKSUM_H #define _CHECKSUM_H +#include <linux/errno.h> #include <asm/types.h> #include <asm/byteorder.h> -#include <net/ip.h> -#include <linux/in6.h> #include <asm/uaccess.h> #include <asm/checksum.h> -#ifndef _HAVE_ARCH_IPV6_CSUM - -static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr, - struct in6_addr *daddr, - __u16 len, - unsigned short proto, - unsigned int csum) -{ - - int carry; - __u32 ulen; - __u32 uproto; - - csum += saddr->s6_addr32[0]; - carry = (csum < saddr->s6_addr32[0]); - csum += carry; - - csum += saddr->s6_addr32[1]; - carry = (csum < saddr->s6_addr32[1]); - csum += carry; - - csum += saddr->s6_addr32[2]; - carry = (csum < saddr->s6_addr32[2]); - csum += carry; - - csum += saddr->s6_addr32[3]; - carry = (csum < saddr->s6_addr32[3]); - csum += carry; - - csum += daddr->s6_addr32[0]; - carry = (csum < daddr->s6_addr32[0]); - csum += carry; - - csum += daddr->s6_addr32[1]; - carry = (csum < daddr->s6_addr32[1]); - csum += carry; - - csum += daddr->s6_addr32[2]; - carry = (csum < daddr->s6_addr32[2]); - csum += carry; - - csum += daddr->s6_addr32[3]; - carry = (csum < daddr->s6_addr32[3]); - csum += carry; - - ulen = htonl((__u32) len); - csum += ulen; - carry = (csum < ulen); - csum += carry; - - uproto = htonl(proto); - csum += uproto; - carry = (csum < uproto); - csum += carry; - - return csum_fold(csum); -} - -#endif - #ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER static inline unsigned int csum_and_copy_from_user (const char __user *src, char *dst, diff --git a/include/net/ip.h b/include/net/ip.h index 5a683ccd4cb0..d36a3b230819 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -37,7 +37,7 @@ #include <net/snmp.h> #endif -#include <net/sock.h> /* struct sock */ +struct sock; struct inet_skb_parm { diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h new file mode 100644 index 000000000000..3dfc885bdf25 --- /dev/null +++ b/include/net/ip6_checksum.h @@ -0,0 +1,94 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Checksumming functions for IPv6 + * + * Authors: Jorge Cwik, <jorge@laser.satlink.net> + * Arnt Gulbrandsen, <agulbra@nvg.unit.no> + * Borrows very liberally from tcp.c and ip.c, see those + * files for more names. + * + * 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. + */ + +/* + * Fixes: + * + * Ralf Baechle : generic ipv6 checksum + * <ralf@waldorf-gmbh.de> + */ + +#ifndef _CHECKSUM_IPV6_H +#define _CHECKSUM_IPV6_H + +#include <asm/types.h> +#include <asm/byteorder.h> +#include <net/ip.h> +#include <asm/checksum.h> +#include <linux/in6.h> + +#ifndef _HAVE_ARCH_IPV6_CSUM + +static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr, + struct in6_addr *daddr, + __u16 len, + unsigned short proto, + unsigned int csum) +{ + + int carry; + __u32 ulen; + __u32 uproto; + + csum += saddr->s6_addr32[0]; + carry = (csum < saddr->s6_addr32[0]); + csum += carry; + + csum += saddr->s6_addr32[1]; + carry = (csum < saddr->s6_addr32[1]); + csum += carry; + + csum += saddr->s6_addr32[2]; + carry = (csum < saddr->s6_addr32[2]); + csum += carry; + + csum += saddr->s6_addr32[3]; + carry = (csum < saddr->s6_addr32[3]); + csum += carry; + + csum += daddr->s6_addr32[0]; + carry = (csum < daddr->s6_addr32[0]); + csum += carry; + + csum += daddr->s6_addr32[1]; + carry = (csum < daddr->s6_addr32[1]); + csum += carry; + + csum += daddr->s6_addr32[2]; + carry = (csum < daddr->s6_addr32[2]); + csum += carry; + + csum += daddr->s6_addr32[3]; + carry = (csum < daddr->s6_addr32[3]); + csum += carry; + + ulen = htonl((__u32) len); + csum += ulen; + carry = (csum < ulen); + csum += carry; + + uproto = htonl(proto); + csum += uproto; + carry = (csum < uproto); + csum += carry; + + return csum_fold(csum); +} + +#endif +#endif diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 80661d855fd8..d8960a01df42 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -11,6 +11,7 @@ #include <linux/netdevice.h> #include <linux/types.h> #include <linux/pkt_sched.h> +#include <linux/rcupdate.h> #include <net/pkt_cls.h> #ifdef CONFIG_X86_TSC @@ -92,6 +93,7 @@ struct Qdisc struct net_device *dev; struct tc_stats stats; + struct rcu_head q_rcu; int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q); /* This field is deprecated, but it is still used by CBQ diff --git a/include/net/sock.h b/include/net/sock.h index 38b90c8ab25f..0ee6ccddca40 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -53,6 +53,7 @@ #include <asm/atomic.h> #include <net/dst.h> +#include <net/checksum.h> /* * This structure really needs to be cleaned up. @@ -428,6 +429,11 @@ static inline int sk_stream_wspace(struct sock *sk) extern void sk_stream_write_space(struct sock *sk); +static inline int sk_stream_memory_free(struct sock *sk) +{ + return sk->sk_wmem_queued < sk->sk_sndbuf; +} + /* The per-socket spinlock must be held here. */ #define sk_add_backlog(__sk, __skb) \ do { if (!(__sk)->sk_backlog.tail) { \ @@ -923,6 +929,29 @@ static inline void sk_charge_skb(struct sock *sk, struct sk_buff *skb) sk->sk_forward_alloc -= skb->truesize; } +static inline int skb_copy_to_page(struct sock *sk, char __user *from, + struct sk_buff *skb, struct page *page, + int off, int copy) +{ + if (skb->ip_summed == CHECKSUM_NONE) { + int err = 0; + unsigned int csum = csum_and_copy_from_user(from, + page_address(page) + off, + copy, 0, &err); + if (err) + return err; + skb->csum = csum_block_add(skb->csum, csum, skb->len); + } else if (copy_from_user(page_address(page) + off, from, copy)) + return -EFAULT; + + skb->len += copy; + skb->data_len += copy; + skb->truesize += copy; + sk->sk_wmem_queued += copy; + sk->sk_forward_alloc -= copy; + return 0; +} + /* * Queue a received datagram if it will fit. Stream and sequenced * protocols can't normally use this as they need to fit buffers in diff --git a/include/net/tcp.h b/include/net/tcp.h index 52f27edef69e..3a323cd1e79f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -33,6 +33,7 @@ #include <net/checksum.h> #include <net/sock.h> #include <net/snmp.h> +#include <net/ip.h> #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) #include <linux/ipv6.h> #endif diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 64704968507f..c36a3aed38c2 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -497,10 +497,6 @@ xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, return 0; } -/* placeholder until xfrm6_tunnel.c is written */ -static inline int xfrm6_tunnel_check_size(struct sk_buff *skb) -{ return 0; } - /* A struct encoding bundle of transformations to apply to some set of flow. * * dst->child points to the next element of bundle. @@ -783,6 +779,12 @@ struct xfrm_tunnel { void (*err_handler)(struct sk_buff *skb, void *info); }; +struct xfrm6_tunnel { + int (*handler)(struct sk_buff **pskb, unsigned int *nhoffp); + void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info); +}; + extern void xfrm_init(void); extern void xfrm4_init(void); extern void xfrm4_fini(void); @@ -793,6 +795,8 @@ extern void xfrm4_state_init(void); extern void xfrm4_state_fini(void); extern void xfrm6_state_init(void); extern void xfrm6_state_fini(void); +extern void xfrm6_tunnel_init(void); +extern void xfrm6_tunnel_fini(void); extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *); extern struct xfrm_state *xfrm_state_alloc(void); @@ -812,12 +816,18 @@ extern void xfrm_state_flush(u8 proto); extern int xfrm_replay_check(struct xfrm_state *x, u32 seq); extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl); -extern int xfrm_check_output(struct xfrm_state *x, struct sk_buff *skb, unsigned short family); +extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm4_rcv(struct sk_buff *skb); extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_check_size(struct sk_buff *skb); extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); +extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); +extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); +extern int xfrm6_tunnel_check_size(struct sk_buff *skb); +extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); +extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); +extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); #ifdef CONFIG_XFRM extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); diff --git a/init/main.c b/init/main.c index 027896bba166..1e58b66b2144 100644 --- a/init/main.c +++ b/init/main.c @@ -458,6 +458,7 @@ asmlinkage void __init start_kernel(void) initrd_start = 0; } #endif + vfs_caches_init_early(); mem_init(); kmem_cache_init(); numa_policy_init(); diff --git a/kernel/Makefile b/kernel/Makefile index 238c65f60d9e..2b7b352b1a38 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -48,7 +48,7 @@ quiet_cmd_ikconfig = IKCFG $@ cmd_ikconfig = $(CONFIG_SHELL) $< .config $(srctree)/Makefile > $@ targets += ikconfig.h -$(obj)/ikconfig.h: scripts/mkconfigs .config Makefile FORCE +$(obj)/ikconfig.h: scripts/mkconfigs .config $(srctree)/Makefile FORCE $(call if_changed,ikconfig) # config_data.h contains the same information as ikconfig.h but gzipped. diff --git a/kernel/signal.c b/kernel/signal.c index d41b3a0e8b7e..18048ca42f0e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1197,6 +1197,13 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p) unsigned long flags; /* + * Make sure legacy kernel users don't send in bad values + * (normal paths check this in check_kill_permission). + */ + if (sig < 0 || sig > _NSIG) + return -EINVAL; + + /* * We need the tasklist lock even for the specific * thread case (when we don't need to follow the group * lists) in order to avoid races with "p->sighand" diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c index a71152d550f0..96255f47b1f8 100644 --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c @@ -1,5 +1,5 @@ -/* rwsem-spinlock.c: R/W semaphores: contention handling functions for generic spinlock - * implementation +/* rwsem-spinlock.c: R/W semaphores: contention handling functions for + * generic spinlock implementation * * Copyright (c) 2001 David Howells (dhowells@redhat.com). * - Derived partially from idea by Andrea Arcangeli <andrea@suse.de> @@ -10,9 +10,9 @@ #include <linux/module.h> struct rwsem_waiter { - struct list_head list; - struct task_struct *task; - unsigned int flags; + struct list_head list; + struct task_struct *task; + unsigned int flags; #define RWSEM_WAITING_FOR_READ 0x00000001 #define RWSEM_WAITING_FOR_WRITE 0x00000002 }; @@ -22,7 +22,8 @@ void rwsemtrace(struct rw_semaphore *sem, const char *str) { if (sem->debug) printk("[%d] %s({%d,%d})\n", - current->pid,str,sem->activity,list_empty(&sem->wait_list)?0:1); + current->pid, str, sem->activity, + list_empty(&sem->wait_list) ? 0 : 1); } #endif @@ -40,7 +41,7 @@ void fastcall init_rwsem(struct rw_semaphore *sem) } /* - * handle the lock being released whilst there are processes blocked on it that can now run + * handle the lock release when processes blocked on it that can now run * - if we come here, then: * - the 'active count' _reached_ zero * - the 'waiting count' is non-zero @@ -48,15 +49,16 @@ void fastcall init_rwsem(struct rw_semaphore *sem) * - woken process blocks are discarded from the list after having task zeroed * - writers are only woken if wakewrite is non-zero */ -static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) +static inline struct rw_semaphore * +__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) { struct rwsem_waiter *waiter; struct task_struct *tsk; int woken; - rwsemtrace(sem,"Entering __rwsem_do_wake"); + rwsemtrace(sem, "Entering __rwsem_do_wake"); - waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list); + waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list); if (!wakewrite) { if (waiter->flags & RWSEM_WAITING_FOR_WRITE) @@ -64,14 +66,16 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int goto dont_wake_writers; } - /* if we are allowed to wake writers try to grant a single write lock if there's a - * writer at the front of the queue - * - we leave the 'waiting count' incremented to signify potential contention + /* if we are allowed to wake writers try to grant a single write lock + * if there's a writer at the front of the queue + * - we leave the 'waiting count' incremented to signify potential + * contention */ if (waiter->flags & RWSEM_WAITING_FOR_WRITE) { sem->activity = -1; list_del(&waiter->list); tsk = waiter->task; + /* Don't touch waiter after ->task has been NULLed */ mb(); waiter->task = NULL; wake_up_process(tsk); @@ -79,10 +83,10 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int goto out; } - /* grant an infinite number of read locks to the readers at the front of the queue */ + /* grant an infinite number of read locks to the front of the queue */ dont_wake_writers: woken = 0; - while (waiter->flags&RWSEM_WAITING_FOR_READ) { + while (waiter->flags & RWSEM_WAITING_FOR_READ) { struct list_head *next = waiter->list.next; list_del(&waiter->list); @@ -94,27 +98,28 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int woken++; if (list_empty(&sem->wait_list)) break; - waiter = list_entry(next,struct rwsem_waiter,list); + waiter = list_entry(next, struct rwsem_waiter, list); } sem->activity += woken; out: - rwsemtrace(sem,"Leaving __rwsem_do_wake"); + rwsemtrace(sem, "Leaving __rwsem_do_wake"); return sem; } /* * wake a single writer */ -static inline struct rw_semaphore *__rwsem_wake_one_writer(struct rw_semaphore *sem) +static inline struct rw_semaphore * +__rwsem_wake_one_writer(struct rw_semaphore *sem) { struct rwsem_waiter *waiter; struct task_struct *tsk; sem->activity = -1; - waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list); + waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list); list_del(&waiter->list); tsk = waiter->task; @@ -128,16 +133,16 @@ static inline struct rw_semaphore *__rwsem_wake_one_writer(struct rw_semaphore * /* * get a read lock on the semaphore */ -void fastcall __down_read(struct rw_semaphore *sem) +void fastcall __sched __down_read(struct rw_semaphore *sem) { struct rwsem_waiter waiter; struct task_struct *tsk; - rwsemtrace(sem,"Entering __down_read"); + rwsemtrace(sem, "Entering __down_read"); spin_lock(&sem->wait_lock); - if (sem->activity>=0 && list_empty(&sem->wait_list)) { + if (sem->activity >= 0 && list_empty(&sem->wait_list)) { /* granted */ sem->activity++; spin_unlock(&sem->wait_lock); @@ -145,14 +150,14 @@ void fastcall __down_read(struct rw_semaphore *sem) } tsk = current; - set_task_state(tsk,TASK_UNINTERRUPTIBLE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); /* set up my own style of waitqueue */ waiter.task = tsk; waiter.flags = RWSEM_WAITING_FOR_READ; get_task_struct(tsk); - list_add_tail(&waiter.list,&sem->wait_list); + list_add_tail(&waiter.list, &sem->wait_list); /* we don't need to touch the semaphore struct anymore */ spin_unlock(&sem->wait_lock); @@ -168,7 +173,7 @@ void fastcall __down_read(struct rw_semaphore *sem) tsk->state = TASK_RUNNING; out: - rwsemtrace(sem,"Leaving __down_read"); + rwsemtrace(sem, "Leaving __down_read"); } /* @@ -177,11 +182,11 @@ void fastcall __down_read(struct rw_semaphore *sem) int fastcall __down_read_trylock(struct rw_semaphore *sem) { int ret = 0; - rwsemtrace(sem,"Entering __down_read_trylock"); + rwsemtrace(sem, "Entering __down_read_trylock"); spin_lock(&sem->wait_lock); - if (sem->activity>=0 && list_empty(&sem->wait_list)) { + if (sem->activity >= 0 && list_empty(&sem->wait_list)) { /* granted */ sem->activity++; ret = 1; @@ -189,24 +194,24 @@ int fastcall __down_read_trylock(struct rw_semaphore *sem) spin_unlock(&sem->wait_lock); - rwsemtrace(sem,"Leaving __down_read_trylock"); + rwsemtrace(sem, "Leaving __down_read_trylock"); return ret; } /* * get a write lock on the semaphore - * - note that we increment the waiting count anyway to indicate an exclusive lock + * - we increment the waiting count anyway to indicate an exclusive lock */ -void fastcall __down_write(struct rw_semaphore *sem) +void fastcall __sched __down_write(struct rw_semaphore *sem) { struct rwsem_waiter waiter; struct task_struct *tsk; - rwsemtrace(sem,"Entering __down_write"); + rwsemtrace(sem, "Entering __down_write"); spin_lock(&sem->wait_lock); - if (sem->activity==0 && list_empty(&sem->wait_list)) { + if (sem->activity == 0 && list_empty(&sem->wait_list)) { /* granted */ sem->activity = -1; spin_unlock(&sem->wait_lock); @@ -214,14 +219,14 @@ void fastcall __down_write(struct rw_semaphore *sem) } tsk = current; - set_task_state(tsk,TASK_UNINTERRUPTIBLE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); /* set up my own style of waitqueue */ waiter.task = tsk; waiter.flags = RWSEM_WAITING_FOR_WRITE; get_task_struct(tsk); - list_add_tail(&waiter.list,&sem->wait_list); + list_add_tail(&waiter.list, &sem->wait_list); /* we don't need to touch the semaphore struct anymore */ spin_unlock(&sem->wait_lock); @@ -237,7 +242,7 @@ void fastcall __down_write(struct rw_semaphore *sem) tsk->state = TASK_RUNNING; out: - rwsemtrace(sem,"Leaving __down_write"); + rwsemtrace(sem, "Leaving __down_write"); } /* @@ -246,11 +251,11 @@ void fastcall __down_write(struct rw_semaphore *sem) int fastcall __down_write_trylock(struct rw_semaphore *sem) { int ret = 0; - rwsemtrace(sem,"Entering __down_write_trylock"); + rwsemtrace(sem, "Entering __down_write_trylock"); spin_lock(&sem->wait_lock); - if (sem->activity==0 && list_empty(&sem->wait_list)) { + if (sem->activity == 0 && list_empty(&sem->wait_list)) { /* granted */ sem->activity = -1; ret = 1; @@ -258,7 +263,7 @@ int fastcall __down_write_trylock(struct rw_semaphore *sem) spin_unlock(&sem->wait_lock); - rwsemtrace(sem,"Leaving __down_write_trylock"); + rwsemtrace(sem, "Leaving __down_write_trylock"); return ret; } @@ -267,16 +272,16 @@ int fastcall __down_write_trylock(struct rw_semaphore *sem) */ void fastcall __up_read(struct rw_semaphore *sem) { - rwsemtrace(sem,"Entering __up_read"); + rwsemtrace(sem, "Entering __up_read"); spin_lock(&sem->wait_lock); - if (--sem->activity==0 && !list_empty(&sem->wait_list)) + if (--sem->activity == 0 && !list_empty(&sem->wait_list)) sem = __rwsem_wake_one_writer(sem); spin_unlock(&sem->wait_lock); - rwsemtrace(sem,"Leaving __up_read"); + rwsemtrace(sem, "Leaving __up_read"); } /* @@ -284,7 +289,7 @@ void fastcall __up_read(struct rw_semaphore *sem) */ void fastcall __up_write(struct rw_semaphore *sem) { - rwsemtrace(sem,"Entering __up_write"); + rwsemtrace(sem, "Entering __up_write"); spin_lock(&sem->wait_lock); @@ -294,7 +299,7 @@ void fastcall __up_write(struct rw_semaphore *sem) spin_unlock(&sem->wait_lock); - rwsemtrace(sem,"Leaving __up_write"); + rwsemtrace(sem, "Leaving __up_write"); } /* @@ -303,17 +308,17 @@ void fastcall __up_write(struct rw_semaphore *sem) */ void fastcall __downgrade_write(struct rw_semaphore *sem) { - rwsemtrace(sem,"Entering __downgrade_write"); + rwsemtrace(sem, "Entering __downgrade_write"); spin_lock(&sem->wait_lock); sem->activity = 1; if (!list_empty(&sem->wait_list)) - sem = __rwsem_do_wake(sem,0); + sem = __rwsem_do_wake(sem, 0); spin_unlock(&sem->wait_lock); - rwsemtrace(sem,"Leaving __downgrade_write"); + rwsemtrace(sem, "Leaving __downgrade_write"); } EXPORT_SYMBOL(init_rwsem); diff --git a/lib/rwsem.c b/lib/rwsem.c index 27dcd95f7d3b..465ec725607e 100644 --- a/lib/rwsem.c +++ b/lib/rwsem.c @@ -9,9 +9,9 @@ #include <linux/module.h> struct rwsem_waiter { - struct list_head list; - struct task_struct *task; - unsigned int flags; + struct list_head list; + struct task_struct *task; + unsigned int flags; #define RWSEM_WAITING_FOR_READ 0x00000001 #define RWSEM_WAITING_FOR_WRITE 0x00000002 }; @@ -20,31 +20,32 @@ struct rwsem_waiter { #undef rwsemtrace void rwsemtrace(struct rw_semaphore *sem, const char *str) { - printk("sem=%p\n",sem); - printk("(sem)=%08lx\n",sem->count); + printk("sem=%p\n", sem); + printk("(sem)=%08lx\n", sem->count); if (sem->debug) - printk("[%d] %s({%08lx})\n",current->pid,str,sem->count); + printk("[%d] %s({%08lx})\n", current->pid, str, sem->count); } #endif /* - * handle the lock being released whilst there are processes blocked on it that can now run + * handle the lock release when processes blocked on it that can now run * - if we come here from up_xxxx(), then: - * - the 'active part' of the count (&0x0000ffff) had reached zero (but may have changed) - * - the 'waiting part' of the count (&0xffff0000) is negative (and will still be so) + * - the 'active part' of count (&0x0000ffff) reached 0 (but may have changed) + * - the 'waiting part' of count (&0xffff0000) is -ve (and will still be so) * - there must be someone on the queue * - the spinlock must be held by the caller * - woken process blocks are discarded from the list after having task zeroed * - writers are only woken if downgrading is false */ -static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int downgrading) +static inline struct rw_semaphore * +__rwsem_do_wake(struct rw_semaphore *sem, int downgrading) { struct rwsem_waiter *waiter; struct task_struct *tsk; struct list_head *next; signed long oldcount, woken, loop; - rwsemtrace(sem,"Entering __rwsem_do_wake"); + rwsemtrace(sem, "Entering __rwsem_do_wake"); if (downgrading) goto dont_wake_writers; @@ -53,19 +54,24 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int * if we can transition the active part of the count from 0 -> 1 */ try_again: - oldcount = rwsem_atomic_update(RWSEM_ACTIVE_BIAS,sem) - RWSEM_ACTIVE_BIAS; + oldcount = rwsem_atomic_update(RWSEM_ACTIVE_BIAS, sem) + - RWSEM_ACTIVE_BIAS; if (oldcount & RWSEM_ACTIVE_MASK) goto undo; - waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list); + waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list); - /* try to grant a single write lock if there's a writer at the front of the queue - * - note we leave the 'active part' of the count incremented by 1 and the waiting part - * incremented by 0x00010000 + /* try to grant a single write lock if there's a writer at the front + * of the queue - note we leave the 'active part' of the count + * incremented by 1 and the waiting part incremented by 0x00010000 */ if (!(waiter->flags & RWSEM_WAITING_FOR_WRITE)) goto readers_only; + /* We must be careful not to touch 'waiter' after we set ->task = NULL. + * It is an allocated on the waiter's stack and may become invalid at + * any time after that point (due to a wakeup from another source). + */ list_del(&waiter->list); tsk = waiter->task; mb(); @@ -76,7 +82,7 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int /* don't want to wake any writers */ dont_wake_writers: - waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list); + waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list); if (waiter->flags & RWSEM_WAITING_FOR_WRITE) goto out; @@ -90,23 +96,25 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int do { woken++; - if (waiter->list.next==&sem->wait_list) + if (waiter->list.next == &sem->wait_list) break; - waiter = list_entry(waiter->list.next,struct rwsem_waiter,list); + waiter = list_entry(waiter->list.next, + struct rwsem_waiter, list); } while (waiter->flags & RWSEM_WAITING_FOR_READ); loop = woken; woken *= RWSEM_ACTIVE_BIAS - RWSEM_WAITING_BIAS; if (!downgrading) - woken -= RWSEM_ACTIVE_BIAS; /* we'd already done one increment - * earlier */ - rwsem_atomic_add(woken,sem); + /* we'd already done one increment earlier */ + woken -= RWSEM_ACTIVE_BIAS; + + rwsem_atomic_add(woken, sem); next = sem->wait_list.next; - for (; loop>0; loop--) { - waiter = list_entry(next,struct rwsem_waiter,list); + for (; loop > 0; loop--) { + waiter = list_entry(next, struct rwsem_waiter, list); next = waiter->list.next; tsk = waiter->task; mb(); @@ -119,12 +127,12 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int next->prev = &sem->wait_list; out: - rwsemtrace(sem,"Leaving __rwsem_do_wake"); + rwsemtrace(sem, "Leaving __rwsem_do_wake"); return sem; /* undo the change to count, but check for a transition 1->0 */ undo: - if (rwsem_atomic_update(-RWSEM_ACTIVE_BIAS,sem)!=0) + if (rwsem_atomic_update(-RWSEM_ACTIVE_BIAS, sem) != 0) goto out; goto try_again; } @@ -132,28 +140,26 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int /* * wait for a lock to be granted */ -static inline struct rw_semaphore *rwsem_down_failed_common(struct rw_semaphore *sem, - struct rwsem_waiter *waiter, - signed long adjustment) +static inline struct rw_semaphore * +rwsem_down_failed_common(struct rw_semaphore *sem, + struct rwsem_waiter *waiter, signed long adjustment) { struct task_struct *tsk = current; signed long count; - set_task_state(tsk,TASK_UNINTERRUPTIBLE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); /* set up my own style of waitqueue */ spin_lock(&sem->wait_lock); waiter->task = tsk; get_task_struct(tsk); - list_add_tail(&waiter->list,&sem->wait_list); + list_add_tail(&waiter->list, &sem->wait_list); - /* note that we're now waiting on the lock, but no longer actively read-locking */ - count = rwsem_atomic_update(adjustment,sem); + /* we're now waiting on the lock, but no longer actively read-locking */ + count = rwsem_atomic_update(adjustment, sem); - /* if there are no longer active locks, wake the front queued process(es) up - * - it might even be this process, since the waker takes a more active part - */ + /* if there are no active locks, wake the front queued process(es) up */ if (!(count & RWSEM_ACTIVE_MASK)) sem = __rwsem_do_wake(sem, 0); @@ -175,42 +181,45 @@ static inline struct rw_semaphore *rwsem_down_failed_common(struct rw_semaphore /* * wait for the read lock to be granted */ -struct rw_semaphore fastcall __sched *rwsem_down_read_failed(struct rw_semaphore *sem) +struct rw_semaphore fastcall __sched * +rwsem_down_read_failed(struct rw_semaphore *sem) { struct rwsem_waiter waiter; - rwsemtrace(sem,"Entering rwsem_down_read_failed"); + rwsemtrace(sem, "Entering rwsem_down_read_failed"); waiter.flags = RWSEM_WAITING_FOR_READ; - rwsem_down_failed_common(sem,&waiter,RWSEM_WAITING_BIAS-RWSEM_ACTIVE_BIAS); + rwsem_down_failed_common(sem, &waiter, + RWSEM_WAITING_BIAS - RWSEM_ACTIVE_BIAS); - rwsemtrace(sem,"Leaving rwsem_down_read_failed"); + rwsemtrace(sem, "Leaving rwsem_down_read_failed"); return sem; } /* * wait for the write lock to be granted */ -struct rw_semaphore fastcall __sched *rwsem_down_write_failed(struct rw_semaphore *sem) +struct rw_semaphore fastcall __sched * +rwsem_down_write_failed(struct rw_semaphore *sem) { struct rwsem_waiter waiter; - rwsemtrace(sem,"Entering rwsem_down_write_failed"); + rwsemtrace(sem, "Entering rwsem_down_write_failed"); waiter.flags = RWSEM_WAITING_FOR_WRITE; - rwsem_down_failed_common(sem,&waiter,-RWSEM_ACTIVE_BIAS); + rwsem_down_failed_common(sem, &waiter, -RWSEM_ACTIVE_BIAS); - rwsemtrace(sem,"Leaving rwsem_down_write_failed"); + rwsemtrace(sem, "Leaving rwsem_down_write_failed"); return sem; } /* * handle waking up a waiter on the semaphore - * - up_read/up_write has decremented the active part of the count if we come here + * - up_read/up_write has decremented the active part of count if we come here */ struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem) { - rwsemtrace(sem,"Entering rwsem_wake"); + rwsemtrace(sem, "Entering rwsem_wake"); spin_lock(&sem->wait_lock); @@ -220,19 +229,19 @@ struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem) spin_unlock(&sem->wait_lock); - rwsemtrace(sem,"Leaving rwsem_wake"); + rwsemtrace(sem, "Leaving rwsem_wake"); return sem; } /* * downgrade a write lock into a read lock - * - caller incremented waiting part of count, and discovered it to be still negative + * - caller incremented waiting part of count and discovered it still negative * - just wake up any readers at the front of the queue */ struct rw_semaphore fastcall *rwsem_downgrade_wake(struct rw_semaphore *sem) { - rwsemtrace(sem,"Entering rwsem_downgrade_wake"); + rwsemtrace(sem, "Entering rwsem_downgrade_wake"); spin_lock(&sem->wait_lock); @@ -242,7 +251,7 @@ struct rw_semaphore fastcall *rwsem_downgrade_wake(struct rw_semaphore *sem) spin_unlock(&sem->wait_lock); - rwsemtrace(sem,"Leaving rwsem_downgrade_wake"); + rwsemtrace(sem, "Leaving rwsem_downgrade_wake"); return sem; } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index ad260e0dbb59..4f1fc840550a 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -26,7 +26,7 @@ * process policy. * default Allocate on the local node first, or when on a VMA * use the process policy. This is what Linux always did - * in a NUMA aware kernel and still does by, ahem, default. + * in a NUMA aware kernel and still does by, ahem, default. * * The process policy is applied for most non interrupt memory allocations * in that process' context. Interrupts ignore the policies and always @@ -135,6 +135,10 @@ static int get_nodes(unsigned long *nodes, unsigned long __user *nmask, unsigned long endmask; --maxnode; + bitmap_zero(nodes, MAX_NUMNODES); + if (maxnode == 0 || !nmask) + return 0; + nlongs = BITS_TO_LONGS(maxnode); if ((maxnode % BITS_PER_LONG) == 0) endmask = ~0UL; @@ -143,7 +147,7 @@ static int get_nodes(unsigned long *nodes, unsigned long __user *nmask, /* When the user specified more nodes than supported just check if the non supported part is all zero. */ - if (nmask && nlongs > BITS_TO_LONGS(MAX_NUMNODES)) { + if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) { for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) { unsigned long t; if (get_user(t, nmask + k)) @@ -158,8 +162,7 @@ static int get_nodes(unsigned long *nodes, unsigned long __user *nmask, endmask = ~0UL; } - bitmap_zero(nodes, MAX_NUMNODES); - if (nmask && copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long))) + if (copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long))) return -EFAULT; nodes[nlongs-1] &= endmask; return mpol_check_policy(mode, nodes); @@ -622,14 +625,14 @@ static unsigned offset_il_node(struct mempolicy *pol, /* Allocate a page in interleaved policy. Own path because it needs to do special accounting. */ -static struct page *alloc_page_interleave(unsigned gfp, unsigned nid) +static struct page *alloc_page_interleave(unsigned gfp, unsigned order, unsigned nid) { struct zonelist *zl; struct page *page; BUG_ON(!test_bit(nid, node_online_map)); zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK); - page = __alloc_pages(gfp, 0, zl); + page = __alloc_pages(gfp, order, zl); if (page && page_zone(page) == zl->zones[0]) { zl->zones[0]->pageset[get_cpu()].interleave_hit++; put_cpu(); @@ -677,7 +680,7 @@ alloc_page_vma(unsigned gfp, struct vm_area_struct *vma, unsigned long addr) /* fall back to process interleaving */ nid = interleave_nodes(pol); } - return alloc_page_interleave(gfp, nid); + return alloc_page_interleave(gfp, 0, nid); } return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); } @@ -686,7 +689,7 @@ alloc_page_vma(unsigned gfp, struct vm_area_struct *vma, unsigned long addr) * alloc_pages_current - Allocate pages. * * @gfp: - * %GFP_USER user allocation, + * %GFP_USER user allocation, * %GFP_KERNEL kernel allocation, * %GFP_HIGHMEM highmem allocation, * %GFP_FS don't call back into a file system. @@ -703,8 +706,8 @@ struct page *alloc_pages_current(unsigned gfp, unsigned order) if (!pol || in_interrupt()) pol = &default_policy; - if (pol->policy == MPOL_INTERLEAVE && order == 0) - return alloc_page_interleave(gfp, interleave_nodes(pol)); + if (pol->policy == MPOL_INTERLEAVE) + return alloc_page_interleave(gfp, order, interleave_nodes(pol)); return __alloc_pages(gfp, order, zonelist_policy(gfp, pol)); } EXPORT_SYMBOL(alloc_pages_current); @@ -1022,7 +1025,7 @@ void __init numa_policy_init(void) /* Reset policy of current process to default. * Assumes fs == KERNEL_DS */ -void __init numa_default_policy(void) +void numa_default_policy(void) { sys_set_mempolicy(MPOL_DEFAULT, NULL, 0); } diff --git a/mm/mmap.c b/mm/mmap.c index 359698bfdfcb..42738ed90294 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -362,6 +362,7 @@ void vma_adjust(struct vm_area_struct *vma, unsigned long start, { struct mm_struct *mm = vma->vm_mm; struct vm_area_struct *next = vma->vm_next; + struct vm_area_struct *importer = NULL; struct address_space *mapping = NULL; struct prio_tree_root *root = NULL; struct file *file = vma->vm_file; @@ -385,6 +386,7 @@ again: remove_next = 1 + (end > next->vm_end); */ adjust_next = (end - next->vm_start) >> PAGE_SHIFT; anon_vma = next->anon_vma; + importer = vma; } else if (end < vma->vm_end) { /* * vma shrinks, and !insert tells it's not @@ -393,6 +395,7 @@ again: remove_next = 1 + (end > next->vm_end); */ adjust_next = - ((vma->vm_end - end) >> PAGE_SHIFT); anon_vma = next->anon_vma; + importer = next; } } @@ -418,8 +421,18 @@ again: remove_next = 1 + (end > next->vm_end); */ if (vma->anon_vma) anon_vma = vma->anon_vma; - if (anon_vma) + if (anon_vma) { spin_lock(&anon_vma->lock); + /* + * Easily overlooked: when mprotect shifts the boundary, + * make sure the expanding vma has anon_vma set if the + * shrinking vma had, to cover any anon pages imported. + */ + if (importer && !importer->anon_vma) { + importer->anon_vma = anon_vma; + __anon_vma_link(importer); + } + } if (root) { flush_dcache_mmap_lock(mapping); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 444bb534dbd8..16d5c2af94ee 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -55,6 +55,9 @@ EXPORT_SYMBOL(zone_table); static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; int min_free_kbytes = 1024; +static unsigned long __initdata nr_kernel_pages; +static unsigned long __initdata nr_all_pages; + /* * Temporary debugging check for pages not lying within a given zone. */ @@ -1430,6 +1433,10 @@ static void __init free_area_init_core(struct pglist_data *pgdat, if (zholes_size) realsize -= zholes_size[j]; + if (j == ZONE_DMA || j == ZONE_NORMAL) + nr_kernel_pages += realsize; + nr_all_pages += realsize; + zone->spanned_pages = size; zone->present_pages = realsize; zone->name = zone_names[j]; @@ -1970,3 +1977,69 @@ int lower_zone_protection_sysctl_handler(ctl_table *table, int write, setup_per_zone_protection(); return 0; } + +/* + * allocate a large system hash table from bootmem + * - it is assumed that the hash table must contain an exact power-of-2 + * quantity of entries + */ +void *__init alloc_large_system_hash(const char *tablename, + unsigned long bucketsize, + unsigned long numentries, + int scale, + int consider_highmem, + unsigned int *_hash_shift, + unsigned int *_hash_mask) +{ + unsigned long mem, max, log2qty, size; + void *table; + + /* round applicable memory size up to nearest megabyte */ + mem = consider_highmem ? nr_all_pages : nr_kernel_pages; + mem += (1UL << (20 - PAGE_SHIFT)) - 1; + mem >>= 20 - PAGE_SHIFT; + mem <<= 20 - PAGE_SHIFT; + + /* limit to 1 bucket per 2^scale bytes of low memory (rounded up to + * nearest power of 2 in size) */ + if (scale > PAGE_SHIFT) + mem >>= (scale - PAGE_SHIFT); + else + mem <<= (PAGE_SHIFT - scale); + + mem = 1UL << (long_log2(mem) + 1); + + /* limit allocation size */ + max = (1UL << (PAGE_SHIFT + MAX_SYS_HASH_TABLE_ORDER)) / bucketsize; + if (max > mem) + max = mem; + + /* allow the kernel cmdline to have a say */ + if (!numentries || numentries > max) + numentries = max; + + log2qty = long_log2(numentries); + + do { + size = bucketsize << log2qty; + + table = (void *) alloc_bootmem(size); + + } while (!table && size > PAGE_SIZE); + + if (!table) + panic("Failed to allocate %s hash table\n", tablename); + + printk("%s hash table entries: %d (order: %d, %lu bytes)\n", + tablename, + (1U << log2qty), + long_log2(size) - PAGE_SHIFT, + size); + + if (_hash_shift) + *_hash_shift = log2qty; + if (_hash_mask) + *_hash_mask = (1 << log2qty) - 1; + + return table; +} diff --git a/mm/swapfile.c b/mm/swapfile.c index 2eabfd19a50c..154d05795678 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -467,6 +467,13 @@ static unsigned long unuse_pmd(struct vm_area_struct * vma, pmd_t *dir, if (unlikely(pte_same(*pte, swp_pte))) { unuse_pte(vma, offset + address, pte, entry, page); pte_unmap(pte); + + /* + * Move the page to the active list so it is not + * immediately swapped out again after swapon. + */ + activate_page(page); + /* add 1 since address may be 0 */ return 1 + offset + address; } diff --git a/net/core/dev.c b/net/core/dev.c index 27cbb530b95b..9729210ca4cb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -107,6 +107,7 @@ #include <linux/module.h> #include <linux/kallsyms.h> #include <linux/netpoll.h> +#include <linux/rcupdate.h> #ifdef CONFIG_NET_RADIO #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */ #include <net/iw_handler.h> @@ -1305,6 +1306,20 @@ int __skb_linearize(struct sk_buff *skb, int gfp_mask) return 0; } +#define HARD_TX_LOCK_BH(dev, cpu) { \ + if ((dev->features & NETIF_F_LLTX) == 0) { \ + spin_lock_bh(&dev->xmit_lock); \ + dev->xmit_lock_owner = cpu; \ + } \ +} + +#define HARD_TX_UNLOCK_BH(dev) { \ + if ((dev->features & NETIF_F_LLTX) == 0) { \ + dev->xmit_lock_owner = -1; \ + spin_unlock_bh(&dev->xmit_lock); \ + } \ +} + /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit @@ -1348,18 +1363,35 @@ int dev_queue_xmit(struct sk_buff *skb) if (skb_checksum_help(&skb, 0)) goto out_kfree_skb; - /* Grab device queue */ - spin_lock_bh(&dev->queue_lock); + rcu_read_lock(); + /* Updates of qdisc are serialized by queue_lock. + * The struct Qdisc which is pointed to by qdisc is now a + * rcu structure - it may be accessed without acquiring + * a lock (but the structure may be stale.) The freeing of the + * qdisc will be deferred until it's known that there are no + * more references to it. + * + * If the qdisc has an enqueue function, we still need to + * hold the queue_lock before calling it, since queue_lock + * also serializes access to the device queue. + */ + q = dev->qdisc; + smp_read_barrier_depends(); if (q->enqueue) { + /* Grab device queue */ + spin_lock_bh(&dev->queue_lock); + rc = q->enqueue(skb, q); qdisc_run(dev); spin_unlock_bh(&dev->queue_lock); + rcu_read_unlock(); rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc; goto out; } + rcu_read_unlock(); /* The device has no queue. Common case for software devices: loopback, all the sorts of tunnels... @@ -1374,17 +1406,12 @@ int dev_queue_xmit(struct sk_buff *skb) Either shot noqueue qdisc, it is even simpler 8) */ if (dev->flags & IFF_UP) { + preempt_disable(); int cpu = smp_processor_id(); if (dev->xmit_lock_owner != cpu) { - /* - * The spin_lock effectivly does a preempt lock, but - * we are about to drop that... - */ - preempt_disable(); - spin_unlock(&dev->queue_lock); - spin_lock(&dev->xmit_lock); - dev->xmit_lock_owner = cpu; + + HARD_TX_LOCK_BH(dev, cpu); preempt_enable(); if (!netif_queue_stopped(dev)) { @@ -1393,18 +1420,17 @@ int dev_queue_xmit(struct sk_buff *skb) rc = 0; if (!dev->hard_start_xmit(skb, dev)) { - dev->xmit_lock_owner = -1; - spin_unlock_bh(&dev->xmit_lock); + HARD_TX_UNLOCK_BH(dev); goto out; } } - dev->xmit_lock_owner = -1; - spin_unlock_bh(&dev->xmit_lock); + HARD_TX_UNLOCK_BH(dev); if (net_ratelimit()) printk(KERN_CRIT "Virtual device %s asks to " "queue packet!\n", dev->name); goto out_enetdown; } else { + preempt_enable(); /* Recursion is detected! It is possible, * unfortunately */ if (net_ratelimit()) @@ -1412,7 +1438,6 @@ int dev_queue_xmit(struct sk_buff *skb) "%s, fix it urgently!\n", dev->name); } } - spin_unlock_bh(&dev->queue_lock); out_enetdown: rc = -ENETDOWN; out_kfree_skb: diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 7d72cdb49a57..f191cae7462e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1263,6 +1263,81 @@ void skb_add_mtu(int mtu) } #endif +static void inline skb_split_inside_header(struct sk_buff *skb, + struct sk_buff* skb1, + const u32 len, const int pos) +{ + int i; + + memcpy(skb_put(skb1, pos - len), skb->data + len, pos - len); + + /* And move data appendix as is. */ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i]; + + skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags; + skb_shinfo(skb)->nr_frags = 0; + skb1->data_len = skb->data_len; + skb1->len += skb1->data_len; + skb->data_len = 0; + skb->len = len; + skb->tail = skb->data + len; +} + +static void inline skb_split_no_header(struct sk_buff *skb, + struct sk_buff* skb1, + const u32 len, int pos) +{ + int i, k = 0; + const int nfrags = skb_shinfo(skb)->nr_frags; + + skb_shinfo(skb)->nr_frags = 0; + skb1->len = skb1->data_len = skb->len - len; + skb->len = len; + skb->data_len = len - pos; + + for (i = 0; i < nfrags; i++) { + int size = skb_shinfo(skb)->frags[i].size; + + if (pos + size > len) { + skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i]; + + if (pos < len) { + /* Split frag. + * We have to variants in this case: + * 1. Move all the frag to the second + * part, if it is possible. F.e. + * this approach is mandatory for TUX, + * where splitting is expensive. + * 2. Split is accurately. We make this. + */ + get_page(skb_shinfo(skb)->frags[i].page); + skb_shinfo(skb1)->frags[0].page_offset += len - pos; + skb_shinfo(skb1)->frags[0].size -= len - pos; + skb_shinfo(skb)->frags[i].size = len - pos; + skb_shinfo(skb)->nr_frags++; + } + k++; + } else + skb_shinfo(skb)->nr_frags++; + pos += size; + } + skb_shinfo(skb1)->nr_frags = k; +} + +/** + * skb_split - Split fragmented skb to two parts at length len. + */ +void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len) +{ + int pos = skb_headlen(skb); + + if (len < pos) /* Split line is inside header. */ + skb_split_inside_header(skb, skb1, len, pos); + else /* Second chunk has no header, nothing to copy. */ + skb_split_no_header(skb, skb1, len, pos); +} + void __init skb_init(void) { skbuff_head_cache = kmem_cache_create("skbuff_head_cache", @@ -1300,3 +1375,4 @@ EXPORT_SYMBOL(skb_queue_head); EXPORT_SYMBOL(skb_queue_tail); EXPORT_SYMBOL(skb_unlink); EXPORT_SYMBOL(skb_append); +EXPORT_SYMBOL(skb_split); diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 93103a3cb100..46215ba94c01 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -201,7 +201,7 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len return 0; } -#ifdef CONFIG_ECONET_NATIVE +#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) /* * Queue a transmit result for the user to be told about. */ @@ -228,7 +228,9 @@ static void tx_result(struct sock *sk, unsigned long cookie, int result) if (sock_queue_rcv_skb(sk, skb) < 0) kfree_skb(skb); } +#endif +#ifdef CONFIG_ECONET_NATIVE /* * Called by the Econet hardware driver when a packet transmit * has completed. Tell the user. @@ -255,6 +257,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, struct ec_addr addr; int err; unsigned char port, cb; +#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) + struct sk_buff *skb; + struct ec_cb *eb; +#endif #ifdef CONFIG_ECONET_AUNUDP struct msghdr udpmsg; struct iovec iov[msg->msg_iovlen+1]; @@ -311,8 +317,6 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, { /* Real hardware Econet. We're not worthy etc. */ #ifdef CONFIG_ECONET_NATIVE - struct ec_cb *eb; - struct sk_buff *skb; unsigned short proto = 0; dev_hold(dev); @@ -717,7 +721,7 @@ static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { #include <linux/smp_lock.h> SOCKOPS_WRAP(econet, PF_ECONET); -#ifdef CONFIG_ECONET_AUNUDP +#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) /* * Find the listening socket, if any, for the given data. */ @@ -761,7 +765,9 @@ static int ec_queue_packet(struct sock *sk, struct sk_buff *skb, return sock_queue_rcv_skb(sk, skb); } +#endif +#ifdef CONFIG_ECONET_AUNUDP /* * Send an AUN protocol response. */ diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 0d62398f71a6..cbe0c7295c2d 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -74,12 +74,15 @@ static int ah_output(struct sk_buff **pskb) } spin_lock_bh(&x->lock); - err = xfrm_check_output(x, *pskb, AF_INET); + err = xfrm_state_check(x, *pskb); if (err) goto error; iph = (*pskb)->nh.iph; if (x->props.mode) { + err = xfrm4_tunnel_check_size(*pskb); + if (err) + goto error; top_iph = (struct iphdr*)skb_push(*pskb, x->props.header_len); top_iph->ihl = 5; top_iph->version = 4; diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 4755e0dcc90d..acecd602a2c8 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -49,19 +49,24 @@ int esp_output(struct sk_buff **pskb) } spin_lock_bh(&x->lock); - err = xfrm_check_output(x, *pskb, AF_INET); + err = xfrm_state_check(x, *pskb); if (err) goto error; - err = -ENOMEM; - /* Strip IP header in transport mode. Save it. */ - if (!x->props.mode) { + if (x->props.mode) { + err = xfrm4_tunnel_check_size(*pskb); + if (err) + goto error; + } else { + /* Strip IP header in transport mode. Save it. */ iph = (*pskb)->nh.iph; memcpy(&tmp_iph, iph, iph->ihl*4); __skb_pull(*pskb, iph->ihl*4); } /* Now skb is pure payload to encrypt */ + err = -ENOMEM; + /* Round to block size */ clen = (*pskb)->len; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 60fc5091c0ef..34a4a3feccb7 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -702,17 +702,6 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk return 0; } -static inline int -skb_can_coalesce(struct sk_buff *skb, int i, struct page *page, int off) -{ - if (i) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1]; - return page == frag->page && - off == frag->page_offset+frag->size; - } - return 0; -} - static inline unsigned int csum_page(struct page *page, int offset, int copy) { diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index e20c7e43b215..7201cacf4e5c 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -164,12 +164,16 @@ static int ipcomp_output(struct sk_buff **pskb) } spin_lock_bh(&x->lock); - err = xfrm_check_output(x, *pskb, AF_INET); + err = xfrm_state_check(x, *pskb); if (err) goto error; - /* Don't bother compressing */ - if (!x->props.mode) { + if (x->props.mode) { + err = xfrm4_tunnel_check_size(*pskb); + if (err) + goto error; + } else { + /* Don't bother compressing */ iph = (*pskb)->nh.iph; hdr_len = iph->ihl * 4; } diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 67c2fd2a5335..1f47e9bbc4eb 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -28,6 +28,7 @@ #include <linux/proc_fs.h> #include <linux/vmalloc.h> #include <net/checksum.h> +#include <net/ip.h> #include <linux/stddef.h> #include <linux/sysctl.h> #include <linux/slab.h> diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 4d378394aac4..fbe26d1ca0ad 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -24,6 +24,7 @@ #include <linux/sysctl.h> #endif #include <net/checksum.h> +#include <net/ip.h> #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock) #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock) diff --git a/net/ipv4/netfilter/ip_fw_compat_redir.c b/net/ipv4/netfilter/ip_fw_compat_redir.c index 6a24a5cb17e0..7f68c1ed5a87 100644 --- a/net/ipv4/netfilter/ip_fw_compat_redir.c +++ b/net/ipv4/netfilter/ip_fw_compat_redir.c @@ -22,6 +22,7 @@ #include <linux/udp.h> #include <linux/tcp.h> #include <net/checksum.h> +#include <net/ip.h> #include <linux/timer.h> #include <linux/netdevice.h> #include <linux/if.h> diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index a84453f899fe..9765fd2d5cf1 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -27,6 +27,7 @@ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/proc_fs.h> +#include <net/ip.h> #include <net/checksum.h> #include <linux/spinlock.h> diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index fb499905f05d..54bc4684cc9d 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/netfilter.h> #include <net/protocol.h> +#include <net/ip.h> #include <net/checksum.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4/ip_nat_rule.h> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f12f5904bfa5..cf0adc2f1a89 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -670,11 +670,6 @@ static int wait_for_tcp_connect(struct sock *sk, int flags, long *timeo_p) return 0; } -static inline int tcp_memory_free(struct sock *sk) -{ - return sk->sk_wmem_queued < sk->sk_sndbuf; -} - /* * Wait for more memory for a socket */ @@ -686,7 +681,7 @@ static int wait_for_tcp_memory(struct sock *sk, long *timeo) long current_timeo = *timeo; DEFINE_WAIT(wait); - if (tcp_memory_free(sk)) + if (sk_stream_memory_free(sk)) current_timeo = vm_wait = (net_random() % (HZ / 5)) + 2; for (;;) { @@ -701,13 +696,13 @@ static int wait_for_tcp_memory(struct sock *sk, long *timeo) if (signal_pending(current)) goto do_interrupted; clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); - if (tcp_memory_free(sk) && !vm_wait) + if (sk_stream_memory_free(sk) && !vm_wait) break; set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); tp->write_pending++; release_sock(sk); - if (!tcp_memory_free(sk) || vm_wait) + if (!sk_stream_memory_free(sk) || vm_wait) current_timeo = schedule_timeout(current_timeo); lock_sock(sk); tp->write_pending--; @@ -737,17 +732,6 @@ do_interrupted: goto out; } -static inline int can_coalesce(struct sk_buff *skb, int i, struct page *page, - int off) -{ - if (i) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; - return page == frag->page && - off == frag->page_offset + frag->size; - } - return 0; -} - static inline void fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size) { @@ -849,7 +833,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse if (!tp->send_head || (copy = mss_now - skb->len) <= 0) { new_segment: - if (!tcp_memory_free(sk)) + if (!sk_stream_memory_free(sk)) goto wait_for_sndbuf; skb = tcp_alloc_pskb(sk, 0, tp->mss_cache, @@ -865,7 +849,7 @@ new_segment: copy = size; i = skb_shinfo(skb)->nr_frags; - if (can_coalesce(skb, i, page, offset)) { + if (skb_can_coalesce(skb, i, page, offset)) { skb_shinfo(skb)->frags[i - 1].size += copy; } else if (i < MAX_SKB_FRAGS) { get_page(page); @@ -948,53 +932,6 @@ ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, #define TCP_PAGE(sk) (inet_sk(sk)->sndmsg_page) #define TCP_OFF(sk) (inet_sk(sk)->sndmsg_off) -static inline int tcp_copy_to_page(struct sock *sk, char __user *from, - struct sk_buff *skb, struct page *page, - int off, int copy) -{ - int err = 0; - unsigned int csum; - - if (skb->ip_summed == CHECKSUM_NONE) { - csum = csum_and_copy_from_user(from, page_address(page) + off, - copy, 0, &err); - if (err) return err; - skb->csum = csum_block_add(skb->csum, csum, skb->len); - } else { - if (copy_from_user(page_address(page) + off, from, copy)) - return -EFAULT; - } - - skb->len += copy; - skb->data_len += copy; - skb->truesize += copy; - sk->sk_wmem_queued += copy; - sk->sk_forward_alloc -= copy; - return 0; -} - -static inline int skb_add_data(struct sk_buff *skb, char __user *from, int copy) -{ - int err = 0; - unsigned int csum; - int off = skb->len; - - if (skb->ip_summed == CHECKSUM_NONE) { - csum = csum_and_copy_from_user(from, skb_put(skb, copy), - copy, 0, &err); - if (!err) { - skb->csum = csum_block_add(skb->csum, csum, off); - return 0; - } - } else { - if (!copy_from_user(skb_put(skb, copy), from, copy)) - return 0; - } - - __skb_trim(skb, off); - return -EFAULT; -} - static inline int select_size(struct sock *sk, struct tcp_opt *tp) { int tmp = tp->mss_cache_std; @@ -1063,7 +1000,7 @@ new_segment: /* Allocate new segment. If the interface is SG, * allocate skb fitting to single page. */ - if (!tcp_memory_free(sk)) + if (!sk_stream_memory_free(sk)) goto wait_for_sndbuf; skb = tcp_alloc_pskb(sk, select_size(sk, tp), @@ -1100,7 +1037,7 @@ new_segment: struct page *page = TCP_PAGE(sk); int off = TCP_OFF(sk); - if (can_coalesce(skb, i, page, off) && + if (skb_can_coalesce(skb, i, page, off) && off != PAGE_SIZE) { /* We can extend the last page * fragment. */ @@ -1138,7 +1075,7 @@ new_segment: /* Time to copy data. We are close to * the end! */ - err = tcp_copy_to_page(sk, from, skb, page, + err = skb_copy_to_page(sk, from, skb, page, off, copy); if (err) { /* If this page was new, give it to the diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index ac6c55259e1a..ad0c2ac89a1a 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -354,70 +354,6 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss) } } -/* Split fragmented skb to two parts at length len. */ - -static void skb_split(struct sk_buff *skb, struct sk_buff *skb1, u32 len) -{ - int i; - int pos = skb_headlen(skb); - - if (len < pos) { - /* Split line is inside header. */ - memcpy(skb_put(skb1, pos-len), skb->data + len, pos-len); - - /* And move data appendix as is. */ - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) - skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i]; - - skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags; - skb_shinfo(skb)->nr_frags = 0; - - skb1->data_len = skb->data_len; - skb1->len += skb1->data_len; - skb->data_len = 0; - skb->len = len; - skb->tail = skb->data+len; - } else { - int k = 0; - int nfrags = skb_shinfo(skb)->nr_frags; - - /* Second chunk has no header, nothing to copy. */ - - skb_shinfo(skb)->nr_frags = 0; - skb1->len = skb1->data_len = skb->len - len; - skb->len = len; - skb->data_len = len - pos; - - for (i=0; i<nfrags; i++) { - int size = skb_shinfo(skb)->frags[i].size; - if (pos + size > len) { - skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i]; - - if (pos < len) { - /* Split frag. - * We have to variants in this case: - * 1. Move all the frag to the second - * part, if it is possible. F.e. - * this approach is mandatory for TUX, - * where splitting is expensive. - * 2. Split is accurately. We make this. - */ - get_page(skb_shinfo(skb)->frags[i].page); - skb_shinfo(skb1)->frags[0].page_offset += (len-pos); - skb_shinfo(skb1)->frags[0].size -= (len-pos); - skb_shinfo(skb)->frags[i].size = len-pos; - skb_shinfo(skb)->nr_frags++; - } - k++; - } else { - skb_shinfo(skb)->nr_frags++; - } - pos += size; - } - skb_shinfo(skb1)->nr_frags = k; - } -} - /* Function to create two new TCP segments. Shrinks the given segment * to the specified size and appends a new segment with the rest of the * packet to the list. This won't be called frequently, I hope. diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 26e292c9db9e..31afc9cfc0a6 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -10,7 +10,8 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ ip6_flowlabel.o ipv6_syms.o -ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o +ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ + xfrm6_tunnel.o ipv6-objs += $(ipv6-y) obj-$(CONFIG_INET6_AH) += ah6.o diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 185092c0d6b5..bb7ee1a25598 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -163,11 +163,15 @@ int ah6_output(struct sk_buff **pskb) } spin_lock_bh(&x->lock); - err = xfrm_check_output(x, *pskb, AF_INET6); + err = xfrm_state_check(x, *pskb); if (err) goto error; if (x->props.mode) { + err = xfrm6_tunnel_check_size(*pskb); + if (err) + goto error; + iph = (*pskb)->nh.ipv6h; (*pskb)->nh.ipv6h = (struct ipv6hdr*)skb_push(*pskb, x->props.header_len); (*pskb)->nh.ipv6h->version = 6; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 8156942b141f..fb2720697d96 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -65,14 +65,16 @@ int esp6_output(struct sk_buff **pskb) } spin_lock_bh(&x->lock); - err = xfrm_check_output(x, *pskb, AF_INET6); + err = xfrm_state_check(x, *pskb); if (err) goto error; - err = -ENOMEM; - - /* Strip IP header in transport mode. Save it. */ - if (!x->props.mode) { + if (x->props.mode) { + err = xfrm6_tunnel_check_size(*pskb); + if (err) + goto error; + } else { + /* Strip IP header in transport mode. Save it. */ hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr); nexthdr = *prevhdr; *prevhdr = IPPROTO_ESP; @@ -86,6 +88,7 @@ int esp6_output(struct sk_buff **pskb) } /* Now skb is pure payload to encrypt */ + err = -ENOMEM; /* Round to block size */ clen = (*pskb)->len; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index cfecd15d9b5c..6bc7ebcc32fd 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -55,7 +55,7 @@ #include <net/sock.h> #include <net/ipv6.h> -#include <net/checksum.h> +#include <net/ip6_checksum.h> #include <net/protocol.h> #include <net/raw.h> #include <net/rawv6.h> diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index e8153808dbe9..9e5677dd45a2 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -123,7 +123,7 @@ static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst) * else %NULL **/ -struct ip6_tnl * +static struct ip6_tnl * ip6ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local) { unsigned h0 = HASH(remote); @@ -387,8 +387,9 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) * to the specifications in RFC 2473. **/ -void ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) +static void +ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info) { struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; struct ip6_tnl *t; @@ -496,7 +497,8 @@ out: * Return: 0 **/ -int ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) +static int +ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) { struct sk_buff *skb = *pskb; struct ipv6hdr *ipv6h; @@ -510,6 +512,11 @@ int ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) read_lock(&ip6ip6_lock); if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { + if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { + kfree_skb(skb); + return 0; + } + if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { t->stat.rx_dropped++; read_unlock(&ip6ip6_lock); @@ -533,8 +540,7 @@ int ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) read_unlock(&ip6ip6_lock); icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); discard: - kfree_skb(skb); - return 0; + return 1; } static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) @@ -598,7 +604,8 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) * 0 **/ -int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) +static int +ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) { struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; struct net_device_stats *stats = &t->stat; @@ -1079,7 +1086,8 @@ ip6ip6_tnl_dev_init(struct net_device *dev) * Return: 0 **/ -int ip6ip6_fb_tnl_dev_init(struct net_device *dev) +static int +ip6ip6_fb_tnl_dev_init(struct net_device *dev) { struct ip6_tnl *t = dev->priv; ip6ip6_tnl_dev_init_gen(dev); @@ -1088,10 +1096,9 @@ int ip6ip6_fb_tnl_dev_init(struct net_device *dev) return 0; } -static struct inet6_protocol ip6ip6_protocol = { +static struct xfrm6_tunnel ip6ip6_handler = { .handler = ip6ip6_rcv, .err_handler = ip6ip6_err, - .flags = INET6_PROTO_FINAL }; /** @@ -1104,9 +1111,9 @@ static int __init ip6_tunnel_init(void) { int err; - if ((err = inet6_add_protocol(&ip6ip6_protocol, IPPROTO_IPV6)) < 0) { - printk(KERN_ERR "Failed to register IPv6 protocol\n"); - return err; + if (xfrm6_tunnel_register(&ip6ip6_handler) < 0) { + printk(KERN_ERR "ip6ip6 init: can't register tunnel\n"); + return -EAGAIN; } ip6ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", ip6ip6_tnl_dev_setup); @@ -1123,7 +1130,7 @@ static int __init ip6_tunnel_init(void) } return 0; fail: - inet6_del_protocol(&ip6ip6_protocol, IPPROTO_IPV6); + xfrm6_tunnel_deregister(&ip6ip6_handler); return err; } @@ -1133,8 +1140,10 @@ fail: static void __exit ip6_tunnel_cleanup(void) { + if (xfrm6_tunnel_deregister(&ip6ip6_handler) < 0) + printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); + unregister_netdev(ip6ip6_fb_tnl_dev); - inet6_del_protocol(&ip6ip6_protocol, IPPROTO_IPV6); } module_init(ip6_tunnel_init); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index b357db4cc84b..d129078f0b8f 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -140,11 +140,15 @@ static int ipcomp6_output(struct sk_buff **pskb) spin_lock_bh(&x->lock); - err = xfrm_check_output(x, *pskb, AF_INET6); + err = xfrm_state_check(x, *pskb); if (err) goto error; if (x->props.mode) { + err = xfrm6_tunnel_check_size(*pskb); + if (err) + goto error; + hdr_len = sizeof(struct ipv6hdr); nexthdr = IPPROTO_IPV6; iph = (*pskb)->nh.ipv6h; @@ -258,6 +262,66 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, xfrm_state_put(x); } +static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) +{ + struct xfrm_state *t = NULL; + + t = xfrm_state_alloc(); + if (!t) + goto out; + + t->id.proto = IPPROTO_IPV6; + t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr); + memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); + memcpy(&t->sel, &x->sel, sizeof(t->sel)); + t->props.family = AF_INET6; + t->props.mode = 1; + memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); + + t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family); + if (t->type == NULL) + goto error; + + if (t->type->init_state(t, NULL)) + goto error; + + t->km.state = XFRM_STATE_VALID; + atomic_set(&t->tunnel_users, 1); + +out: + return t; + +error: + xfrm_state_put(t); + goto out; +} + +static int ipcomp6_tunnel_attach(struct xfrm_state *x) +{ + int err = 0; + struct xfrm_state *t = NULL; + u32 spi; + + spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&x->props.saddr); + if (spi) + t = xfrm_state_lookup((xfrm_address_t *)&x->id.daddr, + spi, IPPROTO_IPV6, AF_INET6); + if (!t) { + t = ipcomp6_tunnel_create(x); + if (!t) { + err = -EINVAL; + goto out; + } + xfrm_state_insert(t); + xfrm_state_hold(t); + } + x->tunnel = t; + atomic_inc(&t->tunnel_users); + +out: + return err; +} + static void ipcomp6_free_data(struct ipcomp_data *ipcd) { if (ipcd->tfm) @@ -271,8 +335,11 @@ static void ipcomp6_destroy(struct xfrm_state *x) struct ipcomp_data *ipcd = x->data; if (!ipcd) return; + xfrm_state_delete_tunnel(x); ipcomp6_free_data(ipcd); kfree(ipcd); + + xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); } static int ipcomp6_init_state(struct xfrm_state *x, void *args) @@ -303,6 +370,12 @@ static int ipcomp6_init_state(struct xfrm_state *x, void *args) if (!ipcd->tfm) goto error; + if (x->props.mode) { + err = ipcomp6_tunnel_attach(x); + if (err) + goto error; + } + calg_desc = xfrm_calg_get_byname(x->calg->alg_name); BUG_ON(!calg_desc); ipcd->threshold = calg_desc->uinfo.comp.threshold; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 1f2896b7d530..f6d651dde985 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -60,7 +60,7 @@ #include <net/addrconf.h> #include <net/ip6_route.h> -#include <net/checksum.h> +#include <net/ip6_checksum.h> /* Set to 3 to get tracing... */ #define MCAST_DEBUG 2 diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 245dac731e5b..3b6d83eeb7f1 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -77,7 +77,7 @@ #include <net/icmp.h> #include <net/flow.h> -#include <net/checksum.h> +#include <net/ip6_checksum.h> #include <linux/proc_fs.h> #include <linux/netfilter.h> diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 0e1b275ad98b..079d3cac18e0 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -35,6 +35,7 @@ #include <asm/uaccess.h> #include <asm/ioctls.h> +#include <net/ip.h> #include <net/sock.h> #include <net/snmp.h> @@ -42,6 +43,7 @@ #include <net/ndisc.h> #include <net/protocol.h> #include <net/ip6_route.h> +#include <net/ip6_checksum.h> #include <net/addrconf.h> #include <net/transp_v6.h> #include <net/udp.h> diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 74923017b60e..80979412a65a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -51,6 +51,7 @@ #include <net/transp_v6.h> #include <net/addrconf.h> #include <net/ip6_route.h> +#include <net/ip6_checksum.h> #include <net/inet_ecn.h> #include <net/protocol.h> #include <net/xfrm.h> diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e2514081e4e6..52d2b8b3024e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -51,7 +51,7 @@ #include <net/udp.h> #include <net/inet_common.h> -#include <net/checksum.h> +#include <net/ip6_checksum.h> #include <net/xfrm.h> #include <linux/proc_fs.h> diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 1041ef9524af..b5a3bdb440e4 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -277,10 +277,12 @@ void __init xfrm6_init(void) { xfrm6_policy_init(); xfrm6_state_init(); + xfrm6_tunnel_init(); } void __exit xfrm6_fini(void) { + xfrm6_tunnel_fini(); //xfrm6_input_fini(); xfrm6_policy_fini(); xfrm6_state_fini(); diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c new file mode 100644 index 000000000000..f5a06546d301 --- /dev/null +++ b/net/ipv6/xfrm6_tunnel.c @@ -0,0 +1,634 @@ +/* + * Copyright (C)2003,2004 USAGI/WIDE Project + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors Mitsuru KANDA <mk@linux-ipv6.org> + * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> + * + * Based on net/ipv4/xfrm4_tunnel.c + * + */ +#include <linux/config.h> +#include <linux/module.h> +#include <linux/xfrm.h> +#include <linux/list.h> +#include <net/ip.h> +#include <net/xfrm.h> +#include <net/icmp.h> +#include <net/ipv6.h> +#include <linux/ipv6.h> +#include <linux/icmpv6.h> + +#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG +# define X6TDEBUG 3 +#else +# define X6TDEBUG 1 +#endif + +#define X6TPRINTK(fmt, args...) printk(fmt, ## args) +#define X6TNOPRINTK(fmt, args...) do { ; } while(0) + +#if X6TDEBUG >= 1 +# define X6TPRINTK1 X6TPRINTK +#else +# define X6TPRINTK1 X6TNOPRINTK +#endif + +#if X6TDEBUG >= 3 +# define X6TPRINTK3 X6TPRINTK +#else +# define X6TPRINTK3 X6TNOPRINTK +#endif + +/* + * xfrm_tunnel_spi things are for allocating unique id ("spi") + * per xfrm_address_t. + */ +struct xfrm6_tunnel_spi { + struct hlist_node list_byaddr; + struct hlist_node list_byspi; + xfrm_address_t addr; + u32 spi; + atomic_t refcnt; +#ifdef XFRM6_TUNNEL_SPI_MAGIC + u32 magic; +#endif +}; + +#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG +# define XFRM6_TUNNEL_SPI_MAGIC 0xdeadbeef +#endif + +static rwlock_t xfrm6_tunnel_spi_lock = RW_LOCK_UNLOCKED; + +static u32 xfrm6_tunnel_spi; + +#define XFRM6_TUNNEL_SPI_MIN 1 +#define XFRM6_TUNNEL_SPI_MAX 0xffffffff + +static kmem_cache_t *xfrm6_tunnel_spi_kmem; + +#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 +#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 + +static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE]; +static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE]; + +#ifdef XFRM6_TUNNEL_SPI_MAGIC +static int x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi, + const char *name) +{ + if (unlikely(x6spi->magic != XFRM6_TUNNEL_SPI_MAGIC)) { + X6TPRINTK3(KERN_DEBUG "%s(): x6spi object " + "at %p has corrupted magic %08x " + "(should be %08x)\n", + name, x6spi, x6spi->magic, XFRM6_TUNNEL_SPI_MAGIC); + return -1; + } + return 0; +} +#else +static int inline x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi, + const char *name) +{ + return 0; +} +#endif + +#define X6SPI_CHECK_MAGIC(x6spi) x6spi_check_magic((x6spi), __FUNCTION__) + + +static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) +{ + unsigned h; + + X6TPRINTK3(KERN_DEBUG "%s(addr=%p)\n", __FUNCTION__, addr); + + h = addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]; + h ^= h >> 16; + h ^= h >> 8; + h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1; + + X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, h); + + return h; +} + +static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi) +{ + return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; +} + + +static int xfrm6_tunnel_spi_init(void) +{ + int i; + + X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); + + xfrm6_tunnel_spi = 0; + xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi", + sizeof(struct xfrm6_tunnel_spi), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!xfrm6_tunnel_spi_kmem) { + X6TPRINTK1(KERN_ERR + "%s(): failed to allocate xfrm6_tunnel_spi_kmem\n", + __FUNCTION__); + return -ENOMEM; + } + + for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) + INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byaddr[i]); + for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) + INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byspi[i]); + return 0; +} + +static void xfrm6_tunnel_spi_fini(void) +{ + int i; + + X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); + + for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) { + if (!hlist_empty(&xfrm6_tunnel_spi_byaddr[i])) + goto err; + } + for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) { + if (!hlist_empty(&xfrm6_tunnel_spi_byspi[i])) + goto err; + } + kmem_cache_destroy(xfrm6_tunnel_spi_kmem); + xfrm6_tunnel_spi_kmem = NULL; + return; +err: + X6TPRINTK1(KERN_ERR "%s(): table is not empty\n", __FUNCTION__); + return; +} + +static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) +{ + struct xfrm6_tunnel_spi *x6spi; + struct hlist_node *pos; + + X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); + + hlist_for_each_entry(x6spi, pos, + &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], + list_byaddr) { + if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { + X6SPI_CHECK_MAGIC(x6spi); + X6TPRINTK3(KERN_DEBUG "%s() = %p(%u)\n", __FUNCTION__, x6spi, x6spi->spi); + return x6spi; + } + } + + X6TPRINTK3(KERN_DEBUG "%s() = NULL(0)\n", __FUNCTION__); + return NULL; +} + +u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) +{ + struct xfrm6_tunnel_spi *x6spi; + u32 spi; + + X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); + + read_lock_bh(&xfrm6_tunnel_spi_lock); + x6spi = __xfrm6_tunnel_spi_lookup(saddr); + spi = x6spi ? x6spi->spi : 0; + read_unlock_bh(&xfrm6_tunnel_spi_lock); + return spi; +} + +EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); + +static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) +{ + u32 spi; + struct xfrm6_tunnel_spi *x6spi; + struct hlist_node *pos; + unsigned index; + + X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); + + if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || + xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) + xfrm6_tunnel_spi = XFRM6_TUNNEL_SPI_MIN; + else + xfrm6_tunnel_spi++; + + for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { + index = xfrm6_tunnel_spi_hash_byspi(spi); + hlist_for_each_entry(x6spi, pos, + &xfrm6_tunnel_spi_byspi[index], + list_byspi) { + if (x6spi->spi == spi) + goto try_next_1; + } + xfrm6_tunnel_spi = spi; + goto alloc_spi; +try_next_1:; + } + for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { + index = xfrm6_tunnel_spi_hash_byspi(spi); + hlist_for_each_entry(x6spi, pos, + &xfrm6_tunnel_spi_byspi[index], + list_byspi) { + if (x6spi->spi == spi) + goto try_next_2; + } + xfrm6_tunnel_spi = spi; + goto alloc_spi; +try_next_2:; + } + spi = 0; + goto out; +alloc_spi: + X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " + "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + __FUNCTION__, + NIP6(*(struct in6_addr *)saddr)); + x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC); + if (!x6spi) { + X6TPRINTK1(KERN_ERR "%s(): kmem_cache_alloc() failed\n", + __FUNCTION__); + goto out; + } +#ifdef XFRM6_TUNNEL_SPI_MAGIC + x6spi->magic = XFRM6_TUNNEL_SPI_MAGIC; +#endif + memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr)); + x6spi->spi = spi; + atomic_set(&x6spi->refcnt, 1); + + hlist_add_head(&x6spi->list_byspi, &xfrm6_tunnel_spi_byspi[index]); + + index = xfrm6_tunnel_spi_hash_byaddr(saddr); + hlist_add_head(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]); + X6SPI_CHECK_MAGIC(x6spi); +out: + X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi); + return spi; +} + +u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) +{ + struct xfrm6_tunnel_spi *x6spi; + u32 spi; + + X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); + + write_lock_bh(&xfrm6_tunnel_spi_lock); + x6spi = __xfrm6_tunnel_spi_lookup(saddr); + if (x6spi) { + atomic_inc(&x6spi->refcnt); + spi = x6spi->spi; + } else + spi = __xfrm6_tunnel_alloc_spi(saddr); + write_unlock_bh(&xfrm6_tunnel_spi_lock); + + X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi); + + return spi; +} + +EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi); + +void xfrm6_tunnel_free_spi(xfrm_address_t *saddr) +{ + struct xfrm6_tunnel_spi *x6spi; + struct hlist_node *pos, *n; + + X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); + + write_lock_bh(&xfrm6_tunnel_spi_lock); + + hlist_for_each_entry_safe(x6spi, pos, n, + &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], + list_byaddr) + { + if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { + X6TPRINTK3(KERN_DEBUG "%s(): x6spi object " + "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " + "found at %p\n", + __FUNCTION__, + NIP6(*(struct in6_addr *)saddr), + x6spi); + X6SPI_CHECK_MAGIC(x6spi); + if (atomic_dec_and_test(&x6spi->refcnt)) { + hlist_del(&x6spi->list_byaddr); + hlist_del(&x6spi->list_byspi); + kmem_cache_free(xfrm6_tunnel_spi_kmem, x6spi); + break; + } + } + } + write_unlock_bh(&xfrm6_tunnel_spi_lock); +} + +EXPORT_SYMBOL(xfrm6_tunnel_free_spi); + +int xfrm6_tunnel_check_size(struct sk_buff *skb) +{ + int mtu, ret = 0; + struct dst_entry *dst = skb->dst; + + mtu = dst_pmtu(dst) - sizeof(struct ipv6hdr); + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + + if (skb->len > mtu) { + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + ret = -EMSGSIZE; + } + + return ret; +} + +EXPORT_SYMBOL(xfrm6_tunnel_check_size); + +static int xfrm6_tunnel_output(struct sk_buff **pskb) +{ + struct sk_buff *skb = *pskb; + struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; + struct ipv6hdr *iph, *top_iph; + int err; + + if ((err = xfrm6_tunnel_check_size(skb)) != 0) + goto error_nolock; + + iph = skb->nh.ipv6h; + + top_iph = (struct ipv6hdr *)skb_push(skb, x->props.header_len); + top_iph->version = 6; + top_iph->priority = iph->priority; + top_iph->flow_lbl[0] = iph->flow_lbl[0]; + top_iph->flow_lbl[1] = iph->flow_lbl[1]; + top_iph->flow_lbl[2] = iph->flow_lbl[2]; + top_iph->nexthdr = IPPROTO_IPV6; + top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); + top_iph->hop_limit = iph->hop_limit; + memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr)); + memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr)); + skb->nh.raw = skb->data; + skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr); + + x->curlft.bytes += skb->len; + x->curlft.packets++; + + spin_unlock_bh(&x->lock); + + if ((skb->dst = dst_pop(dst)) == NULL) { + kfree_skb(skb); + err = -EHOSTUNREACH; + goto error_nolock; + } + + return NET_XMIT_BYPASS; + +error_nolock: + kfree_skb(skb); + return err; +} + +static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +{ + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) + return -EINVAL; + + skb->mac.raw = skb->nh.raw; + skb->nh.raw = skb->data; + dst_release(skb->dst); + skb->dst = NULL; + skb->protocol = htons(ETH_P_IPV6); + skb->pkt_type = PACKET_HOST; + netif_rx(skb); + + return 0; +} + +static struct xfrm6_tunnel *xfrm6_tunnel_handler; +static DECLARE_MUTEX(xfrm6_tunnel_sem); + +int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) +{ + int ret; + + down(&xfrm6_tunnel_sem); + ret = 0; + if (xfrm6_tunnel_handler != NULL) + ret = -EINVAL; + if (!ret) + xfrm6_tunnel_handler = handler; + up(&xfrm6_tunnel_sem); + + return ret; +} + +EXPORT_SYMBOL(xfrm6_tunnel_register); + +int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) +{ + int ret; + + down(&xfrm6_tunnel_sem); + ret = 0; + if (xfrm6_tunnel_handler != handler) + ret = -EINVAL; + if (!ret) + xfrm6_tunnel_handler = NULL; + up(&xfrm6_tunnel_sem); + + synchronize_net(); + + return ret; +} + +EXPORT_SYMBOL(xfrm6_tunnel_deregister); + +static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp) +{ + struct sk_buff *skb = *pskb; + struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; + struct xfrm_state *x = NULL; + struct ipv6hdr *iph = skb->nh.ipv6h; + int err = 0; + u32 spi; + + /* device-like_ip6ip6_handler() */ + if (handler) { + err = handler->handler(pskb, nhoffp); + if (!err) + goto out; + } + + spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); + x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, + spi, + IPPROTO_IPV6, AF_INET6); + + if (!x) + goto drop; + + spin_lock(&x->lock); + + if (unlikely(x->km.state != XFRM_STATE_VALID)) + goto drop_unlock; + + err = xfrm6_tunnel_input(x, NULL, skb); + if (err) + goto drop_unlock; + + x->curlft.bytes += skb->len; + x->curlft.packets++; + spin_unlock(&x->lock); + xfrm_state_put(x); + +out: + return 0; + +drop_unlock: + spin_unlock(&x->lock); + xfrm_state_put(x); +drop: + kfree_skb(skb); + return -1; +} + +static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info) +{ + struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; + + /* call here first for device-like ip6ip6 err handling */ + if (handler) { + handler->err_handler(skb, opt, type, code, offset, info); + return; + } + + /* xfrm6_tunnel native err handling */ + switch (type) { + case ICMPV6_DEST_UNREACH: + switch (code) { + case ICMPV6_NOROUTE: + case ICMPV6_ADM_PROHIBITED: + case ICMPV6_NOT_NEIGHBOUR: + case ICMPV6_ADDR_UNREACH: + case ICMPV6_PORT_UNREACH: + default: + X6TPRINTK3(KERN_DEBUG + "xfrm6_tunnel: Destination Unreach.\n"); + break; + } + break; + case ICMPV6_PKT_TOOBIG: + X6TPRINTK3(KERN_DEBUG + "xfrm6_tunnel: Packet Too Big.\n"); + break; + case ICMPV6_TIME_EXCEED: + switch (code) { + case ICMPV6_EXC_HOPLIMIT: + X6TPRINTK3(KERN_DEBUG + "xfrm6_tunnel: Too small Hoplimit.\n"); + break; + case ICMPV6_EXC_FRAGTIME: + default: + break; + } + break; + case ICMPV6_PARAMPROB: + switch (code) { + case ICMPV6_HDR_FIELD: break; + case ICMPV6_UNK_NEXTHDR: break; + case ICMPV6_UNK_OPTION: break; + } + break; + default: + break; + } + return; +} + +static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args) +{ + if (!x->props.mode) + return -EINVAL; + + x->props.header_len = sizeof(struct ipv6hdr); + + return 0; +} + +static void xfrm6_tunnel_destroy(struct xfrm_state *x) +{ + xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); +} + +static struct xfrm_type xfrm6_tunnel_type = { + .description = "IP6IP6", + .owner = THIS_MODULE, + .proto = IPPROTO_IPV6, + .init_state = xfrm6_tunnel_init_state, + .destructor = xfrm6_tunnel_destroy, + .input = xfrm6_tunnel_input, + .output = xfrm6_tunnel_output, +}; + +static struct inet6_protocol xfrm6_tunnel_protocol = { + .handler = xfrm6_tunnel_rcv, + .err_handler = xfrm6_tunnel_err, + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, +}; + +void __init xfrm6_tunnel_init(void) +{ + X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); + + if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) { + X6TPRINTK1(KERN_ERR + "xfrm6_tunnel init: can't add xfrm type\n"); + return; + } + if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) { + X6TPRINTK1(KERN_ERR + "xfrm6_tunnel init(): can't add protocol\n"); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + return; + } + if (xfrm6_tunnel_spi_init() < 0) { + X6TPRINTK1(KERN_ERR + "xfrm6_tunnel init: failed to initialize spi\n"); + inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + return; + } +} + +void __exit xfrm6_tunnel_fini(void) +{ + X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); + + xfrm6_tunnel_spi_fini(); + if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) + X6TPRINTK1(KERN_ERR + "xfrm6_tunnel close: can't remove protocol\n"); + if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0) + X6TPRINTK1(KERN_ERR + "xfrm6_tunnel close: can't remove xfrm type\n"); +} diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 432531dca1c8..85ed105d1a12 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -450,6 +450,9 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) if (!try_module_get(ops->owner)) goto err_out; + /* enqueue is accessed locklessly - make sure it's visible + * before we set a netdevice's qdisc pointer to sch */ + smp_wmb(); if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { write_lock(&qdisc_tree_lock); sch->next = dev->qdisc_list; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 97b56255c7be..111dad476d2b 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -30,6 +30,7 @@ #include <linux/skbuff.h> #include <linux/rtnetlink.h> #include <linux/init.h> +#include <linux/rcupdate.h> #include <net/sock.h> #include <net/pkt_sched.h> @@ -387,6 +388,9 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) sch->dev = dev; sch->stats.lock = &dev->queue_lock; atomic_set(&sch->refcnt, 1); + /* enqueue is accessed locklessly - make sure it's visible + * before we set a netdevice's qdisc pointer to sch */ + smp_wmb(); if (!ops->init || ops->init(sch, NULL) == 0) return sch; @@ -404,18 +408,36 @@ void qdisc_reset(struct Qdisc *qdisc) ops->reset(qdisc); } +/* this is the rcu callback function to clean up a qdisc when there + * are no further references to it */ + +static void __qdisc_destroy (void * arg) +{ + struct Qdisc *qdisc = (struct Qdisc *) arg; + struct Qdisc_ops *ops = qdisc->ops; + +#ifdef CONFIG_NET_ESTIMATOR + qdisc_kill_estimator(&qdisc->stats); +#endif + if (ops->reset) + ops->reset(qdisc); + if (ops->destroy) + ops->destroy(qdisc); + module_put(ops->owner); + + if (!(qdisc->flags&TCQ_F_BUILTIN)) + kfree(qdisc); +} + /* Under dev->queue_lock and BH! */ void qdisc_destroy(struct Qdisc *qdisc) { - struct Qdisc_ops *ops = qdisc->ops; - struct net_device *dev; + struct net_device *dev = qdisc->dev; if (!atomic_dec_and_test(&qdisc->refcnt)) return; - dev = qdisc->dev; - if (dev) { struct Qdisc *q, **qp; for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) { @@ -425,16 +447,9 @@ void qdisc_destroy(struct Qdisc *qdisc) } } } -#ifdef CONFIG_NET_ESTIMATOR - qdisc_kill_estimator(&qdisc->stats); -#endif - if (ops->reset) - ops->reset(qdisc); - if (ops->destroy) - ops->destroy(qdisc); - module_put(ops->owner); - if (!(qdisc->flags&TCQ_F_BUILTIN)) - kfree(qdisc); + + call_rcu(&qdisc->q_rcu, __qdisc_destroy, qdisc); + } diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile index 7cf00be13197..12bf0f88616c 100644 --- a/net/xfrm/Makefile +++ b/net/xfrm/Makefile @@ -2,7 +2,7 @@ # Makefile for the XFRM subsystem. # -obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o xfrm_output.o \ +obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o \ xfrm_export.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o diff --git a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c index fdd4d0ee7af7..e77179ccf742 100644 --- a/net/xfrm/xfrm_export.c +++ b/net/xfrm/xfrm_export.c @@ -18,6 +18,7 @@ EXPORT_SYMBOL(xfrm_state_add); EXPORT_SYMBOL(xfrm_state_update); EXPORT_SYMBOL(xfrm_state_check_expire); EXPORT_SYMBOL(xfrm_state_check_space); +EXPORT_SYMBOL(xfrm_state_check); EXPORT_SYMBOL(xfrm_state_lookup); EXPORT_SYMBOL(xfrm_state_register_afinfo); EXPORT_SYMBOL(xfrm_state_unregister_afinfo); @@ -27,7 +28,6 @@ EXPORT_SYMBOL(xfrm_state_delete_tunnel); EXPORT_SYMBOL(xfrm_replay_check); EXPORT_SYMBOL(xfrm_replay_advance); EXPORT_SYMBOL(xfrm_check_selectors); -EXPORT_SYMBOL(xfrm_check_output); EXPORT_SYMBOL(__secpath_destroy); EXPORT_SYMBOL(secpath_dup); EXPORT_SYMBOL(xfrm_get_acqseq); diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c deleted file mode 100644 index ae72dfde26d4..000000000000 --- a/net/xfrm/xfrm_output.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * generic xfrm output routines - * - * Copyright (c) 2003 James Morris <jmorris@intercode.com.au> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/skbuff.h> -#include <net/xfrm.h> - -int xfrm_check_output(struct xfrm_state *x, - struct sk_buff *skb, unsigned short family) -{ - int err; - - err = xfrm_state_check_expire(x); - if (err) - goto out; - - if (x->props.mode) { - switch (family) { - case AF_INET: - err = xfrm4_tunnel_check_size(skb); - break; - - case AF_INET6: - err = xfrm6_tunnel_check_size(skb); - break; - - default: - err = -EINVAL; - } - - if (err) - goto out; - } - - err = xfrm_state_check_space(x, skb); -out: - return err; -} diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 44cb5240fa8f..160bb617d7eb 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -531,6 +531,16 @@ int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) return 0; } +int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb) +{ + int err = xfrm_state_check_expire(x); + if (err < 0) + goto err; + err = xfrm_state_check_space(x, skb); +err: + return err; +} + struct xfrm_state * xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) diff --git a/scripts/Makefile b/scripts/Makefile index 8de642c6e8b6..4931b3e361e2 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -13,7 +13,7 @@ modpost-objs := modpost.o file2alias.o sumversion.o subdir-$(CONFIG_MODVERSIONS) += genksyms # Let clean descend into subdirs -subdir- += basic lxdialog kconfig +subdir- += basic lxdialog kconfig package # dependencies on generated files need to be listed explicitly diff --git a/scripts/package/Makefile b/scripts/package/Makefile new file mode 100644 index 000000000000..f3df4bc950dc --- /dev/null +++ b/scripts/package/Makefile @@ -0,0 +1,71 @@ +# Makefile for the different targets used to generate full packages of a kernel +# It uses the generic clean infrastructure of kbuild + +# Ignore the following files/directories during tar operation +TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS + + +# RPM target +# --------------------------------------------------------------------------- +# The rpm target generates two rpm files: +# /usr/src/packages/SRPMS/kernel-2.6.7rc2-1.src.rpm +# /usr/src/packages/RPMS/i386/kernel-2.6.7rc2-1.<arch>.rpm +# The src.rpm files includes all source for the kernel being built +# The <arch>.rpm includes kernel configuration, modules etc. +# +# Process to create the rpm files +# a) clean the kernel +# b) Generate .spec file +# c) Build a tar ball, using symlink to make kernel version +# first entry in the path +# d) and pack the result to a tar.gz file +# e) generate the rpm files, based on kernel.spec +# - Use /. to avoid tar packing just the symlink + +# Do we have rpmbuild, otherwise fall back to the older rpm +RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \ + else echo rpm; fi) + +# Remove hyphens since they have special meaning in RPM filenames +KERNELPATH := kernel-$(subst -,,$(KERNELRELEASE)) +MKSPEC := $(srctree)/scripts/package/mkspec +PREV := set -e; cd ..; + +.PHONY: rpm-pkg rpm + +$(objtree)/kernel.spec: $(MKSPEC) + $(CONFIG_SHELL) $(MKSPEC) > $@ + +rpm-pkg rpm: $(objtree)/kernel.spec + $(MAKE) clean + $(PREV) ln -sf $(srctree) $(KERNELPATH) + $(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. + $(PREV) rm $(KERNELPATH) + + set -e; \ + $(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version + set -e; \ + mv -f $(objtree)/.tmp_version $(objtree)/.version + + $(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz + rm ../$(KERNELPATH).tar.gz + +clean-rule += rm -f $(objtree)/kernel.spec + +# Deb target +# --------------------------------------------------------------------------- +# +.PHONY: deb-pkg +deb-pkg: + $(MAKE) + $(CONFIG_SHELL) $(srctree)/scripts/package/builddeb + +clean-rule += && rm -rf $(objtree)/debian/ + + +# Help text displayed when executing 'make help' +# --------------------------------------------------------------------------- +help: + @echo ' rpm-pkg - Build the kernel as an RPM package' + @echo ' deb-pkg - Build the kernel as an deb package' + diff --git a/scripts/package/builddeb b/scripts/package/builddeb new file mode 100644 index 000000000000..968a0a77da95 --- /dev/null +++ b/scripts/package/builddeb @@ -0,0 +1,79 @@ +#!/bin/sh +# +# builddeb 1.2 +# Copyright 2003 Wichert Akkerman <wichert@wiggy.net> +# +# Simple script to generate a deb package for a Linux kernel. All the +# complexity of what to do with a kernel after it is installer or removed +# is left to other scripts and packages: they can install scripts in the +# /etc/kernel/{pre,post}{inst,rm}.d/ directories that will be called on +# package install and removal. + +set -e + +# Some variables and settings used throughout the script +version="$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION" +tmpdir="$objtree/debian/tmp" + +# Setup the directory structure +rm -rf "$tmpdir" +mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot" + +# Build and install the kernel +cp System.map "$tmpdir/boot/System.map-$version" +cp .config "$tmpdir/boot/config-$version" +cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version" + +if grep -q '^CONFIG_MODULES=y' .config ; then + INSTALL_MOD_PATH="$tmpdir" make modules_install +fi + +# Install the maintainer scripts +for script in postinst postrm preinst prerm ; do + mkdir -p "$tmpdir/etc/kernel/$script.d" + cat <<EOF > "$tmpdir/DEBIAN/$script" +#!/bin/sh + +set -e + +test -d /etc/kernel/$script.d && run-parts --arg="$version" /etc/kernel/$script.d +exit 0 +EOF + chmod 755 "$tmpdir/DEBIAN/$script" +done + +name="Kernel Compiler <$(id -nu)@$(hostname -f)>" +# Generate a simple changelog template +cat <<EOF > debian/changelog +linux ($version) unstable; urgency=low + + * A standard release + + -- $name $(date -R) +EOF + +# Generate a control file +cat <<EOF > debian/control +Source: linux +Section: base +Priority: optional +Maintainer: $name +Standards-Version: 3.6.1 + +Package: linux-$version +Architecture: any +Description: Linux kernel, version $version + This package contains the Linux kernel, modules and corresponding other + files version $version. +EOF + +# Fix some ownership and permissions +chown -R root:root "$tmpdir" +chmod -R go-w "$tmpdir" + +# Perform the final magic +dpkg-gencontrol -isp +dpkg --build "$tmpdir" .. + +exit 0 + diff --git a/scripts/mkspec b/scripts/package/mkspec index e64429666a89..3ecfc23e0921 100755 --- a/scripts/mkspec +++ b/scripts/package/mkspec @@ -3,18 +3,12 @@ # Output a simple RPM spec file that uses no fancy features requring # RPM v4. This is intended to work with any RPM distro. # -# The only gothic bit here is redefining install_post to avoid +# The only gothic bit here is redefining install_post to avoid # stripping the symbols from files in the kernel which we want # # Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net> # -# That's the voodoo to see if it's a x86. -ISX86=`echo ${ARCH:=\`arch\`} | grep -ie i.86` -if [ ! -z $ISX86 ]; then - PC=1 -else - PC=0 -fi + # starting to output the spec if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then PROVIDES=kernel-drm @@ -46,19 +40,16 @@ echo "%prep" echo "%setup -q" echo "" echo "%build" -echo "make clean all" +echo "make clean && make" echo "" echo "%install" echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules' + echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install' -# This is the first disagreement between i386 and most others -if [ $PC = 1 ]; then - echo 'cp arch/i386/boot/bzImage $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION" -else - echo 'cp vmlinux $RPM_BUILD_ROOT'"/boot/vmlinux-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION" -fi -# Back on track +echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION" + echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION" + echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION" echo "" echo "%clean" |
