diff options
201 files changed, 2509 insertions, 1765 deletions
diff --git a/Documentation/hw_random.txt b/Documentation/hw_random.txt index bb58c36b5845..690f52550c80 100644 --- a/Documentation/hw_random.txt +++ b/Documentation/hw_random.txt @@ -1,33 +1,26 @@ - Hardware driver for Intel/AMD/VIA Random Number Generators (RNG) - Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> - Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> - Introduction: - The hw_random device driver is software that makes use of a + The hw_random framework is software that makes use of a special hardware feature on your CPU or motherboard, - a Random Number Generator (RNG). + a Random Number Generator (RNG). The software has two parts: + a core providing the /dev/hw_random character device and its + sysfs support, plus a hardware-specific driver that plugs + into that core. - In order to make effective use of this device driver, you + To make the most effective use of these mechanisms, you should download the support software as well. Download the latest version of the "rng-tools" package from the hw_random driver's official Web site: http://sourceforge.net/projects/gkernel/ -About the Intel RNG hardware, from the firmware hub datasheet: - - The Firmware Hub integrates a Random Number Generator (RNG) - using thermal noise generated from inherently random quantum - mechanical properties of silicon. When not generating new random - bits the RNG circuitry will enter a low power state. Intel will - provide a binary software driver to give third party software - access to our RNG for use as a security feature. At this time, - the RNG is only to be used with a system in an OS-present state. + Those tools use /dev/hw_random to fill the kernel entropy pool, + which is used internally and exported by the /dev/urandom and + /dev/random special files. Theory of operation: - Character driver. Using the standard open() + CHARACTER DEVICE. Using the standard open() and read() system calls, you can read random data from the hardware RNG device. This data is NOT CHECKED by any fitness tests, and could potentially be bogus (if the @@ -36,9 +29,37 @@ Theory of operation: a security-conscious person would run fitness tests on the data before assuming it is truly random. - /dev/hwrandom is char device major 10, minor 183. + The rng-tools package uses such tests in "rngd", and lets you + run them by hand with a "rngtest" utility. + + /dev/hw_random is char device major 10, minor 183. + + CLASS DEVICE. There is a /sys/class/misc/hw_random node with + two unique attributes, "rng_available" and "rng_current". The + "rng_available" attribute lists the hardware-specific drivers + available, while "rng_current" lists the one which is currently + connected to /dev/hw_random. If your system has more than one + RNG available, you may change the one used by writing a name from + the list in "rng_available" into "rng_current". + +========================================================================== + + Hardware driver for Intel/AMD/VIA Random Number Generators (RNG) + Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> + Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> + + +About the Intel RNG hardware, from the firmware hub datasheet: + + The Firmware Hub integrates a Random Number Generator (RNG) + using thermal noise generated from inherently random quantum + mechanical properties of silicon. When not generating new random + bits the RNG circuitry will enter a low power state. Intel will + provide a binary software driver to give third party software + access to our RNG for use as a security feature. At this time, + the RNG is only to be used with a system in an OS-present state. -Driver notes: +Intel RNG Driver notes: * FIXME: support poll(2) diff --git a/Documentation/i386/IO-APIC.txt b/Documentation/i386/IO-APIC.txt index f95166645d29..30b4c714fbe1 100644 --- a/Documentation/i386/IO-APIC.txt +++ b/Documentation/i386/IO-APIC.txt @@ -70,7 +70,7 @@ Every PCI card emits a PCI IRQ, which can be INTA, INTB, INTC or INTD: These INTA-D PCI IRQs are always 'local to the card', their real meaning depends on which slot they are in. If you look at the daisy chaining diagram, -a card in slot4, issuing INTA IRQ, it will end up as a signal on PIRQ2 of +a card in slot4, issuing INTA IRQ, it will end up as a signal on PIRQ4 of the PCI chipset. Most cards issue INTA, this creates optimal distribution between the PIRQ lines. (distributing IRQ sources properly is not a necessity, PCI IRQs can be shared at will, but it's a good for performance diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 650b0d8aa89b..508e2a2c9864 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1130,6 +1130,10 @@ and is between 256 and 4096 characters. It is defined in the file memmap=nn[KMG]$ss[KMG] [KNL,ACPI] Mark specific memory as reserved. Region of memory to be used, from ss to ss+nn. + Example: Exclude memory from 0x18690000-0x1869ffff + memmap=64K$0x18690000 + or + memmap=0x10000$0x18690000 meye.*= [HW] Set MotionEye Camera parameters See Documentation/video4linux/meye.txt. diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index bec5a32e4095..4c1fc65a8b3d 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c @@ -1,7 +1,7 @@ /*P:100 This is the Launcher code, a simple program which lays out the - * "physical" memory for the new Guest by mapping the kernel image and the - * virtual devices, then reads repeatedly from /dev/lguest to run the Guest. -:*/ + * "physical" memory for the new Guest by mapping the kernel image and + * the virtual devices, then opens /dev/lguest to tell the kernel + * about the Guest and control it. :*/ #define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include <stdio.h> @@ -43,7 +43,7 @@ #include "linux/virtio_console.h" #include "linux/virtio_ring.h" #include "asm-x86/bootparam.h" -/*L:110 We can ignore the 38 include files we need for this program, but I do +/*L:110 We can ignore the 39 include files we need for this program, but I do * want to draw attention to the use of kernel-style types. * * As Linus said, "C is a Spartan language, and so should your naming be." I @@ -320,7 +320,7 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr) err(1, "Reading program headers"); /* Try all the headers: there are usually only three. A read-only one, - * a read-write one, and a "note" section which isn't loadable. */ + * a read-write one, and a "note" section which we don't load. */ for (i = 0; i < ehdr->e_phnum; i++) { /* If this isn't a loadable segment, we ignore it */ if (phdr[i].p_type != PT_LOAD) @@ -387,7 +387,7 @@ static unsigned long load_kernel(int fd) if (memcmp(hdr.e_ident, ELFMAG, SELFMAG) == 0) return map_elf(fd, &hdr); - /* Otherwise we assume it's a bzImage, and try to unpack it */ + /* Otherwise we assume it's a bzImage, and try to load it. */ return load_bzimage(fd); } @@ -433,12 +433,12 @@ static unsigned long load_initrd(const char *name, unsigned long mem) return len; } -/* Once we know how much memory we have, we can construct simple linear page +/* Once we know how much memory we have we can construct simple linear page * tables which set virtual == physical which will get the Guest far enough * into the boot to create its own. * * We lay them out of the way, just below the initrd (which is why we need to - * know its size). */ + * know its size here). */ static unsigned long setup_pagetables(unsigned long mem, unsigned long initrd_size) { @@ -850,7 +850,8 @@ static void handle_console_output(int fd, struct virtqueue *vq) * * Handling output for network is also simple: we get all the output buffers * and write them (ignoring the first element) to this device's file descriptor - * (stdout). */ + * (/dev/net/tun). + */ static void handle_net_output(int fd, struct virtqueue *vq) { unsigned int head, out, in; @@ -924,7 +925,7 @@ static void enable_fd(int fd, struct virtqueue *vq) write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd)); } -/* Resetting a device is fairly easy. */ +/* When the Guest asks us to reset a device, it's is fairly easy. */ static void reset_device(struct device *dev) { struct virtqueue *vq; @@ -1003,8 +1004,8 @@ static void handle_input(int fd) if (select(devices.max_infd+1, &fds, NULL, NULL, &poll) == 0) break; - /* Otherwise, call the device(s) which have readable - * file descriptors and a method of handling them. */ + /* Otherwise, call the device(s) which have readable file + * descriptors and a method of handling them. */ for (i = devices.dev; i; i = i->next) { if (i->handle_input && FD_ISSET(i->fd, &fds)) { int dev_fd; @@ -1015,8 +1016,7 @@ static void handle_input(int fd) * should no longer service it. Networking and * console do this when there's no input * buffers to deliver into. Console also uses - * it when it discovers that stdin is - * closed. */ + * it when it discovers that stdin is closed. */ FD_CLR(i->fd, &devices.infds); /* Tell waker to ignore it too, by sending a * negative fd number (-1, since 0 is a valid @@ -1033,7 +1033,8 @@ static void handle_input(int fd) * * All devices need a descriptor so the Guest knows it exists, and a "struct * device" so the Launcher can keep track of it. We have common helper - * routines to allocate and manage them. */ + * routines to allocate and manage them. + */ /* The layout of the device page is a "struct lguest_device_desc" followed by a * number of virtqueue descriptors, then two sets of feature bits, then an @@ -1078,7 +1079,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, struct virtqueue **i, *vq = malloc(sizeof(*vq)); void *p; - /* First we need some pages for this virtqueue. */ + /* First we need some memory for this virtqueue. */ pages = (vring_size(num_descs, getpagesize()) + getpagesize() - 1) / getpagesize(); p = get_pages(pages); @@ -1122,7 +1123,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, } /* The first half of the feature bitmask is for us to advertise features. The - * second half if for the Guest to accept features. */ + * second half is for the Guest to accept features. */ static void add_feature(struct device *dev, unsigned bit) { u8 *features = get_feature_bits(dev); @@ -1151,7 +1152,9 @@ static void set_config(struct device *dev, unsigned len, const void *conf) } /* This routine does all the creation and setup of a new device, including - * calling new_dev_desc() to allocate the descriptor and device memory. */ + * calling new_dev_desc() to allocate the descriptor and device memory. + * + * See what I mean about userspace being boring? */ static struct device *new_device(const char *name, u16 type, int fd, bool (*handle_input)(int, struct device *)) { @@ -1383,7 +1386,6 @@ struct vblk_info * Launcher triggers interrupt to Guest. */ int done_fd; }; -/*:*/ /*L:210 * The Disk @@ -1493,7 +1495,10 @@ static int io_thread(void *_dev) while (read(vblk->workpipe[0], &c, 1) == 1) { /* We acknowledge each request immediately to reduce latency, * rather than waiting until we've done them all. I haven't - * measured to see if it makes any difference. */ + * measured to see if it makes any difference. + * + * That would be an interesting test, wouldn't it? You could + * also try having more than one I/O thread. */ while (service_io(dev)) write(vblk->done_fd, &c, 1); } @@ -1501,7 +1506,7 @@ static int io_thread(void *_dev) } /* Now we've seen the I/O thread, we return to the Launcher to see what happens - * when the thread tells us it's completed some I/O. */ + * when that thread tells us it's completed some I/O. */ static bool handle_io_finish(int fd, struct device *dev) { char c; @@ -1573,11 +1578,12 @@ static void setup_block_file(const char *filename) * more work. */ pipe(vblk->workpipe); - /* Create stack for thread and run it */ + /* Create stack for thread and run it. Since stack grows upwards, we + * point the stack pointer to the end of this region. */ stack = malloc(32768); /* SIGCHLD - We dont "wait" for our cloned thread, so prevent it from * becoming a zombie. */ - if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1) + if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1) err(1, "Creating clone"); /* We don't need to keep the I/O thread's end of the pipes open. */ @@ -1587,14 +1593,14 @@ static void setup_block_file(const char *filename) verbose("device %u: virtblock %llu sectors\n", devices.device_num, le64_to_cpu(conf.capacity)); } -/* That's the end of device setup. :*/ +/* That's the end of device setup. */ -/* Reboot */ +/*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */ static void __attribute__((noreturn)) restart_guest(void) { unsigned int i; - /* Closing pipes causes the waker thread and io_threads to die, and + /* Closing pipes causes the Waker thread and io_threads to die, and * closing /dev/lguest cleans up the Guest. Since we don't track all * open fds, we simply close everything beyond stderr. */ for (i = 3; i < FD_SETSIZE; i++) @@ -1603,7 +1609,7 @@ static void __attribute__((noreturn)) restart_guest(void) err(1, "Could not exec %s", main_args[0]); } -/*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves +/*L:220 Finally we reach the core of the Launcher which runs the Guest, serves * its input and output, and finally, lays it to rest. */ static void __attribute__((noreturn)) run_guest(int lguest_fd) { @@ -1644,7 +1650,7 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd) err(1, "Resetting break"); } } -/* +/*L:240 * This is the end of the Launcher. The good news: we are over halfway * through! The bad news: the most fiendish part of the code still lies ahead * of us. @@ -1691,8 +1697,8 @@ int main(int argc, char *argv[]) * device receive input from a file descriptor, we keep an fdset * (infds) and the maximum fd number (max_infd) with the head of the * list. We also keep a pointer to the last device. Finally, we keep - * the next interrupt number to hand out (1: remember that 0 is used by - * the timer). */ + * the next interrupt number to use for devices (1: remember that 0 is + * used by the timer). */ FD_ZERO(&devices.infds); devices.max_infd = -1; devices.lastdev = NULL; @@ -1793,8 +1799,8 @@ int main(int argc, char *argv[]) lguest_fd = tell_kernel(pgdir, start); /* We fork off a child process, which wakes the Launcher whenever one - * of the input file descriptors needs attention. Otherwise we would - * run the Guest until it tries to output something. */ + * of the input file descriptors needs attention. We call this the + * Waker, and we'll cover it in a moment. */ waker_fd = setup_waker(lguest_fd); /* Finally, run the Guest. This doesn't return. */ diff --git a/Documentation/lguest/lguest.txt b/Documentation/lguest/lguest.txt index 722d4e7fbebe..29510dc51510 100644 --- a/Documentation/lguest/lguest.txt +++ b/Documentation/lguest/lguest.txt @@ -1,6 +1,7 @@ -Rusty's Remarkably Unreliable Guide to Lguest - - or, A Young Coder's Illustrated Hypervisor -http://lguest.ozlabs.org + __ + (___()'`; Rusty's Remarkably Unreliable Guide to Lguest + /, /` - or, A Young Coder's Illustrated Hypervisor + \\"--\\ http://lguest.ozlabs.org Lguest is designed to be a minimal hypervisor for the Linux kernel, for Linux developers and users to experiment with virtualization with the @@ -41,12 +42,16 @@ Running Lguest: CONFIG_PHYSICAL_ALIGN=0x100000) "Device Drivers": + "Block devices" + "Virtio block driver (EXPERIMENTAL)" = M/Y "Network device support" "Universal TUN/TAP device driver support" = M/Y - (CONFIG_TUN=m) - "Virtualization" - "Linux hypervisor example code" = M/Y - (CONFIG_LGUEST=m) + "Virtio network driver (EXPERIMENTAL)" = M/Y + (CONFIG_VIRTIO_BLK=m, CONFIG_VIRTIO_NET=m and CONFIG_TUN=m) + + "Virtualization" + "Linux hypervisor example code" = M/Y + (CONFIG_LGUEST=m) - A tool called "lguest" is available in this directory: type "make" to build it. If you didn't build your kernel in-tree, use "make diff --git a/Documentation/nmi_watchdog.txt b/Documentation/nmi_watchdog.txt index c025a4561c10..757c729ee42e 100644 --- a/Documentation/nmi_watchdog.txt +++ b/Documentation/nmi_watchdog.txt @@ -23,8 +23,7 @@ kernel debugging options, such as Kernel Stack Meter or Kernel Tracer, may implicitly disable the NMI watchdog.] For x86-64, the needed APIC is always compiled in, and the NMI watchdog is -always enabled with I/O-APIC mode (nmi_watchdog=1). Currently, local APIC -mode (nmi_watchdog=2) does not work on x86-64. +always enabled with I/O-APIC mode (nmi_watchdog=1). Using local APIC (nmi_watchdog=2) needs the first performance register, so you can't use it for other purposes (such as high precision performance diff --git a/MAINTAINERS b/MAINTAINERS index 73883b8bbd76..f1ed75cef6a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2110,7 +2110,7 @@ M: reinette.chatre@intel.com L: linux-wireless@vger.kernel.org L: ipw3945-devel@lists.sourceforge.net W: http://intellinuxwireless.org -T: git git://intellinuxwireless.org/repos/iwlwifi +T: git git://git.kernel.org/pub/scm/linux/kernel/git/rchatre/iwlwifi-2.6.git S: Supported IOC3 ETHERNET DRIVER @@ -2322,6 +2322,8 @@ P: Anil S Keshavamurthy M: anil.s.keshavamurthy@intel.com P: David S. Miller M: davem@davemloft.net +P: Masami Hiramatsu +M: mhiramat@redhat.com L: linux-kernel@vger.kernel.org S: Maintained @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 25 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Funky Weasel is Jiggy wit it # *DOCUMENTATION* @@ -189,7 +189,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ # Alternatively CROSS_COMPILE can be set in the environment. # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile - +export KBUILD_BUILDHOST := $(SUBARCH) ARCH ?= $(SUBARCH) CROSS_COMPILE ?= diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index e66a07a928cd..2687b730e2d0 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c @@ -163,6 +163,7 @@ add_reserved_region(resource_size_t start, resource_size_t end, new->start = start; new->end = end; new->name = name; + new->sibling = next; new->flags = IORESOURCE_MEM; *pprev = new; diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index cf6f686d9b0b..b835c4c01368 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -178,6 +178,7 @@ static int do_cop_absent(u32 insn) return 0; } +#ifdef CONFIG_BUG int is_valid_bugaddr(unsigned long pc) { unsigned short opcode; @@ -189,6 +190,7 @@ int is_valid_bugaddr(unsigned long pc) return opcode == AVR32_BUG_OPCODE; } +#endif asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs) { @@ -197,6 +199,7 @@ asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs) void __user *pc; long code; +#ifdef CONFIG_BUG if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) { enum bug_trap_type type; @@ -211,6 +214,7 @@ asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs) die("Kernel BUG", regs, SIGKILL); } } +#endif local_irq_enable(); diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 250958d1e3cb..9d4bd2229493 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.25-rc1 -# Sun Feb 17 22:44:12 2008 +# Linux kernel version: 2.6.25-rc3 +# Wed Mar 26 04:33:35 2008 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -55,9 +55,11 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=18 # CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set +CONFIG_RT_GROUP_SCHED=y +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y CONFIG_NAMESPACES=y @@ -482,6 +484,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_MVSAS is not set # CONFIG_SCSI_STEX is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_QLOGIC_1280 is not set @@ -810,6 +813,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set # CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c index dd5d28e3d798..0097c08dc600 100644 --- a/arch/sparc64/kernel/cpu.c +++ b/arch/sparc64/kernel/cpu.c @@ -15,6 +15,8 @@ #include <asm/spitfire.h> #include <asm/oplib.h> +#include "entry.h" + DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; struct cpu_iu_info { @@ -65,8 +67,6 @@ static struct cpu_iu_info linux_sparc_chips[] = { char *sparc_cpu_type; char *sparc_fpu_type; -unsigned int fsr_storage; - static void __init sun4v_cpu_probe(void) { switch (sun4v_chip_type) { @@ -94,8 +94,10 @@ void __init cpu_probe(void) unsigned long ver, fpu_vers, manuf, impl, fprs; int i; - if (tlb_type == hypervisor) - return sun4v_cpu_probe(); + if (tlb_type == hypervisor) { + sun4v_cpu_probe(); + return; + } fprs = fprs_read(); fprs_write(FPRS_FEF); diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 6be4d2d2904e..49eca4b1cf25 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1705,6 +1705,36 @@ __flushw_user: 2: retl nop + /* Flush %fp and %i7 to the stack for all register + * windows active inside of the cpu. This allows + * show_stack_trace() to avoid using an expensive + * 'flushw'. + */ + .globl stack_trace_flush + .type stack_trace_flush,#function +stack_trace_flush: + rdpr %pstate, %o0 + wrpr %o0, PSTATE_IE, %pstate + + rdpr %cwp, %g1 + rdpr %canrestore, %g2 + sub %g1, 1, %g3 + +1: brz,pn %g2, 2f + sub %g2, 1, %g2 + wrpr %g3, %cwp + stx %fp, [%sp + STACK_BIAS + RW_V9_I6] + stx %i7, [%sp + STACK_BIAS + RW_V9_I7] + ba,pt %xcc, 1b + sub %g3, 1, %g3 + +2: wrpr %g1, %cwp + wrpr %o0, %pstate + + retl + nop + .size stack_trace_flush,.-stack_trace_flush + #ifdef CONFIG_SMP .globl hard_smp_processor_id hard_smp_processor_id: diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h new file mode 100644 index 000000000000..4a91e9c6d31b --- /dev/null +++ b/arch/sparc64/kernel/entry.h @@ -0,0 +1,196 @@ +#ifndef _ENTRY_H +#define _ENTRY_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> + +extern char *sparc_cpu_type; +extern char *sparc_fpu_type; + +extern void __init per_cpu_patch(void); +extern void __init sun4v_patch(void); +extern void __init boot_cpu_id_too_large(int cpu); +extern unsigned int dcache_parity_tl1_occurred; +extern unsigned int icache_parity_tl1_occurred; + +extern asmlinkage void update_perfctrs(void); +extern asmlinkage void sparc_breakpoint(struct pt_regs *regs); +extern void timer_interrupt(int irq, struct pt_regs *regs); + +extern void do_notify_resume(struct pt_regs *regs, + unsigned long orig_i0, + int restart_syscall, + unsigned long thread_info_flags); + +extern asmlinkage void syscall_trace(struct pt_regs *regs, + int syscall_exit_p); + +extern void bad_trap_tl1(struct pt_regs *regs, long lvl); + +extern void do_fpe_common(struct pt_regs *regs); +extern void do_fpieee(struct pt_regs *regs); +extern void do_fpother(struct pt_regs *regs); +extern void do_tof(struct pt_regs *regs); +extern void do_div0(struct pt_regs *regs); +extern void do_illegal_instruction(struct pt_regs *regs); +extern void mem_address_unaligned(struct pt_regs *regs, + unsigned long sfar, + unsigned long sfsr); +extern void sun4v_do_mna(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void do_privop(struct pt_regs *regs); +extern void do_privact(struct pt_regs *regs); +extern void do_cee(struct pt_regs *regs); +extern void do_cee_tl1(struct pt_regs *regs); +extern void do_dae_tl1(struct pt_regs *regs); +extern void do_iae_tl1(struct pt_regs *regs); +extern void do_div0_tl1(struct pt_regs *regs); +extern void do_fpdis_tl1(struct pt_regs *regs); +extern void do_fpieee_tl1(struct pt_regs *regs); +extern void do_fpother_tl1(struct pt_regs *regs); +extern void do_ill_tl1(struct pt_regs *regs); +extern void do_irq_tl1(struct pt_regs *regs); +extern void do_lddfmna_tl1(struct pt_regs *regs); +extern void do_stdfmna_tl1(struct pt_regs *regs); +extern void do_paw(struct pt_regs *regs); +extern void do_paw_tl1(struct pt_regs *regs); +extern void do_vaw(struct pt_regs *regs); +extern void do_vaw_tl1(struct pt_regs *regs); +extern void do_tof_tl1(struct pt_regs *regs); +extern void do_getpsr(struct pt_regs *regs); + +extern void spitfire_insn_access_exception(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_insn_access_exception_tl1(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_data_access_exception(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_data_access_exception_tl1(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_access_error(struct pt_regs *regs, + unsigned long status_encoded, + unsigned long afar); + +extern void cheetah_fecc_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_cee_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_deferred_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_plus_parity_error(int type, struct pt_regs *regs); + +extern void sun4v_insn_access_exception(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_insn_access_exception_tl1(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_data_access_exception(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_data_access_exception_tl1(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_resum_error(struct pt_regs *regs, + unsigned long offset); +extern void sun4v_resum_overflow(struct pt_regs *regs); +extern void sun4v_nonresum_error(struct pt_regs *regs, + unsigned long offset); +extern void sun4v_nonresum_overflow(struct pt_regs *regs); + +extern unsigned long sun4v_err_itlb_vaddr; +extern unsigned long sun4v_err_itlb_ctx; +extern unsigned long sun4v_err_itlb_pte; +extern unsigned long sun4v_err_itlb_error; + +extern void sun4v_itlb_error_report(struct pt_regs *regs, int tl); + +extern unsigned long sun4v_err_dtlb_vaddr; +extern unsigned long sun4v_err_dtlb_ctx; +extern unsigned long sun4v_err_dtlb_pte; +extern unsigned long sun4v_err_dtlb_error; + +extern void sun4v_dtlb_error_report(struct pt_regs *regs, int tl); +extern void hypervisor_tlbop_error(unsigned long err, + unsigned long op); +extern void hypervisor_tlbop_error_xcall(unsigned long err, + unsigned long op); + +/* WARNING: The error trap handlers in assembly know the precise + * layout of the following structure. + * + * C-level handlers in traps.c use this information to log the + * error and then determine how to recover (if possible). + */ +struct cheetah_err_info { +/*0x00*/u64 afsr; +/*0x08*/u64 afar; + + /* D-cache state */ +/*0x10*/u64 dcache_data[4]; /* The actual data */ +/*0x30*/u64 dcache_index; /* D-cache index */ +/*0x38*/u64 dcache_tag; /* D-cache tag/valid */ +/*0x40*/u64 dcache_utag; /* D-cache microtag */ +/*0x48*/u64 dcache_stag; /* D-cache snooptag */ + + /* I-cache state */ +/*0x50*/u64 icache_data[8]; /* The actual insns + predecode */ +/*0x90*/u64 icache_index; /* I-cache index */ +/*0x98*/u64 icache_tag; /* I-cache phys tag */ +/*0xa0*/u64 icache_utag; /* I-cache microtag */ +/*0xa8*/u64 icache_stag; /* I-cache snooptag */ +/*0xb0*/u64 icache_upper; /* I-cache upper-tag */ +/*0xb8*/u64 icache_lower; /* I-cache lower-tag */ + + /* E-cache state */ +/*0xc0*/u64 ecache_data[4]; /* 32 bytes from staging registers */ +/*0xe0*/u64 ecache_index; /* E-cache index */ +/*0xe8*/u64 ecache_tag; /* E-cache tag/state */ + +/*0xf0*/u64 __pad[32 - 30]; +}; +#define CHAFSR_INVALID ((u64)-1L) + +/* This is allocated at boot time based upon the largest hardware + * cpu ID in the system. We allocate two entries per cpu, one for + * TL==0 logging and one for TL >= 1 logging. + */ +extern struct cheetah_err_info *cheetah_error_log; + +/* UPA nodes send interrupt packet to UltraSparc with first data reg + * value low 5 (7 on Starfire) bits holding the IRQ identifier being + * delivered. We must translate this into a non-vector IRQ so we can + * set the softint on this cpu. + * + * To make processing these packets efficient and race free we use + * an array of irq buckets below. The interrupt vector handler in + * entry.S feeds incoming packets into per-cpu pil-indexed lists. + * + * If you make changes to ino_bucket, please update hand coded assembler + * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S + */ +struct ino_bucket { +/*0x00*/unsigned long __irq_chain_pa; + + /* Virtual interrupt number assigned to this INO. */ +/*0x08*/unsigned int __virt_irq; +/*0x0c*/unsigned int __pad; +}; + +extern struct ino_bucket *ivector_table; +extern unsigned long ivector_table_pa; + +extern void handler_irq(int irq, struct pt_regs *regs); +extern void init_irqwork_curcpu(void); +extern void __cpuinit sun4v_register_mondo_queues(int this_cpu); + +#endif /* _ENTRY_H */ diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index fbaab3497bfd..b781d3d54fb8 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc64/kernel/iommu.c @@ -626,7 +626,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, iommu_map_failed: for_each_sg(sglist, s, nelems, i) { if (s->dma_length != 0) { - unsigned long vaddr, npages, entry, i; + unsigned long vaddr, npages, entry, j; iopte_t *base; vaddr = s->dma_address & IO_PAGE_MASK; @@ -637,8 +637,8 @@ iommu_map_failed: >> IO_PAGE_SHIFT; base = iommu->page_table + entry; - for (i = 0; i < npages; i++) - iopte_make_dummy(iommu, base + i); + for (j = 0; j < npages; j++) + iopte_make_dummy(iommu, base + j); s->dma_address = DMA_ERROR_CODE; s->dma_length = 0; @@ -803,7 +803,7 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev, spin_unlock_irqrestore(&iommu->lock, flags); } -const struct dma_ops sun4u_dma_ops = { +static const struct dma_ops sun4u_dma_ops = { .alloc_coherent = dma_4u_alloc_coherent, .free_coherent = dma_4u_free_coherent, .map_single = dma_4u_map_single, diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 5ec06c8c7fea..eb88bd6e674e 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -44,27 +44,10 @@ #include <asm/hypervisor.h> #include <asm/cacheflush.h> -/* UPA nodes send interrupt packet to UltraSparc with first data reg - * value low 5 (7 on Starfire) bits holding the IRQ identifier being - * delivered. We must translate this into a non-vector IRQ so we can - * set the softint on this cpu. - * - * To make processing these packets efficient and race free we use - * an array of irq buckets below. The interrupt vector handler in - * entry.S feeds incoming packets into per-cpu pil-indexed lists. - * - * If you make changes to ino_bucket, please update hand coded assembler - * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S - */ -struct ino_bucket { -/*0x00*/unsigned long __irq_chain_pa; - - /* Virtual interrupt number assigned to this INO. */ -/*0x08*/unsigned int __virt_irq; -/*0x0c*/unsigned int __pad; -}; +#include "entry.h" #define NUM_IVECS (IMAP_INR + 1) + struct ino_bucket *ivector_table; unsigned long ivector_table_pa; diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 9a1ba1fe859d..aaae865e7932 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -35,6 +35,9 @@ #include <asm/spitfire.h> #include <asm/page.h> #include <asm/cpudata.h> +#include <asm/cacheflush.h> + +#include "entry.h" /* #define ALLOW_INIT_TRACING */ @@ -67,6 +70,8 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, if (tlb_type == hypervisor) return; + preempt_disable(); + #ifdef DCACHE_ALIASING_POSSIBLE /* If bit 13 of the kernel address we used to access the * user page is the same as the virtual address that page @@ -105,6 +110,8 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, for (; start < end; start += icache_line_size) flushi(start); } + + preempt_enable(); } enum sparc_regset { @@ -382,6 +389,7 @@ static const struct user_regset_view user_sparc64_view = { .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets) }; +#ifdef CONFIG_COMPAT static int genregs32_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, @@ -676,14 +684,18 @@ static const struct user_regset_view user_sparc32_view = { .name = "sparc", .e_machine = EM_SPARC, .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets) }; +#endif /* CONFIG_COMPAT */ const struct user_regset_view *task_user_regset_view(struct task_struct *task) { +#ifdef CONFIG_COMPAT if (test_tsk_thread_flag(task, TIF_32BIT)) return &user_sparc32_view; +#endif return &user_sparc64_view; } +#ifdef CONFIG_COMPAT struct compat_fps { unsigned int regs[32]; unsigned int fsr; @@ -798,6 +810,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, return ret; } +#endif /* CONFIG_COMPAT */ struct fps { unsigned int regs[64]; @@ -807,11 +820,14 @@ struct fps { long arch_ptrace(struct task_struct *child, long request, long addr, long data) { const struct user_regset_view *view = task_user_regset_view(child); - struct pt_regs __user *pregs = (struct pt_regs __user *) addr; unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; - struct fps __user *fps = (struct fps __user *) addr; + struct pt_regs __user *pregs; + struct fps __user *fps; int ret; + pregs = (struct pt_regs __user *) (unsigned long) addr; + fps = (struct fps __user *) (unsigned long) addr; + switch (request) { case PTRACE_PEEKUSR: ret = (addr != 0) ? -EIO : 0; diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index d036dbe72864..6acb4c51cfe4 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -51,6 +51,8 @@ #include <net/ipconfig.h> #endif +#include "entry.h" + /* Used to synchronize accesses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h */ @@ -335,9 +337,6 @@ void __init setup_arch(char **cmdline_p) /* BUFFER is PAGE_SIZE bytes long. */ -extern char *sparc_cpu_type; -extern char *sparc_fpu_type; - extern void smp_info(struct seq_file *); extern void smp_bogo(struct seq_file *); extern void mmu_info(struct seq_file *); diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index fb13775b3682..94a9d64208ee 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -32,6 +32,9 @@ #include <asm/siginfo.h> #include <asm/visasm.h> +#include "entry.h" +#include "systbls.h" + #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) /* {set, get}context() needed for 64-bit SparcLinux userland. */ diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 5a1126b363a4..59f020d69d4c 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -1,6 +1,6 @@ /* smp.c: Sparc64 SMP support. * - * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include <linux/module.h> @@ -30,6 +30,7 @@ #include <asm/cpudata.h> #include <asm/hvtramp.h> #include <asm/io.h> +#include <asm/timer.h> #include <asm/irq.h> #include <asm/irq_regs.h> diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c index 47f92a59be18..84d39e873e88 100644 --- a/arch/sparc64/kernel/stacktrace.c +++ b/arch/sparc64/kernel/stacktrace.c @@ -2,13 +2,15 @@ #include <linux/stacktrace.h> #include <linux/thread_info.h> #include <asm/ptrace.h> +#include <asm/stacktrace.h> void save_stack_trace(struct stack_trace *trace) { unsigned long ksp, fp, thread_base; struct thread_info *tp = task_thread_info(current); - flushw_all(); + stack_trace_flush(); + __asm__ __volatile__( "mov %%fp, %0" : "=r" (ksp) diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 134d801579f9..f952745d0f3d 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -1,5 +1,4 @@ -/* $Id: sys_sparc.c,v 1.57 2002/02/09 19:49:30 davem Exp $ - * linux/arch/sparc64/kernel/sys_sparc.c +/* linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/sparc @@ -30,6 +29,9 @@ #include <asm/perfctr.h> #include <asm/unistd.h> +#include "entry.h" +#include "systbls.h" + /* #define DEBUG_UNIMP_SYSCALL */ asmlinkage unsigned long sys_getpagesize(void) @@ -445,7 +447,8 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, goto out; case SEMTIMEDOP: err = sys_semtimedop(first, ptr, (unsigned)second, - (const struct timespec __user *) fifth); + (const struct timespec __user *) + (unsigned long) fifth); goto out; case SEMGET: err = sys_semget(first, (int)second, (int)third); @@ -788,7 +791,7 @@ asmlinkage long sys_utrap_install(utrap_entry_t type, } else { if ((utrap_handler_t)current_thread_info()->utraps[type] != new_p && current_thread_info()->utraps[0] > 1) { - long *p = current_thread_info()->utraps; + unsigned long *p = current_thread_info()->utraps; current_thread_info()->utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), @@ -816,7 +819,8 @@ asmlinkage long sys_utrap_install(utrap_entry_t type, return 0; } -long sparc_memory_ordering(unsigned long model, struct pt_regs *regs) +asmlinkage long sparc_memory_ordering(unsigned long model, + struct pt_regs *regs) { if (model >= 3) return -EINVAL; diff --git a/arch/sparc64/kernel/systbls.h b/arch/sparc64/kernel/systbls.h new file mode 100644 index 000000000000..8a0d20a35d0c --- /dev/null +++ b/arch/sparc64/kernel/systbls.h @@ -0,0 +1,53 @@ +#ifndef _SYSTBLS_H +#define _SYSTBLS_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/utsname.h> +#include <asm/utrap.h> +#include <asm/signal.h> + +extern asmlinkage unsigned long sys_getpagesize(void); +extern asmlinkage unsigned long sparc_brk(unsigned long brk); +extern asmlinkage long sparc_pipe(struct pt_regs *regs); +extern asmlinkage long sys_ipc(unsigned int call, int first, + unsigned long second, + unsigned long third, + void __user *ptr, long fifth); +extern asmlinkage long sparc64_newuname(struct new_utsname __user *name); +extern asmlinkage long sparc64_personality(unsigned long personality); +extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long off); +extern asmlinkage long sys64_munmap(unsigned long addr, size_t len); +extern asmlinkage unsigned long sys64_mremap(unsigned long addr, + unsigned long old_len, + unsigned long new_len, + unsigned long flags, + unsigned long new_addr); +extern asmlinkage unsigned long c_sys_nis_syscall(struct pt_regs *regs); +extern asmlinkage long sys_getdomainname(char __user *name, int len); +extern asmlinkage long solaris_syscall(struct pt_regs *regs); +extern asmlinkage long sunos_syscall(struct pt_regs *regs); +extern asmlinkage long sys_utrap_install(utrap_entry_t type, + utrap_handler_t new_p, + utrap_handler_t new_d, + utrap_handler_t __user *old_p, + utrap_handler_t __user *old_d); +extern asmlinkage long sparc_memory_ordering(unsigned long model, + struct pt_regs *regs); +extern asmlinkage long sys_rt_sigaction(int sig, + const struct sigaction __user *act, + struct sigaction __user *oact, + void __user *restorer, + size_t sigsetsize); +extern asmlinkage long sys_perfctr(int opcode, unsigned long arg0, + unsigned long arg1, unsigned long arg2); + +extern asmlinkage void sparc64_set_context(struct pt_regs *regs); +extern asmlinkage void sparc64_get_context(struct pt_regs *regs); +extern asmlinkage long sys_sigpause(unsigned int set); +extern asmlinkage long sys_sigsuspend(old_sigset_t set); +extern void do_rt_sigreturn(struct pt_regs *regs); + +#endif /* _SYSTBLS_H */ diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index d204f1ab1d4c..e5d238970c7e 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -1,7 +1,6 @@ -/* $Id: time.c,v 1.42 2002/01/23 14:33:55 davem Exp $ - * time.c: UltraSparc timer and TOD clock support. +/* time.c: UltraSparc timer and TOD clock support. * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * * Based largely on code which is: @@ -48,6 +47,8 @@ #include <asm/uaccess.h> #include <asm/irq_regs.h> +#include "entry.h" + DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); void __iomem *mstk48t02_regs = NULL; @@ -508,6 +509,37 @@ static int __init has_low_battery(void) return (data1 == data2); /* Was the write blocked? */ } +static void __init mostek_set_system_time(void __iomem *mregs) +{ + unsigned int year, mon, day, hour, min, sec; + u8 tmp; + + spin_lock_irq(&mostek_lock); + + /* Traditional Mostek chip. */ + tmp = mostek_read(mregs + MOSTEK_CREG); + tmp |= MSTK_CREG_READ; + mostek_write(mregs + MOSTEK_CREG, tmp); + + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); + + tmp = mostek_read(mregs + MOSTEK_CREG); + tmp &= ~MSTK_CREG_READ; + mostek_write(mregs + MOSTEK_CREG, tmp); + + spin_unlock_irq(&mostek_lock); +} + /* Probe for the real time clock chip. */ static void __init set_system_time(void) { @@ -520,7 +552,6 @@ static void __init set_system_time(void) unsigned long dregs = 0UL; void __iomem *bregs = 0UL; #endif - u8 tmp; if (!mregs && !dregs && !bregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); @@ -528,20 +559,11 @@ static void __init set_system_time(void) } if (mregs) { - spin_lock_irq(&mostek_lock); - - /* Traditional Mostek chip. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); + mostek_set_system_time(mregs); + return; + } - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - } else if (bregs) { + if (bregs) { unsigned char val = readb(bregs + 0x0e); unsigned int century; @@ -596,14 +618,6 @@ static void __init set_system_time(void) xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - - if (mregs) { - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - } } /* davem suggests we keep this within the 4M locked kernel image */ @@ -1027,7 +1041,7 @@ void __init time_init(void) setup_clockevent_multiplier(clock); sparc64_clockevent.max_delta_ns = - clockevent_delta2ns(0x7fffffffffffffff, &sparc64_clockevent); + clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); sparc64_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &sparc64_clockevent); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 007f5317c0de..96da847023f3 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -42,6 +42,7 @@ #endif #include <asm/prom.h> +#include "entry.h" /* When an irrecoverable trap occurs at tl > 0, the trap entry * code logs the trap state registers at every level in the trap @@ -77,11 +78,6 @@ static void dump_tl1_traplog(struct tl1_traplog *p) } } -void do_call_debug(struct pt_regs *regs) -{ - notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); -} - void bad_trap(struct pt_regs *regs, long lvl) { char buffer[32]; @@ -550,41 +546,6 @@ static unsigned long ecache_flush_physbase; static unsigned long ecache_flush_linesize; static unsigned long ecache_flush_size; -/* WARNING: The error trap handlers in assembly know the precise - * layout of the following structure. - * - * C-level handlers below use this information to log the error - * and then determine how to recover (if possible). - */ -struct cheetah_err_info { -/*0x00*/u64 afsr; -/*0x08*/u64 afar; - - /* D-cache state */ -/*0x10*/u64 dcache_data[4]; /* The actual data */ -/*0x30*/u64 dcache_index; /* D-cache index */ -/*0x38*/u64 dcache_tag; /* D-cache tag/valid */ -/*0x40*/u64 dcache_utag; /* D-cache microtag */ -/*0x48*/u64 dcache_stag; /* D-cache snooptag */ - - /* I-cache state */ -/*0x50*/u64 icache_data[8]; /* The actual insns + predecode */ -/*0x90*/u64 icache_index; /* I-cache index */ -/*0x98*/u64 icache_tag; /* I-cache phys tag */ -/*0xa0*/u64 icache_utag; /* I-cache microtag */ -/*0xa8*/u64 icache_stag; /* I-cache snooptag */ -/*0xb0*/u64 icache_upper; /* I-cache upper-tag */ -/*0xb8*/u64 icache_lower; /* I-cache lower-tag */ - - /* E-cache state */ -/*0xc0*/u64 ecache_data[4]; /* 32 bytes from staging registers */ -/*0xe0*/u64 ecache_index; /* E-cache index */ -/*0xe8*/u64 ecache_tag; /* E-cache tag/state */ - -/*0xf0*/u64 __pad[32 - 30]; -}; -#define CHAFSR_INVALID ((u64)-1L) - /* This table is ordered in priority of errors and matches the * AFAR overwrite policy as well. */ @@ -758,10 +719,6 @@ static struct afsr_error_table __jalapeno_error_table[] = { static struct afsr_error_table *cheetah_error_table; static unsigned long cheetah_afsr_errors; -/* This is allocated at boot time based upon the largest hardware - * cpu ID in the system. We allocate two entries per cpu, one for - * TL==0 logging and one for TL >= 1 logging. - */ struct cheetah_err_info *cheetah_error_log; static inline struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr) @@ -2102,7 +2059,7 @@ void do_div0(struct pt_regs *regs) force_sig_info(SIGFPE, &info, current); } -void instruction_dump (unsigned int *pc) +static void instruction_dump(unsigned int *pc) { int i; @@ -2115,7 +2072,7 @@ void instruction_dump (unsigned int *pc) printk("\n"); } -static void user_instruction_dump (unsigned int __user *pc) +static void user_instruction_dump(unsigned int __user *pc) { int i; unsigned int buf[9]; diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 466fd6cffac9..f37078d96407 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -46,6 +46,7 @@ #include <asm/prom.h> #include <asm/sstate.h> #include <asm/mdesc.h> +#include <asm/cpudata.h> #define MAX_PHYS_ADDRESS (1UL << 42UL) #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) @@ -1273,10 +1274,6 @@ void __cpuinit sun4v_ktsb_register(void) /* paging_init() sets up the page tables */ -extern void cheetah_ecache_flush_init(void); -extern void sun4v_patch_tlb_handlers(void); - -extern void cpu_probe(void); extern void central_probe(void); static unsigned long last_valid_pfn; diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c index 3f10fc921b00..a0f000b293de 100644 --- a/arch/sparc64/mm/tlb.c +++ b/arch/sparc64/mm/tlb.c @@ -23,10 +23,11 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; void flush_tlb_pending(void) { - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); + struct mmu_gather *mp; preempt_disable(); + mp = &__get_cpu_var(mmu_gathers); if (mp->tlb_nr) { flush_tsb_user(mp); diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 1e8f41a99511..1d43bdfc20c4 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -256,11 +256,7 @@ static struct net_device_stats *uml_net_get_stats(struct net_device *dev) static void uml_net_set_multicast_list(struct net_device *dev) { - if (dev->flags & IFF_PROMISC) - return; - else if (dev->mc_count) - dev->flags |= IFF_ALLMULTI; - else dev->flags &= ~IFF_ALLMULTI; + return; } static void uml_net_tx_timeout(struct net_device *dev) diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c index f2b5a621d27b..8a85c93bd62a 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c @@ -63,7 +63,7 @@ static struct cpufreq_frequency_table speedstep_freqs[] = { */ static int speedstep_smi_ownership (void) { - u32 command, result, magic; + u32 command, result, magic, dummy; u32 function = GET_SPEEDSTEP_OWNER; unsigned char magic_data[] = "Copyright (c) 1999 Intel Corporation"; @@ -73,8 +73,11 @@ static int speedstep_smi_ownership (void) dprintk("trying to obtain ownership with command %x at port %x\n", command, smi_port); __asm__ __volatile__( + "push %%ebp\n" "out %%al, (%%dx)\n" - : "=D" (result) + "pop %%ebp\n" + : "=D" (result), "=a" (dummy), "=b" (dummy), "=c" (dummy), "=d" (dummy), + "=S" (dummy) : "a" (command), "b" (function), "c" (0), "d" (smi_port), "D" (0), "S" (magic) : "memory" @@ -96,7 +99,7 @@ static int speedstep_smi_ownership (void) */ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) { - u32 command, result = 0, edi, high_mhz, low_mhz; + u32 command, result = 0, edi, high_mhz, low_mhz, dummy; u32 state=0; u32 function = GET_SPEEDSTEP_FREQS; @@ -109,10 +112,12 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) dprintk("trying to determine frequencies with command %x at port %x\n", command, smi_port); - __asm__ __volatile__("movl $0, %%edi\n" + __asm__ __volatile__( + "push %%ebp\n" "out %%al, (%%dx)\n" - : "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi) - : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) + "pop %%ebp" + : "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi), "=S" (dummy) + : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0) ); dprintk("result %x, low_freq %u, high_freq %u\n", result, low_mhz, high_mhz); @@ -135,16 +140,18 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) static int speedstep_get_state (void) { u32 function=GET_SPEEDSTEP_STATE; - u32 result, state, edi, command; + u32 result, state, edi, command, dummy; command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); dprintk("trying to determine current setting with command %x at port %x\n", command, smi_port); - __asm__ __volatile__("movl $0, %%edi\n" + __asm__ __volatile__( + "push %%ebp\n" "out %%al, (%%dx)\n" - : "=a" (result), "=b" (state), "=D" (edi) - : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0) + "pop %%ebp\n" + : "=a" (result), "=b" (state), "=D" (edi), "=c" (dummy), "=d" (dummy), "=S" (dummy) + : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0), "D" (0) ); dprintk("state is %x, result is %x\n", state, result); @@ -160,7 +167,7 @@ static int speedstep_get_state (void) */ static void speedstep_set_state (unsigned int state) { - unsigned int result = 0, command, new_state; + unsigned int result = 0, command, new_state, dummy; unsigned long flags; unsigned int function=SET_SPEEDSTEP_STATE; unsigned int retry = 0; @@ -182,10 +189,12 @@ static void speedstep_set_state (unsigned int state) } retry++; __asm__ __volatile__( - "movl $0, %%edi\n" + "push %%ebp\n" "out %%al, (%%dx)\n" - : "=b" (new_state), "=D" (result) - : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) + "pop %%ebp" + : "=b" (new_state), "=D" (result), "=c" (dummy), "=a" (dummy), + "=d" (dummy), "=S" (dummy) + : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0) ); } while ((new_state != state) && (retry <= SMI_TRIES)); @@ -195,7 +204,7 @@ static void speedstep_set_state (unsigned int state) if (new_state == state) { dprintk("change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result); } else { - printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result); + printk(KERN_ERR "cpufreq: change to state %u failed with new_state %u and result %u\n", state, new_state, result); } return; diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 103d61a59b19..3e18db4cefee 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -176,12 +176,13 @@ static inline void k8_enable_fixed_iorrs(void) } /** - * Checks and updates an fixed-range MTRR if it differs from the value it - * should have. If K8 extentions are wanted, update the K8 SYSCFG MSR also. - * see AMD publication no. 24593, chapter 7.8.1, page 233 for more information - * \param msr MSR address of the MTTR which should be checked and updated - * \param changed pointer which indicates whether the MTRR needed to be changed - * \param msrwords pointer to the MSR values which the MSR should have + * set_fixed_range - checks & updates a fixed-range MTRR if it differs from the value it should have + * @msr: MSR address of the MTTR which should be checked and updated + * @changed: pointer which indicates whether the MTRR needed to be changed + * @msrwords: pointer to the MSR values which the MSR should have + * + * If K8 extentions are wanted, update the K8 SYSCFG MSR also. + * See AMD publication no. 24593, chapter 7.8.1, page 233 for more information. */ static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords) { @@ -199,12 +200,15 @@ static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords) } } +/** + * generic_get_free_region - Get a free MTRR. + * @base: The starting (base) address of the region. + * @size: The size (in bytes) of the region. + * @replace_reg: mtrr index to be replaced; set to invalid value if none. + * + * Returns: The index of the region on success, else negative on error. + */ int generic_get_free_region(unsigned long base, unsigned long size, int replace_reg) -/* [SUMMARY] Get a free MTRR. - <base> The starting (base) address of the region. - <size> The size (in bytes) of the region. - [RETURNS] The index of the region on success, else -1 on error. -*/ { int i, max; mtrr_type ltype; @@ -249,8 +253,8 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, } /** - * Checks and updates the fixed-range MTRRs if they differ from the saved set - * \param frs pointer to fixed-range MTRR values, saved by get_fixed_ranges() + * set_fixed_ranges - checks & updates the fixed-range MTRRs if they differ from the saved set + * @frs: pointer to fixed-range MTRR values, saved by get_fixed_ranges() */ static int set_fixed_ranges(mtrr_type * frs) { @@ -294,13 +298,13 @@ static bool set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) static u32 deftype_lo, deftype_hi; +/** + * set_mtrr_state - Set the MTRR state for this CPU. + * + * NOTE: The CPU must already be in a safe state for MTRR changes. + * RETURNS: 0 if no changes made, else a mask indicating what was changed. + */ static unsigned long set_mtrr_state(void) -/* [SUMMARY] Set the MTRR state for this CPU. - <state> The MTRR state information to read. - <ctxt> Some relevant CPU context. - [NOTE] The CPU must already be in a safe state for MTRR changes. - [RETURNS] 0 if no changes made, else a mask indication what was changed. -*/ { unsigned int i; unsigned long change_mask = 0; diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index c706a3061553..5921e5f0a640 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c @@ -78,6 +78,14 @@ static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = { }, { .callback = dmi_io_delay_0xed_port, + .ident = "HP Pavilion dv6000", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), + DMI_MATCH(DMI_BOARD_NAME, "30B8") + } + }, + { + .callback = dmi_io_delay_0xed_port, .ident = "HP Pavilion tx1000", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c index 027fc067b399..b402c0f3f192 100644 --- a/arch/x86/kernel/mfgpt_32.c +++ b/arch/x86/kernel/mfgpt_32.c @@ -30,6 +30,7 @@ #include <linux/kernel.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <asm/geode.h> static struct mfgpt_timer_t { diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index d5904eef1d31..eb92ccbb3502 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -600,21 +600,6 @@ static int ptrace_bts_read_record(struct task_struct *child, return sizeof(ret); } -static int ptrace_bts_write_record(struct task_struct *child, - const struct bts_struct *in) -{ - int retval; - - if (!child->thread.ds_area_msr) - return -ENXIO; - - retval = ds_write_bts((void *)child->thread.ds_area_msr, in); - if (retval) - return retval; - - return sizeof(*in); -} - static int ptrace_bts_clear(struct task_struct *child) { if (!child->thread.ds_area_msr) @@ -657,75 +642,6 @@ static int ptrace_bts_drain(struct task_struct *child, return end; } -static int ptrace_bts_realloc(struct task_struct *child, - int size, int reduce_size) -{ - unsigned long rlim, vm; - int ret, old_size; - - if (size < 0) - return -EINVAL; - - old_size = ds_get_bts_size((void *)child->thread.ds_area_msr); - if (old_size < 0) - return old_size; - - ret = ds_free((void **)&child->thread.ds_area_msr); - if (ret < 0) - goto out; - - size >>= PAGE_SHIFT; - old_size >>= PAGE_SHIFT; - - current->mm->total_vm -= old_size; - current->mm->locked_vm -= old_size; - - if (size == 0) - goto out; - - rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; - vm = current->mm->total_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->total_vm; - if (size <= 0) - goto out; - } - - rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; - vm = current->mm->locked_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->locked_vm; - if (size <= 0) - goto out; - } - - ret = ds_allocate((void **)&child->thread.ds_area_msr, - size << PAGE_SHIFT); - if (ret < 0) - goto out; - - current->mm->total_vm += size; - current->mm->locked_vm += size; - -out: - if (child->thread.ds_area_msr) - set_tsk_thread_flag(child, TIF_DS_AREA_MSR); - else - clear_tsk_thread_flag(child, TIF_DS_AREA_MSR); - - return ret; -} - static int ptrace_bts_config(struct task_struct *child, long cfg_size, const struct ptrace_bts_config __user *ucfg) @@ -828,6 +744,91 @@ static int ptrace_bts_status(struct task_struct *child, return sizeof(cfg); } + +static int ptrace_bts_write_record(struct task_struct *child, + const struct bts_struct *in) +{ + int retval; + + if (!child->thread.ds_area_msr) + return -ENXIO; + + retval = ds_write_bts((void *)child->thread.ds_area_msr, in); + if (retval) + return retval; + + return sizeof(*in); +} + +static int ptrace_bts_realloc(struct task_struct *child, + int size, int reduce_size) +{ + unsigned long rlim, vm; + int ret, old_size; + + if (size < 0) + return -EINVAL; + + old_size = ds_get_bts_size((void *)child->thread.ds_area_msr); + if (old_size < 0) + return old_size; + + ret = ds_free((void **)&child->thread.ds_area_msr); + if (ret < 0) + goto out; + + size >>= PAGE_SHIFT; + old_size >>= PAGE_SHIFT; + + current->mm->total_vm -= old_size; + current->mm->locked_vm -= old_size; + + if (size == 0) + goto out; + + rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; + vm = current->mm->total_vm + size; + if (rlim < vm) { + ret = -ENOMEM; + + if (!reduce_size) + goto out; + + size = rlim - current->mm->total_vm; + if (size <= 0) + goto out; + } + + rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; + vm = current->mm->locked_vm + size; + if (rlim < vm) { + ret = -ENOMEM; + + if (!reduce_size) + goto out; + + size = rlim - current->mm->locked_vm; + if (size <= 0) + goto out; + } + + ret = ds_allocate((void **)&child->thread.ds_area_msr, + size << PAGE_SHIFT); + if (ret < 0) + goto out; + + current->mm->total_vm += size; + current->mm->locked_vm += size; + +out: + if (child->thread.ds_area_msr) + set_tsk_thread_flag(child, TIF_DS_AREA_MSR); + else + clear_tsk_thread_flag(child, TIF_DS_AREA_MSR); + + return ret; +} + void ptrace_bts_take_timestamp(struct task_struct *tsk, enum bts_qualifier qualifier) { diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index a1d7071a51c9..2b3e5d45176b 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -406,8 +406,6 @@ static unsigned long __init setup_memory(void) */ min_low_pfn = PFN_UP(init_pg_tables_end); - find_max_pfn(); - max_low_pfn = find_max_low_pfn(); #ifdef CONFIG_HIGHMEM @@ -764,12 +762,13 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled) efi_init(); - max_low_pfn = setup_memory(); - /* update e820 for memory not covered by WB MTRRs */ + find_max_pfn(); mtrr_bp_init(); if (mtrr_trim_uncached_memory(max_pfn)) - max_low_pfn = setup_memory(); + find_max_pfn(); + + max_low_pfn = setup_memory(); #ifdef CONFIG_VMI /* diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 7637dc91c79b..f4f7ecfb898c 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -801,7 +801,7 @@ static void __cpuinit srat_detect_node(void) /* Don't do the funky fallback heuristics the AMD version employs for now. */ node = apicid_to_node[apicid]; - if (node == NUMA_NO_NODE) + if (node == NUMA_NO_NODE || !node_online(node)) node = first_node(node_online_map); numa_set_node(cpu, node); diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index d8172aabc660..e55af12e11b7 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -222,8 +222,7 @@ static int is_io_pte(unsigned long pte) static int is_rmap_pte(u64 pte) { - return pte != shadow_trap_nonpresent_pte - && pte != shadow_notrap_nonpresent_pte; + return is_shadow_present_pte(pte); } static gfn_t pse36_gfn_delta(u32 gpte) @@ -893,14 +892,25 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, int *ptwrite, gfn_t gfn, struct page *page) { u64 spte; - int was_rmapped = is_rmap_pte(*shadow_pte); + int was_rmapped = 0; int was_writeble = is_writeble_pte(*shadow_pte); + hfn_t host_pfn = (*shadow_pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT; pgprintk("%s: spte %llx access %x write_fault %d" " user_fault %d gfn %lx\n", __FUNCTION__, *shadow_pte, pt_access, write_fault, user_fault, gfn); + if (is_rmap_pte(*shadow_pte)) { + if (host_pfn != page_to_pfn(page)) { + pgprintk("hfn old %lx new %lx\n", + host_pfn, page_to_pfn(page)); + rmap_remove(vcpu->kvm, shadow_pte); + } + else + was_rmapped = 1; + } + /* * We don't set the accessed bit, since we sometimes want to see * whether the guest actually used the pte (in order to detect @@ -1402,7 +1412,7 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, up_read(¤t->mm->mmap_sem); vcpu->arch.update_pte.gfn = gfn; - vcpu->arch.update_pte.page = gfn_to_page(vcpu->kvm, gfn); + vcpu->arch.update_pte.page = page; } void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 94ea724638fd..8e1462880d1f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -349,8 +349,6 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu) static void reload_tss(void) { -#ifndef CONFIG_X86_64 - /* * VT restores TR but not its size. Useless. */ @@ -361,7 +359,6 @@ static void reload_tss(void) descs = (void *)gdt.base; descs[GDT_ENTRY_TSS].type = 9; /* available TSS */ load_TR_desc(); -#endif } static void load_transition_efer(struct vcpu_vmx *vmx) @@ -1436,7 +1433,7 @@ static int init_rmode_tss(struct kvm *kvm) int ret = 0; int r; - down_read(¤t->mm->mmap_sem); + down_read(&kvm->slots_lock); r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE); if (r < 0) goto out; @@ -1459,7 +1456,7 @@ static int init_rmode_tss(struct kvm *kvm) ret = 1; out: - up_read(¤t->mm->mmap_sem); + up_read(&kvm->slots_lock); return ret; } diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index a104c532ff70..3335b4595efd 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -10,21 +10,19 @@ * (such as the example in Documentation/lguest/lguest.c) is called the * Launcher. * - * Secondly, we only run specially modified Guests, not normal kernels. When - * you set CONFIG_LGUEST to 'y' or 'm', this automatically sets - * CONFIG_LGUEST_GUEST=y, which compiles this file into the kernel so it knows - * how to be a Guest. This means that you can use the same kernel you boot - * normally (ie. as a Host) as a Guest. + * Secondly, we only run specially modified Guests, not normal kernels: setting + * CONFIG_LGUEST_GUEST to "y" compiles this file into the kernel so it knows + * how to be a Guest at boot time. This means that you can use the same kernel + * you boot normally (ie. as a Host) as a Guest. * * These Guests know that they cannot do privileged operations, such as disable * interrupts, and that they have to ask the Host to do such things explicitly. * This file consists of all the replacements for such low-level native * hardware operations: these special Guest versions call the Host. * - * So how does the kernel know it's a Guest? The Guest starts at a special - * entry point marked with a magic string, which sets up a few things then - * calls here. We replace the native functions various "paravirt" structures - * with our Guest versions, then boot like normal. :*/ + * So how does the kernel know it's a Guest? We'll see that later, but let's + * just say that we end up here where we replace the native functions various + * "paravirt" structures with our Guest versions, then boot like normal. :*/ /* * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation. @@ -134,7 +132,7 @@ static void async_hcall(unsigned long call, unsigned long arg1, * lguest_leave_lazy_mode(). * * So, when we're in lazy mode, we call async_hcall() to store the call for - * future processing. */ + * future processing: */ static void lazy_hcall(unsigned long call, unsigned long arg1, unsigned long arg2, @@ -147,7 +145,7 @@ static void lazy_hcall(unsigned long call, } /* When lazy mode is turned off reset the per-cpu lazy mode variable and then - * issue a hypercall to flush any stored calls. */ + * issue the do-nothing hypercall to flush any stored calls. */ static void lguest_leave_lazy_mode(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); @@ -164,7 +162,7 @@ static void lguest_leave_lazy_mode(void) * * So instead we keep an "irq_enabled" field inside our "struct lguest_data", * which the Guest can update with a single instruction. The Host knows to - * check there when it wants to deliver an interrupt. + * check there before it tries to deliver an interrupt. */ /* save_flags() is expected to return the processor state (ie. "flags"). The @@ -196,10 +194,15 @@ static void irq_enable(void) /*M:003 Note that we don't check for outstanding interrupts when we re-enable * them (or when we unmask an interrupt). This seems to work for the moment, * since interrupts are rare and we'll just get the interrupt on the next timer - * tick, but when we turn on CONFIG_NO_HZ, we should revisit this. One way + * tick, but now we can run with CONFIG_NO_HZ, we should revisit this. One way * would be to put the "irq_enabled" field in a page by itself, and have the * Host write-protect it when an interrupt comes in when irqs are disabled. - * There will then be a page fault as soon as interrupts are re-enabled. :*/ + * There will then be a page fault as soon as interrupts are re-enabled. + * + * A better method is to implement soft interrupt disable generally for x86: + * instead of disabling interrupts, we set a flag. If an interrupt does come + * in, we then disable them for real. This is uncommon, so we could simply use + * a hypercall for interrupt control and not worry about efficiency. :*/ /*G:034 * The Interrupt Descriptor Table (IDT). @@ -212,6 +215,10 @@ static void irq_enable(void) static void lguest_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g) { + /* The gate_desc structure is 8 bytes long: we hand it to the Host in + * two 32-bit chunks. The whole 32-bit kernel used to hand descriptors + * around like this; typesafety wasn't a big concern in Linux's early + * years. */ u32 *desc = (u32 *)g; /* Keep the local copy up to date. */ native_write_idt_entry(dt, entrynum, g); @@ -243,7 +250,8 @@ static void lguest_load_idt(const struct desc_ptr *desc) * * This is the opposite of the IDT code where we have a LOAD_IDT_ENTRY * hypercall and use that repeatedly to load a new IDT. I don't think it - * really matters, but wouldn't it be nice if they were the same? + * really matters, but wouldn't it be nice if they were the same? Wouldn't + * it be even better if you were the one to send the patch to fix it? */ static void lguest_load_gdt(const struct desc_ptr *desc) { @@ -298,9 +306,9 @@ static void lguest_load_tr_desc(void) /* The "cpuid" instruction is a way of querying both the CPU identity * (manufacturer, model, etc) and its features. It was introduced before the - * Pentium in 1993 and keeps getting extended by both Intel and AMD. As you - * might imagine, after a decade and a half this treatment, it is now a giant - * ball of hair. Its entry in the current Intel manual runs to 28 pages. + * Pentium in 1993 and keeps getting extended by both Intel, AMD and others. + * As you might imagine, after a decade and a half this treatment, it is now a + * giant ball of hair. Its entry in the current Intel manual runs to 28 pages. * * This instruction even it has its own Wikipedia entry. The Wikipedia entry * has been translated into 4 languages. I am not making this up! @@ -594,17 +602,17 @@ static unsigned long lguest_get_wallclock(void) return lguest_data.time.tv_sec; } -/* The TSC is a Time Stamp Counter. The Host tells us what speed it runs at, - * or 0 if it's unusable as a reliable clock source. This matches what we want - * here: if we return 0 from this function, the x86 TSC clock will not register - * itself. */ +/* The TSC is an Intel thing called the Time Stamp Counter. The Host tells us + * what speed it runs at, or 0 if it's unusable as a reliable clock source. + * This matches what we want here: if we return 0 from this function, the x86 + * TSC clock will give up and not register itself. */ static unsigned long lguest_cpu_khz(void) { return lguest_data.tsc_khz; } -/* If we can't use the TSC, the kernel falls back to our "lguest_clock", where - * we read the time value given to us by the Host. */ +/* If we can't use the TSC, the kernel falls back to our lower-priority + * "lguest_clock", where we read the time value given to us by the Host. */ static cycle_t lguest_clock_read(void) { unsigned long sec, nsec; @@ -648,12 +656,16 @@ static struct clocksource lguest_clock = { static int lguest_clockevent_set_next_event(unsigned long delta, struct clock_event_device *evt) { + /* FIXME: I don't think this can ever happen, but James tells me he had + * to put this code in. Maybe we should remove it now. Anyone? */ if (delta < LG_CLOCK_MIN_DELTA) { if (printk_ratelimit()) printk(KERN_DEBUG "%s: small delta %lu ns\n", __FUNCTION__, delta); return -ETIME; } + + /* Please wake us this far in the future. */ hcall(LHCALL_SET_CLOCKEVENT, delta, 0, 0); return 0; } @@ -738,7 +750,7 @@ static void lguest_time_init(void) * will not tolerate us trying to use that), the stack pointer, and the number * of pages in the stack. */ static void lguest_load_sp0(struct tss_struct *tss, - struct thread_struct *thread) + struct thread_struct *thread) { lazy_hcall(LHCALL_SET_STACK, __KERNEL_DS|0x1, thread->sp0, THREAD_SIZE/PAGE_SIZE); @@ -786,9 +798,8 @@ static void lguest_safe_halt(void) hcall(LHCALL_HALT, 0, 0, 0); } -/* Perhaps CRASH isn't the best name for this hypercall, but we use it to get a - * message out when we're crashing as well as elegant termination like powering - * off. +/* The SHUTDOWN hypercall takes a string to describe what's happening, and + * an argument which says whether this to restart (reboot) the Guest or not. * * Note that the Host always prefers that the Guest speak in physical addresses * rather than virtual addresses, so we use __pa() here. */ @@ -816,8 +827,9 @@ static struct notifier_block paniced = { /* Setting up memory is fairly easy. */ static __init char *lguest_memory_setup(void) { - /* We do this here and not earlier because lockcheck barfs if we do it - * before start_kernel() */ + /* We do this here and not earlier because lockcheck used to barf if we + * did it before start_kernel(). I think we fixed that, so it'd be + * nice to move it back to lguest_init. Patch welcome... */ atomic_notifier_chain_register(&panic_notifier_list, &paniced); /* The Linux bootloader header contains an "e820" memory map: the @@ -850,12 +862,19 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count) return len; } +/* Rebooting also tells the Host we're finished, but the RESTART flag tells the + * Launcher to reboot us. */ +static void lguest_restart(char *reason) +{ + hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0); +} + /*G:050 * Patching (Powerfully Placating Performance Pedants) * - * We have already seen that pv_ops structures let us replace simple - * native instructions with calls to the appropriate back end all throughout - * the kernel. This allows the same kernel to run as a Guest and as a native + * We have already seen that pv_ops structures let us replace simple native + * instructions with calls to the appropriate back end all throughout the + * kernel. This allows the same kernel to run as a Guest and as a native * kernel, but it's slow because of all the indirect branches. * * Remember that David Wheeler quote about "Any problem in computer science can @@ -908,14 +927,9 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf, return insn_len; } -static void lguest_restart(char *reason) -{ - hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0); -} - -/*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops - * structures in the kernel provide points for (almost) every routine we have - * to override to avoid privileged instructions. */ +/*G:030 Once we get to lguest_init(), we know we're a Guest. The various + * pv_ops structures in the kernel provide points for (almost) every routine we + * have to override to avoid privileged instructions. */ __init void lguest_init(void) { /* We're under lguest, paravirt is enabled, and we're running at @@ -1003,9 +1017,9 @@ __init void lguest_init(void) * the normal data segment to get through booting. */ asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory"); - /* The Host uses the top of the Guest's virtual address space for the - * Host<->Guest Switcher, and it tells us how big that is in - * lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */ + /* The Host<->Guest Switcher lives at the top of our address space, and + * the Host told us how big it is when we made LGUEST_INIT hypercall: + * it put the answer in lguest_data.reserve_mem */ reserve_top_address(lguest_data.reserve_mem); /* If we don't initialize the lock dependency checker now, it crashes @@ -1027,6 +1041,7 @@ __init void lguest_init(void) /* Math is always hard! */ new_cpu_data.hard_math = 1; + /* We don't have features. We have puppies! Puppies! */ #ifdef CONFIG_X86_MCE mce_disabled = 1; #endif @@ -1044,10 +1059,11 @@ __init void lguest_init(void) virtio_cons_early_init(early_put_chars); /* Last of all, we set the power management poweroff hook to point to - * the Guest routine to power off. */ + * the Guest routine to power off, and the reboot hook to our restart + * routine. */ pm_power_off = lguest_power_off; - machine_ops.restart = lguest_restart; + /* Now we're set up, call start_kernel() in init/main.c and we proceed * to boot as normal. It never returns. */ start_kernel(); diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 95b6fbcded63..5c7cef34c9e7 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S @@ -5,13 +5,20 @@ #include <asm/thread_info.h> #include <asm/processor-flags.h> -/*G:020 This is where we begin: head.S notes that the boot header's platform - * type field is "1" (lguest), so calls us here. +/*G:020 Our story starts with the kernel booting into startup_32 in + * arch/x86/kernel/head_32.S. It expects a boot header, which is created by + * the bootloader (the Launcher in our case). + * + * The startup_32 function does very little: it clears the uninitialized global + * C variables which we expect to be zero (ie. BSS) and then copies the boot + * header and kernel command line somewhere safe. Finally it checks the + * 'hardware_subarch' field. This was introduced in 2.6.24 for lguest and Xen: + * if it's set to '1' (lguest's assigned number), then it calls us here. * * WARNING: be very careful here! We're running at addresses equal to physical * addesses (around 0), not above PAGE_OFFSET as most code expectes * (eg. 0xC0000000). Jumps are relative, so they're OK, but we can't touch any - * data. + * data without remembering to subtract __PAGE_OFFSET! * * The .section line puts this code in .init.text so it will be discarded after * boot. */ @@ -24,7 +31,7 @@ ENTRY(lguest_entry) int $LGUEST_TRAP_ENTRY /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl - * instruction uses %esi implicitly as the source for the copy we' + * instruction uses %esi implicitly as the source for the copy we're * about to do. */ movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi diff --git a/arch/x86/mach-rdc321x/gpio.c b/arch/x86/mach-rdc321x/gpio.c index 031269163bd6..247f33d3a407 100644 --- a/arch/x86/mach-rdc321x/gpio.c +++ b/arch/x86/mach-rdc321x/gpio.c @@ -1,91 +1,194 @@ /* - * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org> - * RDC321x architecture specific GPIO support + * GPIO support for RDC SoC R3210/R8610 + * + * Copyright (C) 2007, Florian Fainelli <florian@openwrt.org> + * Copyright (C) 2008, Volker Weiss <dev@tintuc.de> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - * 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/autoconf.h> -#include <linux/init.h> + +#include <linux/spinlock.h> #include <linux/io.h> #include <linux/types.h> #include <linux/module.h> -#include <linux/delay.h> +#include <asm/gpio.h> #include <asm/mach-rdc321x/rdc321x_defs.h> -static inline int rdc_gpio_is_valid(unsigned gpio) + +/* spin lock to protect our private copy of GPIO data register plus + the access to PCI conf registers. */ +static DEFINE_SPINLOCK(gpio_lock); + +/* copy of GPIO data registers */ +static u32 gpio_data_reg1; +static u32 gpio_data_reg2; + +static u32 gpio_request_data[2]; + + +static inline void rdc321x_conf_write(unsigned addr, u32 value) { - return (gpio <= RDC_MAX_GPIO); + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + outl(value, RDC3210_CFGREG_DATA); } -static unsigned int rdc_gpio_read(unsigned gpio) +static inline void rdc321x_conf_or(unsigned addr, u32 value) { - unsigned int val; - - val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x84:0x48)); - outl(val, RDC3210_CFGREG_ADDR); - udelay(10); - val = inl(RDC3210_CFGREG_DATA); - val |= (0x1 << (gpio & 0x1F)); - outl(val, RDC3210_CFGREG_DATA); - udelay(10); - val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x88:0x4C)); - outl(val, RDC3210_CFGREG_ADDR); - udelay(10); - val = inl(RDC3210_CFGREG_DATA); - - return val; + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + value |= inl(RDC3210_CFGREG_DATA); + outl(value, RDC3210_CFGREG_DATA); } -static void rdc_gpio_write(unsigned int val) +static inline u32 rdc321x_conf_read(unsigned addr) { - if (val) { - outl(val, RDC3210_CFGREG_DATA); - udelay(10); - } + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + + return inl(RDC3210_CFGREG_DATA); } -int rdc_gpio_get_value(unsigned gpio) +/* configure pin as GPIO */ +static void rdc321x_configure_gpio(unsigned gpio) +{ + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + rdc321x_conf_or(gpio < 32 + ? RDC321X_GPIO_CTRL_REG1 : RDC321X_GPIO_CTRL_REG2, + 1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); +} + +/* initially setup the 2 copies of the gpio data registers. + This function must be called by the platform setup code. */ +void __init rdc321x_gpio_setup() +{ + /* this might not be, what others (BIOS, bootloader, etc.) + wrote to these registers before, but it's a good guess. Still + better than just using 0xffffffff. */ + + gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1); + gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2); +} + +/* determine, if gpio number is valid */ +static inline int rdc321x_is_gpio(unsigned gpio) +{ + return gpio <= RDC321X_MAX_GPIO; +} + +/* request GPIO */ +int rdc_gpio_request(unsigned gpio, const char *label) { - if (rdc_gpio_is_valid(gpio)) - return (int)rdc_gpio_read(gpio); - else + unsigned long flags; + + if (!rdc321x_is_gpio(gpio)) return -EINVAL; + + spin_lock_irqsave(&gpio_lock, flags); + if (gpio_request_data[(gpio & 0x20) ? 1 : 0] & (1 << (gpio & 0x1f))) + goto inuse; + gpio_request_data[(gpio & 0x20) ? 1 : 0] |= (1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +inuse: + spin_unlock_irqrestore(&gpio_lock, flags); + return -EINVAL; } -EXPORT_SYMBOL(rdc_gpio_get_value); +EXPORT_SYMBOL(rdc_gpio_request); -void rdc_gpio_set_value(unsigned gpio, int value) +/* release previously-claimed GPIO */ +void rdc_gpio_free(unsigned gpio) { - unsigned int val; + unsigned long flags; - if (!rdc_gpio_is_valid(gpio)) + if (!rdc321x_is_gpio(gpio)) return; - val = rdc_gpio_read(gpio); + spin_lock_irqsave(&gpio_lock, flags); + gpio_request_data[(gpio & 0x20) ? 1 : 0] &= ~(1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(rdc_gpio_free); + +/* read GPIO pin */ +int rdc_gpio_get_value(unsigned gpio) +{ + u32 reg; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + reg = rdc321x_conf_read(gpio < 32 + ? RDC321X_GPIO_DATA_REG1 : RDC321X_GPIO_DATA_REG2); + spin_unlock_irqrestore(&gpio_lock, flags); - if (value) - val &= ~(0x1 << (gpio & 0x1F)); - else - val |= (0x1 << (gpio & 0x1F)); + return (1 << (gpio & 0x1f)) & reg ? 1 : 0; +} +EXPORT_SYMBOL(rdc_gpio_get_value); - rdc_gpio_write(val); +/* set GPIO pin to value */ +void rdc_gpio_set_value(unsigned gpio, int value) +{ + unsigned long flags; + u32 reg; + + reg = 1 << (gpio & 0x1f); + if (gpio < 32) { + spin_lock_irqsave(&gpio_lock, flags); + if (value) + gpio_data_reg1 |= reg; + else + gpio_data_reg1 &= ~reg; + rdc321x_conf_write(RDC321X_GPIO_DATA_REG1, gpio_data_reg1); + spin_unlock_irqrestore(&gpio_lock, flags); + } else { + spin_lock_irqsave(&gpio_lock, flags); + if (value) + gpio_data_reg2 |= reg; + else + gpio_data_reg2 &= ~reg; + rdc321x_conf_write(RDC321X_GPIO_DATA_REG2, gpio_data_reg2); + spin_unlock_irqrestore(&gpio_lock, flags); + } } EXPORT_SYMBOL(rdc_gpio_set_value); +/* configure GPIO pin as input */ int rdc_gpio_direction_input(unsigned gpio) { + if (!rdc321x_is_gpio(gpio)) + return -EINVAL; + + rdc321x_configure_gpio(gpio); + return 0; } EXPORT_SYMBOL(rdc_gpio_direction_input); +/* configure GPIO pin as output and set value */ int rdc_gpio_direction_output(unsigned gpio, int value) { + if (!rdc321x_is_gpio(gpio)) + return -EINVAL; + + gpio_set_value(gpio, value); + rdc321x_configure_gpio(gpio); + return 0; } EXPORT_SYMBOL(rdc_gpio_direction_output); - - diff --git a/arch/x86/mach-rdc321x/platform.c b/arch/x86/mach-rdc321x/platform.c index dda6024a5862..a037041817c7 100644 --- a/arch/x86/mach-rdc321x/platform.c +++ b/arch/x86/mach-rdc321x/platform.c @@ -62,6 +62,8 @@ static struct platform_device *rdc321x_devs[] = { static int __init rdc_board_setup(void) { + rdc321x_gpio_setup(); + return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs)); } diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c index c394ca0720b8..8e25e06ff730 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/discontig_32.c @@ -324,7 +324,6 @@ unsigned long __init setup_memory(void) * this space and use it to adjust the boundary between ZONE_NORMAL * and ZONE_HIGHMEM. */ - find_max_pfn(); get_memcfg_numa(); kva_pages = calculate_numa_remap_pages(); diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index fdc667422df9..ec08d8389850 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -91,12 +91,10 @@ static int is_prefetch(struct pt_regs *regs, unsigned long addr, int prefetch = 0; unsigned char *max_instr; -#ifdef CONFIG_X86_32 - if (!(__supported_pte_mask & _PAGE_NX)) - return 0; -#endif - - /* If it was a exec fault on NX page, ignore */ + /* + * If it was a exec (instruction fetch) fault on NX page, then + * do not ignore the fault: + */ if (error_code & PF_INSTR) return 0; diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index 4fbafb4bc2f0..0b3d567e686d 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -178,7 +178,7 @@ follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; - WARN_ON(!PageCompound(page)); + WARN_ON(!PageHead(page)); return page; } diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 4afaba0ed722..794895c6dcc9 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -137,7 +137,11 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size, switch (mode) { case IOR_MODE_UNCACHED: default: - prot = PAGE_KERNEL_NOCACHE; + /* + * FIXME: we will use UC MINUS for now, as video fb drivers + * depend on it. Upcoming ioremap_wc() will fix this behavior. + */ + prot = PAGE_KERNEL_UC_MINUS; break; case IOR_MODE_CACHED: prot = PAGE_KERNEL; diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 14e48b5a94ba..7b79f6be4e7d 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -771,7 +771,7 @@ static inline int change_page_attr_clear(unsigned long addr, int numpages, int set_memory_uc(unsigned long addr, int numpages) { return change_page_attr_set(addr, numpages, - __pgprot(_PAGE_PCD | _PAGE_PWT)); + __pgprot(_PAGE_PCD)); } EXPORT_SYMBOL(set_memory_uc); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 8b9ee27805fd..de4e6f05840b 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -95,7 +95,7 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&dummy_shared_info; * * 0: not available, 1: available */ -static int have_vcpu_info_placement = 0; +static int have_vcpu_info_placement = 1; static void __init xen_vcpu_setup(int cpu) { @@ -103,6 +103,7 @@ static void __init xen_vcpu_setup(int cpu) int err; struct vcpu_info *vcpup; + BUG_ON(HYPERVISOR_shared_info == &dummy_shared_info); per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; if (!have_vcpu_info_placement) @@ -805,33 +806,43 @@ static __init void xen_pagetable_setup_start(pgd_t *base) PFN_DOWN(__pa(xen_start_info->pt_base))); } -static __init void xen_pagetable_setup_done(pgd_t *base) +static __init void setup_shared_info(void) { - /* This will work as long as patching hasn't happened yet - (which it hasn't) */ - pv_mmu_ops.alloc_pt = xen_alloc_pt; - pv_mmu_ops.alloc_pd = xen_alloc_pd; - pv_mmu_ops.release_pt = xen_release_pt; - pv_mmu_ops.release_pd = xen_release_pt; - pv_mmu_ops.set_pte = xen_set_pte; - if (!xen_feature(XENFEAT_auto_translated_physmap)) { + unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP); + /* * Create a mapping for the shared info page. * Should be set_fixmap(), but shared_info is a machine * address with no corresponding pseudo-phys address. */ - set_pte_mfn(fix_to_virt(FIX_PARAVIRT_BOOTMAP), + set_pte_mfn(addr, PFN_DOWN(xen_start_info->shared_info), PAGE_KERNEL); - HYPERVISOR_shared_info = - (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); - + HYPERVISOR_shared_info = (struct shared_info *)addr; } else HYPERVISOR_shared_info = (struct shared_info *)__va(xen_start_info->shared_info); +#ifndef CONFIG_SMP + /* In UP this is as good a place as any to set up shared info */ + xen_setup_vcpu_info_placement(); +#endif +} + +static __init void xen_pagetable_setup_done(pgd_t *base) +{ + /* This will work as long as patching hasn't happened yet + (which it hasn't) */ + pv_mmu_ops.alloc_pt = xen_alloc_pt; + pv_mmu_ops.alloc_pd = xen_alloc_pd; + pv_mmu_ops.release_pt = xen_release_pt; + pv_mmu_ops.release_pd = xen_release_pt; + pv_mmu_ops.set_pte = xen_set_pte; + + setup_shared_info(); + /* Actually pin the pagetable down, but we can't set PG_pinned yet because the page structures don't exist yet. */ { @@ -1182,15 +1193,9 @@ asmlinkage void __init xen_start_kernel(void) x86_write_percpu(xen_cr3, __pa(pgd)); x86_write_percpu(xen_current_cr3, __pa(pgd)); -#ifdef CONFIG_SMP /* Don't do the full vcpu_info placement stuff until we have a - possible map. */ + possible map and a non-dummy shared_info. */ per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; -#else - /* May as well do it now, since there's no good time to call - it later on UP. */ - xen_setup_vcpu_info_placement(); -#endif pv_info.kernel_rpl = 1; if (xen_feature(XENFEAT_supervisor_mode_kernel)) diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S index 1a43b60c0c62..6b7190449d07 100644 --- a/arch/x86/xen/xen-asm.S +++ b/arch/x86/xen/xen-asm.S @@ -33,12 +33,17 @@ events, then enter the hypervisor to get them handled. */ ENTRY(xen_irq_enable_direct) - /* Clear mask and test pending */ - andw $0x00ff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending + /* Unmask events */ + movb $0, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask + /* Preempt here doesn't matter because that will deal with any pending interrupts. The pending check may end up being run on the wrong CPU, but that doesn't hurt. */ + + /* Test for pending */ + testb $0xff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending jz 1f + 2: call check_events 1: ENDPATCH(xen_irq_enable_direct) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 7af414a3c63e..89022a74faee 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -131,8 +131,8 @@ struct prt_quirk { */ static struct prt_quirk prt_quirks[] = { { medion_md9580, 0, 0, 9, 'A', - "\\_SB_.PCI0.ISA.LNKA", - "\\_SB_.PCI0.ISA.LNKB"}, + "\\_SB_.PCI0.ISA_.LNKA", + "\\_SB_.PCI0.ISA_.LNKB"}, { dell_optiplex, 0, 0, 0xd, 'A', "\\_SB_.LNKB", "\\_SB_.LNKA"}, diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e8e2d8869236..788da9781f80 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1487,7 +1487,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, return 0; } - acpi_unlazy_tlb(smp_processor_id()); /* * Must be done before busmaster disable as we might need to * access HPET ! @@ -1577,6 +1576,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, return 0; } + acpi_unlazy_tlb(smp_processor_id()); + /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); /* @@ -1692,7 +1693,9 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) switch (cx->type) { case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; - state->flags |= CPUIDLE_FLAG_TIME_VALID; + if (cx->entry_method == ACPI_CSTATE_FFH) + state->flags |= CPUIDLE_FLAG_TIME_VALID; + state->enter = acpi_idle_enter_c1; dev->safe_state = state; break; diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index a2cf3008ce6c..bcf2c70fca87 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -130,7 +130,6 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, goto end; } smb_hc_write(hc, ACPI_SMB_COMMAND, command); - smb_hc_write(hc, ACPI_SMB_COMMAND, command); if (!(protocol & 0x01)) { smb_hc_write(hc, ACPI_SMB_BLOCK_COUNT, length); for (i = 0; i < length; ++i) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 57570ac47803..e6ce262b5d44 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -39,20 +39,26 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, int size) { int len; + int count; - if (!acpi_dev->flags.hardware_id) + if (!acpi_dev->flags.hardware_id && !acpi_dev->flags.compatible_ids) return -ENODEV; - len = snprintf(modalias, size, "acpi:%s:", - acpi_dev->pnp.hardware_id); - if (len < 0 || len >= size) - return -EINVAL; + len = snprintf(modalias, size, "acpi:"); size -= len; + if (acpi_dev->flags.hardware_id) { + count = snprintf(&modalias[len], size, "%s:", + acpi_dev->pnp.hardware_id); + if (count < 0 || count >= size) + return -EINVAL; + len += count; + size -= count; + } + if (acpi_dev->flags.compatible_ids) { struct acpi_compatible_id_list *cid_list; int i; - int count; cid_list = acpi_dev->pnp.cid_list; for (i = 0; i < cid_list->count; i++) { diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 17ee6ed985d9..b1eb4e24c86a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -433,6 +433,7 @@ static const struct ata_port_info ahci_port_info[] = { /* board_ahci_sb600 */ { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | + AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, .link_flags = AHCI_LFLAG_COMMON, @@ -1217,8 +1218,11 @@ static void ahci_dev_config(struct ata_device *dev) { struct ahci_host_priv *hpriv = dev->link->ap->host->private_data; - if (hpriv->flags & AHCI_HFLAG_SECT255) + if (hpriv->flags & AHCI_HFLAG_SECT255) { dev->max_sectors = 255; + ata_dev_printk(dev, KERN_INFO, + "SB600 AHCI: limiting to 255 sectors per cmd\n"); + } } static unsigned int ahci_dev_classify(struct ata_port *ap) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4bbe31f98ef8..c4248b37ff64 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1416,12 +1416,12 @@ static int ata_hpa_resize(struct ata_device *dev) /* read native max address */ rc = ata_read_native_max_address(dev, &native_sectors); if (rc) { - /* If HPA isn't going to be unlocked, skip HPA - * resizing from the next try. + /* If device aborted the command or HPA isn't going to + * be unlocked, skip HPA resizing. */ - if (!ata_ignore_hpa) { + if (rc == -EACCES || !ata_ignore_hpa) { ata_dev_printk(dev, KERN_WARNING, "HPA support seems " - "broken, will skip HPA handling\n"); + "broken, skipping HPA handling\n"); dev->horkage |= ATA_HORKAGE_BROKEN_HPA; /* we can continue if device aborted the command */ @@ -2092,24 +2092,34 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, id, sizeof(id[0]) * ATA_ID_WORDS, 0); if (err_mask) { if (err_mask & AC_ERR_NODEV_HINT) { - DPRINTK("ata%u.%d: NODEV after polling detection\n", - ap->print_id, dev->devno); + ata_dev_printk(dev, KERN_DEBUG, + "NODEV after polling detection\n"); return -ENOENT; } - /* Device or controller might have reported the wrong - * device class. Give a shot at the other IDENTIFY if - * the current one is aborted by the device. - */ - if (may_fallback && - (err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) { - may_fallback = 0; + if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) { + /* Device or controller might have reported + * the wrong device class. Give a shot at the + * other IDENTIFY if the current one is + * aborted by the device. + */ + if (may_fallback) { + may_fallback = 0; - if (class == ATA_DEV_ATA) - class = ATA_DEV_ATAPI; - else - class = ATA_DEV_ATA; - goto retry; + if (class == ATA_DEV_ATA) + class = ATA_DEV_ATAPI; + else + class = ATA_DEV_ATA; + goto retry; + } + + /* Control reaches here iff the device aborted + * both flavors of IDENTIFYs which happens + * sometimes with phantom devices. + */ + ata_dev_printk(dev, KERN_DEBUG, + "both IDENTIFYs aborted, assuming NODEV\n"); + return -ENOENT; } rc = -EIO; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8f0e8f2bc628..15795394b0a8 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -527,6 +527,14 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, return qc; } +static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + + qc->extrabytes = scmd->request->extra_len; + qc->nbytes = scsi_bufflen(scmd) + qc->extrabytes; +} + /** * ata_dump_status - user friendly display of error info * @id: id of the port in question @@ -2539,7 +2547,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) } qc->tf.command = ATA_CMD_PACKET; - qc->nbytes = scsi_bufflen(scmd) + scmd->request->extra_len; + ata_qc_set_pc_nbytes(qc); /* check whether ATAPI DMA is safe */ if (!using_pio && ata_check_atapi_dma(qc)) @@ -2550,7 +2558,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) * want to set it properly, and for DMA where it is * effectively meaningless. */ - nbytes = min(scmd->request->data_len, (unsigned int)63 * 1024); + nbytes = min(ata_qc_raw_nbytes(qc), (unsigned int)63 * 1024); /* Most ATAPI devices which honor transfer chunk size don't * behave according to the spec when odd chunk size which @@ -2876,7 +2884,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * TODO: find out if we need to do more here to * cover scatter/gather case. */ - qc->nbytes = scsi_bufflen(scmd) + scmd->request->extra_len; + ata_qc_set_pc_nbytes(qc); /* request result TF and be quiet about device error */ qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET; diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 109ddd42c266..257951d03dbb 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -564,7 +564,7 @@ static int it821x_check_atapi_dma(struct ata_queued_cmd *qc) struct it821x_dev *itdev = ap->private_data; /* Only use dma for transfers to/from the media. */ - if (qc->nbytes < 2048) + if (ata_qc_raw_nbytes(qc) < 2048) return -EOPNOTSUPP; /* No ATAPI DMA in smart mode */ diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index f251a5f569d5..11c1afea2db2 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -46,7 +46,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "2.11" +#define DRV_VERSION "2.12" enum { PDC_MAX_PORTS = 4, @@ -145,7 +145,9 @@ static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc); static void pdc_irq_clear(struct ata_port *ap); static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static void pdc_freeze(struct ata_port *ap); +static void pdc_sata_freeze(struct ata_port *ap); static void pdc_thaw(struct ata_port *ap); +static void pdc_sata_thaw(struct ata_port *ap); static void pdc_pata_error_handler(struct ata_port *ap); static void pdc_sata_error_handler(struct ata_port *ap); static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); @@ -180,8 +182,8 @@ static const struct ata_port_operations pdc_sata_ops = { .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, - .freeze = pdc_freeze, - .thaw = pdc_thaw, + .freeze = pdc_sata_freeze, + .thaw = pdc_sata_thaw, .error_handler = pdc_sata_error_handler, .post_internal_cmd = pdc_post_internal_cmd, .cable_detect = pdc_sata_cable_detect, @@ -205,8 +207,8 @@ static const struct ata_port_operations pdc_old_sata_ops = { .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, - .freeze = pdc_freeze, - .thaw = pdc_thaw, + .freeze = pdc_sata_freeze, + .thaw = pdc_sata_thaw, .error_handler = pdc_sata_error_handler, .post_internal_cmd = pdc_post_internal_cmd, .cable_detect = pdc_sata_cable_detect, @@ -631,6 +633,41 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) } } +static int pdc_is_sataii_tx4(unsigned long flags) +{ + const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; + return (flags & mask) == mask; +} + +static unsigned int pdc_port_no_to_ata_no(unsigned int port_no, + int is_sataii_tx4) +{ + static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; + return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; +} + +static unsigned int pdc_sata_nr_ports(const struct ata_port *ap) +{ + return (ap->flags & PDC_FLAG_4_PORTS) ? 4 : 2; +} + +static unsigned int pdc_sata_ata_port_to_ata_no(const struct ata_port *ap) +{ + const struct ata_host *host = ap->host; + unsigned int nr_ports = pdc_sata_nr_ports(ap); + unsigned int i; + + for(i = 0; i < nr_ports && host->ports[i] != ap; ++i) + ; + BUG_ON(i >= nr_ports); + return pdc_port_no_to_ata_no(i, pdc_is_sataii_tx4(ap->flags)); +} + +static unsigned int pdc_sata_hotplug_offset(const struct ata_port *ap) +{ + return (ap->flags & PDC_FLAG_GEN_II) ? PDC2_SATA_PLUG_CSR : PDC_SATA_PLUG_CSR; +} + static void pdc_freeze(struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.cmd_addr; @@ -643,6 +680,29 @@ static void pdc_freeze(struct ata_port *ap) readl(mmio + PDC_CTLSTAT); /* flush */ } +static void pdc_sata_freeze(struct ata_port *ap) +{ + struct ata_host *host = ap->host; + void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; + unsigned int hotplug_offset = pdc_sata_hotplug_offset(ap); + unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap); + u32 hotplug_status; + + /* Disable hotplug events on this port. + * + * Locking: + * 1) hotplug register accesses must be serialised via host->lock + * 2) ap->lock == &ap->host->lock + * 3) ->freeze() and ->thaw() are called with ap->lock held + */ + hotplug_status = readl(host_mmio + hotplug_offset); + hotplug_status |= 0x11 << (ata_no + 16); + writel(hotplug_status, host_mmio + hotplug_offset); + readl(host_mmio + hotplug_offset); /* flush */ + + pdc_freeze(ap); +} + static void pdc_thaw(struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.cmd_addr; @@ -658,6 +718,26 @@ static void pdc_thaw(struct ata_port *ap) readl(mmio + PDC_CTLSTAT); /* flush */ } +static void pdc_sata_thaw(struct ata_port *ap) +{ + struct ata_host *host = ap->host; + void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; + unsigned int hotplug_offset = pdc_sata_hotplug_offset(ap); + unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap); + u32 hotplug_status; + + pdc_thaw(ap); + + /* Enable hotplug events on this port. + * Locking: see pdc_sata_freeze(). + */ + hotplug_status = readl(host_mmio + hotplug_offset); + hotplug_status |= 0x11 << ata_no; + hotplug_status &= ~(0x11 << (ata_no + 16)); + writel(hotplug_status, host_mmio + hotplug_offset); + readl(host_mmio + hotplug_offset); /* flush */ +} + static void pdc_common_error_handler(struct ata_port *ap, ata_reset_fn_t hardreset) { if (!(ap->pflags & ATA_PFLAG_FROZEN)) @@ -765,19 +845,6 @@ static void pdc_irq_clear(struct ata_port *ap) readl(mmio + PDC_INT_SEQMASK); } -static int pdc_is_sataii_tx4(unsigned long flags) -{ - const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; - return (flags & mask) == mask; -} - -static unsigned int pdc_port_no_to_ata_no(unsigned int port_no, - int is_sataii_tx4) -{ - static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; - return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; -} - static irqreturn_t pdc_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; @@ -799,6 +866,8 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance) mmio_base = host->iomap[PDC_MMIO_BAR]; + spin_lock(&host->lock); + /* read and clear hotplug flags for all ports */ if (host->ports[0]->flags & PDC_FLAG_GEN_II) hotplug_offset = PDC2_SATA_PLUG_CSR; @@ -814,11 +883,9 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance) if (mask == 0xffffffff && hotplug_status == 0) { VPRINTK("QUICK EXIT 2\n"); - return IRQ_NONE; + goto done_irq; } - spin_lock(&host->lock); - mask &= 0xffff; /* only 16 tags possible */ if (mask == 0 && hotplug_status == 0) { VPRINTK("QUICK EXIT 3\n"); diff --git a/drivers/base/core.c b/drivers/base/core.c index 7de543d1d0b4..24198ad01976 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -19,6 +19,7 @@ #include <linux/kdev_t.h> #include <linux/notifier.h> #include <linux/genhd.h> +#include <linux/kallsyms.h> #include <asm/semaphore.h> #include "base.h" @@ -68,6 +69,10 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, if (dev_attr->show) ret = dev_attr->show(dev, dev_attr, buf); + if (ret >= (ssize_t)PAGE_SIZE) { + print_symbol("dev_attr_show: %s returned bad count\n", + (unsigned long)dev_attr->show); + } return ret; } diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 6bbd4fa50f3b..8d6c2089d2a8 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -9,7 +9,14 @@ config HW_RANDOM Hardware Random Number Generator Core infrastructure. To compile this driver as a module, choose M here: the - module will be called rng-core. + module will be called rng-core. This provides a device + that's usually called /dev/hw_random, and which exposes one + of possibly several hardware random number generators. + + These hardware random number generators do not feed directly + into the kernel's random number generator. That is usually + handled by the "rngd" daemon. Documentation/hw_random.txt + has more information. If unsure, say Y. diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d73663a52324..fc555a90bb21 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -67,7 +67,7 @@ static void cpuidle_idle_call(void) /* enter the state and update stats */ dev->last_residency = target_state->enter(dev, target_state); dev->last_state = target_state; - target_state->time += dev->last_residency; + target_state->time += (unsigned long long)dev->last_residency; target_state->usage++; /* give the governor an opportunity to reflect on the outcome */ @@ -224,7 +224,7 @@ static void poll_idle_init(struct cpuidle_device *dev) state->exit_latency = 0; state->target_residency = 0; state->power_usage = -1; - state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID; + state->flags = CPUIDLE_FLAG_POLL; state->enter = poll_idle; } #else diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 69102ca05685..e949618b9be0 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -218,6 +218,12 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ return sprintf(buf, "%u\n", state->_name);\ } +#define define_show_state_ull_function(_name) \ +static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ +{ \ + return sprintf(buf, "%llu\n", state->_name);\ +} + #define define_show_state_str_function(_name) \ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ { \ @@ -228,8 +234,8 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ define_show_state_function(exit_latency) define_show_state_function(power_usage) -define_show_state_function(usage) -define_show_state_function(time) +define_show_state_ull_function(usage) +define_show_state_ull_function(time) define_show_state_str_function(name) define_show_state_str_function(desc) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 476b0bb72d6c..5fa9c3c67e0c 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -100,7 +100,7 @@ config I2C_AU1550 config I2C_BLACKFIN_TWI tristate "Blackfin TWI I2C support" - depends on BF534 || BF536 || BF537 || BF54x + depends on BF534 || BF536 || BF537 help This is the TWI I2C device driver for Blackfin 534/536/537/54x. This driver can also be built as a module. If so, the module diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index da6639707ea3..7ba31770d773 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -128,6 +128,8 @@ struct omap_i2c_dev { size_t buf_len; struct i2c_adapter adapter; unsigned rev1:1; + unsigned idle:1; + u16 iestate; /* Saved interrupt register */ }; static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, @@ -174,18 +176,30 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev) } } -static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev) +static void omap_i2c_unidle(struct omap_i2c_dev *dev) { if (dev->iclk != NULL) clk_enable(dev->iclk); clk_enable(dev->fclk); + if (dev->iestate) + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); + dev->idle = 0; } -static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev) +static void omap_i2c_idle(struct omap_i2c_dev *dev) { + u16 iv; + + dev->idle = 1; + dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); + if (dev->rev1) + iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ + else + omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); + clk_disable(dev->fclk); if (dev->iclk != NULL) clk_disable(dev->iclk); - clk_disable(dev->fclk); } static int omap_i2c_init(struct omap_i2c_dev *dev) @@ -360,7 +374,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) int i; int r; - omap_i2c_enable_clocks(dev); + omap_i2c_unidle(dev); if ((r = omap_i2c_wait_for_bb(dev)) < 0) goto out; @@ -374,7 +388,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (r == 0) r = num; out: - omap_i2c_disable_clocks(dev); + omap_i2c_idle(dev); return r; } @@ -403,6 +417,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id) struct omap_i2c_dev *dev = dev_id; u16 iv, w; + if (dev->idle) + return IRQ_NONE; + iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); switch (iv) { case 0x00: /* None */ @@ -457,6 +474,9 @@ omap_i2c_isr(int this_irq, void *dev_id) u16 stat, w; int count = 0; + if (dev->idle) + return IRQ_NONE; + bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) { dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat); @@ -575,7 +595,7 @@ omap_i2c_probe(struct platform_device *pdev) if ((r = omap_i2c_get_clocks(dev)) != 0) goto err_free_mem; - omap_i2c_enable_clocks(dev); + omap_i2c_unidle(dev); if (cpu_is_omap15xx()) dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20; @@ -610,7 +630,7 @@ omap_i2c_probe(struct platform_device *pdev) goto err_free_irq; } - omap_i2c_disable_clocks(dev); + omap_i2c_idle(dev); return 0; @@ -618,7 +638,7 @@ err_free_irq: free_irq(dev->irq, dev); err_unuse_clocks: omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); - omap_i2c_disable_clocks(dev); + omap_i2c_idle(dev); omap_i2c_put_clocks(dev); err_free_mem: platform_set_drvdata(pdev, NULL); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index fd84b2a36338..8b645c6b2cb5 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -489,8 +489,8 @@ EXPORT_SYMBOL(i2c_add_adapter); * Context: can sleep * * This routine is used to declare an I2C adapter when its bus number - * matters. Example: for I2C adapters from system-on-chip CPUs, or - * otherwise built in to the system's mainboard, and where i2c_board_info + * matters. For example, use it for I2C adapters from system-on-chip CPUs, + * or otherwise built in to the system's mainboard, and where i2c_board_info * is used to properly configure I2C devices. * * If no devices have pre-been declared for this bus, then be sure to diff --git a/drivers/lguest/Makefile b/drivers/lguest/Makefile index 5e8272d296d8..7d463c26124f 100644 --- a/drivers/lguest/Makefile +++ b/drivers/lguest/Makefile @@ -19,3 +19,11 @@ Beer: @for f in Preparation Guest Drivers Launcher Host Switcher Mastery; do echo "{==- $$f -==}"; make -s $$f; done; echo "{==-==}" Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery: @sh ../../Documentation/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'` +Puppy: + @clear + @printf " __ \n (___()'\`;\n /, /\`\n \\\\\\\"--\\\\\\ \n" + @sleep 2; clear; printf "\n\n Sit!\n\n"; sleep 1; clear + @printf " __ \n ()'\`; \n /\\|\` \n / | \n(/_)_|_ \n" + @sleep 2; clear; printf "\n\n Stand!\n\n"; sleep 1; clear + @printf " __ \n ()'\`; \n /\\|\` \n /._.= \n /| / \n(_\_)_ \n" + @sleep 2; clear; printf "\n\n Good puppy!\n\n"; sleep 1; clear diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index c632c08cbbdc..5eea4356d703 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c @@ -1,8 +1,6 @@ /*P:400 This contains run_guest() which actually calls into the Host<->Guest * Switcher and analyzes the return, such as determining if the Guest wants the - * Host to do something. This file also contains useful helper routines, and a - * couple of non-obvious setup and teardown pieces which were implemented after - * days of debugging pain. :*/ + * Host to do something. This file also contains useful helper routines. :*/ #include <linux/module.h> #include <linux/stringify.h> #include <linux/stddef.h> @@ -49,8 +47,8 @@ static __init int map_switcher(void) * easy. */ - /* We allocate an array of "struct page"s. map_vm_area() wants the - * pages in this form, rather than just an array of pointers. */ + /* We allocate an array of struct page pointers. map_vm_area() wants + * this, rather than just an array of pages. */ switcher_page = kmalloc(sizeof(switcher_page[0])*TOTAL_SWITCHER_PAGES, GFP_KERNEL); if (!switcher_page) { @@ -172,7 +170,7 @@ void __lgread(struct lg_cpu *cpu, void *b, unsigned long addr, unsigned bytes) } } -/* This is the write (copy into guest) version. */ +/* This is the write (copy into Guest) version. */ void __lgwrite(struct lg_cpu *cpu, unsigned long addr, const void *b, unsigned bytes) { @@ -209,9 +207,9 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user) if (cpu->break_out) return -EAGAIN; - /* Check if there are any interrupts which can be delivered - * now: if so, this sets up the hander to be executed when we - * next run the Guest. */ + /* Check if there are any interrupts which can be delivered now: + * if so, this sets up the hander to be executed when we next + * run the Guest. */ maybe_do_interrupt(cpu); /* All long-lived kernel loops need to check with this horrible @@ -246,8 +244,10 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user) lguest_arch_handle_trap(cpu); } + /* Special case: Guest is 'dead' but wants a reboot. */ if (cpu->lg->dead == ERR_PTR(-ERESTART)) return -ERESTART; + /* The Guest is dead => "No such file or directory" */ return -ENOENT; } diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 0f2cb4fd7c69..54d66f05fefa 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c @@ -29,7 +29,7 @@ #include "lg.h" /*H:120 This is the core hypercall routine: where the Guest gets what it wants. - * Or gets killed. Or, in the case of LHCALL_CRASH, both. */ + * Or gets killed. Or, in the case of LHCALL_SHUTDOWN, both. */ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args) { switch (args->arg0) { @@ -190,6 +190,13 @@ static void initialize(struct lg_cpu *cpu) * pagetable. */ guest_pagetable_clear_all(cpu); } +/*:*/ + +/*M:013 If a Guest reads from a page (so creates a mapping) that it has never + * written to, and then the Launcher writes to it (ie. the output of a virtual + * device), the Guest will still see the old page. In practice, this never + * happens: why would the Guest read a page which it has never written to? But + * a similar scenario might one day bite us, so it's worth mentioning. :*/ /*H:100 * Hypercalls @@ -227,7 +234,7 @@ void do_hypercalls(struct lg_cpu *cpu) * However, if we are signalled or the Guest sends I/O to the * Launcher, the run_guest() loop will exit without running the * Guest. When it comes back it would try to re-run the - * hypercall. */ + * hypercall. Finding that bug sucked. */ cpu->hcall = NULL; } } diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 32e97c1858e5..0414ddf87587 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -144,7 +144,6 @@ void maybe_do_interrupt(struct lg_cpu *cpu) if (copy_from_user(&blk, cpu->lg->lguest_data->blocked_interrupts, sizeof(blk))) return; - bitmap_andnot(blk, cpu->irqs_pending, blk, LGUEST_IRQS); /* Find the first interrupt. */ @@ -237,9 +236,9 @@ void free_interrupts(void) clear_bit(syscall_vector, used_vectors); } -/*H:220 Now we've got the routines to deliver interrupts, delivering traps - * like page fault is easy. The only trick is that Intel decided that some - * traps should have error codes: */ +/*H:220 Now we've got the routines to deliver interrupts, delivering traps like + * page fault is easy. The only trick is that Intel decided that some traps + * should have error codes: */ static int has_err(unsigned int trap) { return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17); diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 1b2ec0bf5eb1..2bc9bf7e88e5 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -1,10 +1,10 @@ /*P:050 Lguest guests use a very simple method to describe devices. It's a - * series of device descriptors contained just above the top of normal + * series of device descriptors contained just above the top of normal Guest * memory. * * We use the standard "virtio" device infrastructure, which provides us with a * console, a network and a block driver. Each one expects some configuration - * information and a "virtqueue" mechanism to send and receive data. :*/ + * information and a "virtqueue" or two to send and receive data. :*/ #include <linux/init.h> #include <linux/bootmem.h> #include <linux/lguest_launcher.h> @@ -53,7 +53,7 @@ struct lguest_device { * Device configurations * * The configuration information for a device consists of one or more - * virtqueues, a feature bitmaks, and some configuration bytes. The + * virtqueues, a feature bitmap, and some configuration bytes. The * configuration bytes don't really matter to us: the Launcher sets them up, and * the driver will look at them during setup. * @@ -179,7 +179,7 @@ struct lguest_vq_info }; /* When the virtio_ring code wants to prod the Host, it calls us here and we - * make a hypercall. We hand the page number of the virtqueue so the Host + * make a hypercall. We hand the physical address of the virtqueue so the Host * knows which virtqueue we're talking about. */ static void lg_notify(struct virtqueue *vq) { @@ -199,7 +199,8 @@ static void lg_notify(struct virtqueue *vq) * allocate its own pages and tell the Host where they are, but for lguest it's * simpler for the Host to simply tell us where the pages are. * - * So we provide devices with a "find virtqueue and set it up" function. */ + * So we provide drivers with a "find the Nth virtqueue and set it up" + * function. */ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, unsigned index, void (*callback)(struct virtqueue *vq)) diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 2221485b0773..564e425d71dd 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -73,7 +73,7 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) if (current != cpu->tsk) return -EPERM; - /* If the guest is already dead, we indicate why */ + /* If the Guest is already dead, we indicate why */ if (lg->dead) { size_t len; @@ -88,7 +88,7 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) return len; } - /* If we returned from read() last time because the Guest notified, + /* If we returned from read() last time because the Guest sent I/O, * clear the flag. */ if (cpu->pending_notify) cpu->pending_notify = 0; @@ -97,14 +97,20 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) return run_guest(cpu, (unsigned long __user *)user); } +/*L:025 This actually initializes a CPU. For the moment, a Guest is only + * uniprocessor, so "id" is always 0. */ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) { + /* We have a limited number the number of CPUs in the lguest struct. */ if (id >= NR_CPUS) return -EINVAL; + /* Set up this CPU's id, and pointer back to the lguest struct. */ cpu->id = id; cpu->lg = container_of((cpu - id), struct lguest, cpus[0]); cpu->lg->nr_cpus++; + + /* Each CPU has a timer it can set. */ init_clockdev(cpu); /* We need a complete page for the Guest registers: they are accessible @@ -120,11 +126,11 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) * address. */ lguest_arch_setup_regs(cpu, start_ip); - /* Initialize the queue for the waker to wait on */ + /* Initialize the queue for the Waker to wait on */ init_waitqueue_head(&cpu->break_wq); /* We keep a pointer to the Launcher task (ie. current task) for when - * other Guests want to wake this one (inter-Guest I/O). */ + * other Guests want to wake this one (eg. console input). */ cpu->tsk = current; /* We need to keep a pointer to the Launcher's memory map, because if @@ -136,6 +142,7 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) * when the same Guest runs on the same CPU twice. */ cpu->last_pages = NULL; + /* No error == success. */ return 0; } @@ -185,14 +192,13 @@ static int initialize(struct file *file, const unsigned long __user *input) lg->mem_base = (void __user *)(long)args[0]; lg->pfn_limit = args[1]; - /* This is the first cpu */ + /* This is the first cpu (cpu 0) and it will start booting at args[3] */ err = lg_cpu_start(&lg->cpus[0], 0, args[3]); if (err) goto release_guest; /* Initialize the Guest's shadow page tables, using the toplevel - * address the Launcher gave us. This allocates memory, so can - * fail. */ + * address the Launcher gave us. This allocates memory, so can fail. */ err = init_guest_pagetable(lg, args[2]); if (err) goto free_regs; @@ -218,11 +224,16 @@ unlock: /*L:010 The first operation the Launcher does must be a write. All writes * start with an unsigned long number: for the first write this must be * LHREQ_INITIALIZE to set up the Guest. After that the Launcher can use - * writes of other values to send interrupts. */ + * writes of other values to send interrupts. + * + * Note that we overload the "offset" in the /dev/lguest file to indicate what + * CPU number we're dealing with. Currently this is always 0, since we only + * support uniprocessor Guests, but you can see the beginnings of SMP support + * here. */ static ssize_t write(struct file *file, const char __user *in, size_t size, loff_t *off) { - /* Once the guest is initialized, we hold the "struct lguest" in the + /* Once the Guest is initialized, we hold the "struct lguest" in the * file private data. */ struct lguest *lg = file->private_data; const unsigned long __user *input = (const unsigned long __user *)in; @@ -230,6 +241,7 @@ static ssize_t write(struct file *file, const char __user *in, struct lg_cpu *uninitialized_var(cpu); unsigned int cpu_id = *off; + /* The first value tells us what this request is. */ if (get_user(req, input) != 0) return -EFAULT; input++; diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index a7f64a9d67e0..d93500f24fbb 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -2,8 +2,8 @@ * previous encounters. It's functional, and as neat as it can be in the * circumstances, but be wary, for these things are subtle and break easily. * The Guest provides a virtual to physical mapping, but we can neither trust - * it nor use it: we verify and convert it here to point the hardware to the - * actual Guest pages when running the Guest. :*/ + * it nor use it: we verify and convert it here then point the CPU to the + * converted Guest pages when running the Guest. :*/ /* Copyright (C) Rusty Russell IBM Corporation 2006. * GPL v2 and any later version */ @@ -106,6 +106,11 @@ static unsigned long gpte_addr(pgd_t gpgd, unsigned long vaddr) BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT)); return gpage + ((vaddr>>PAGE_SHIFT) % PTRS_PER_PTE) * sizeof(pte_t); } +/*:*/ + +/*M:014 get_pfn is slow; it takes the mmap sem and calls get_user_pages. We + * could probably try to grab batches of pages here as an optimization + * (ie. pre-faulting). :*/ /*H:350 This routine takes a page number given by the Guest and converts it to * an actual, physical page number. It can fail for several reasons: the @@ -113,8 +118,8 @@ static unsigned long gpte_addr(pgd_t gpgd, unsigned long vaddr) * and the page is read-only, or the write flag was set and the page was * shared so had to be copied, but we ran out of memory. * - * This holds a reference to the page, so release_pte() is careful to - * put that back. */ + * This holds a reference to the page, so release_pte() is careful to put that + * back. */ static unsigned long get_pfn(unsigned long virtpfn, int write) { struct page *page; @@ -532,13 +537,13 @@ static void do_set_pte(struct lg_cpu *cpu, int idx, * all processes. So when the page table above that address changes, we update * all the page tables, not just the current one. This is rare. * - * The benefit is that when we have to track a new page table, we can copy keep - * all the kernel mappings. This speeds up context switch immensely. */ + * The benefit is that when we have to track a new page table, we can keep all + * the kernel mappings. This speeds up context switch immensely. */ void guest_set_pte(struct lg_cpu *cpu, unsigned long gpgdir, unsigned long vaddr, pte_t gpte) { - /* Kernel mappings must be changed on all top levels. Slow, but - * doesn't happen often. */ + /* Kernel mappings must be changed on all top levels. Slow, but doesn't + * happen often. */ if (vaddr >= cpu->lg->kernel_address) { unsigned int i; for (i = 0; i < ARRAY_SIZE(cpu->lg->pgdirs); i++) @@ -704,12 +709,11 @@ static __init void populate_switcher_pte_page(unsigned int cpu, /* We've made it through the page table code. Perhaps our tired brains are * still processing the details, or perhaps we're simply glad it's over. * - * If nothing else, note that all this complexity in juggling shadow page - * tables in sync with the Guest's page tables is for one reason: for most - * Guests this page table dance determines how bad performance will be. This - * is why Xen uses exotic direct Guest pagetable manipulation, and why both - * Intel and AMD have implemented shadow page table support directly into - * hardware. + * If nothing else, note that all this complexity in juggling shadow page tables + * in sync with the Guest's page tables is for one reason: for most Guests this + * page table dance determines how bad performance will be. This is why Xen + * uses exotic direct Guest pagetable manipulation, and why both Intel and AMD + * have implemented shadow page table support directly into hardware. * * There is just one file remaining in the Host. */ diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 635187812d52..5126d5d9ea0e 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -17,6 +17,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/*P:450 This file contains the x86-specific lguest code. It used to be all + * mixed in with drivers/lguest/core.c but several foolhardy code slashers + * wrestled most of the dependencies out to here in preparation for porting + * lguest to other architectures (see what I mean by foolhardy?). + * + * This also contains a couple of non-obvious setup and teardown pieces which + * were implemented after days of debugging pain. :*/ #include <linux/kernel.h> #include <linux/start_kernel.h> #include <linux/string.h> @@ -157,6 +164,8 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) * also simplify copy_in_guest_info(). Note that we'd still need to restore * things when we exit to Launcher userspace, but that's fairly easy. * + * We could also try using this hooks for PGE, but that might be too expensive. + * * The hooks were designed for KVM, but we can also put them to good use. :*/ /*H:040 This is the i386-specific code to setup and run the Guest. Interrupts @@ -182,7 +191,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) * was doing. */ run_guest_once(cpu, lguest_pages(raw_smp_processor_id())); - /* Note that the "regs" pointer contains two extra entries which are + /* Note that the "regs" structure contains two extra entries which are * not really registers: a trap number which says what interrupt or * trap made the switcher code come back, and an error code which some * traps set. */ @@ -293,11 +302,10 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) break; case 14: /* We've intercepted a Page Fault. */ /* The Guest accessed a virtual address that wasn't mapped. - * This happens a lot: we don't actually set up most of the - * page tables for the Guest at all when we start: as it runs - * it asks for more and more, and we set them up as - * required. In this case, we don't even tell the Guest that - * the fault happened. + * This happens a lot: we don't actually set up most of the page + * tables for the Guest at all when we start: as it runs it asks + * for more and more, and we set them up as required. In this + * case, we don't even tell the Guest that the fault happened. * * The errcode tells whether this was a read or a write, and * whether kernel or userspace code. */ @@ -342,7 +350,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) if (!deliver_trap(cpu, cpu->regs->trapnum)) /* If the Guest doesn't have a handler (either it hasn't * registered any yet, or it's one of the faults we don't let - * it handle), it dies with a cryptic error message. */ + * it handle), it dies with this cryptic error message. */ kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)", cpu->regs->trapnum, cpu->regs->eip, cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault @@ -375,8 +383,8 @@ void __init lguest_arch_host_init(void) * The only exception is the interrupt handlers in switcher.S: their * addresses are placed in a table (default_idt_entries), so we need to * update the table with the new addresses. switcher_offset() is a - * convenience function which returns the distance between the builtin - * switcher code and the high-mapped copy we just made. */ + * convenience function which returns the distance between the + * compiled-in switcher code and the high-mapped copy we just made. */ for (i = 0; i < IDT_ENTRIES; i++) default_idt_entries[i] += switcher_offset(); @@ -416,7 +424,7 @@ void __init lguest_arch_host_init(void) state->guest_gdt_desc.address = (long)&state->guest_gdt; /* We know where we want the stack to be when the Guest enters - * the switcher: in pages->regs. The stack grows upwards, so + * the Switcher: in pages->regs. The stack grows upwards, so * we start it at the end of that structure. */ state->guest_tss.sp0 = (long)(&pages->regs + 1); /* And this is the GDT entry to use for the stack: we keep a @@ -513,8 +521,8 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu) { u32 tsc_speed; - /* The pointer to the Guest's "struct lguest_data" is the only - * argument. We check that address now. */ + /* The pointer to the Guest's "struct lguest_data" is the only argument. + * We check that address now. */ if (!lguest_address_ok(cpu->lg, cpu->hcall->arg1, sizeof(*cpu->lg->lguest_data))) return -EFAULT; @@ -546,6 +554,7 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu) return 0; } +/*:*/ /*L:030 lguest_arch_setup_regs() * diff --git a/drivers/lguest/x86/switcher_32.S b/drivers/lguest/x86/switcher_32.S index 0af8baaa0d4a..3fc15318a80f 100644 --- a/drivers/lguest/x86/switcher_32.S +++ b/drivers/lguest/x86/switcher_32.S @@ -1,6 +1,6 @@ -/*P:900 This is the Switcher: code which sits at 0xFFC00000 to do the low-level - * Guest<->Host switch. It is as simple as it can be made, but it's naturally - * very specific to x86. +/*P:900 This is the Switcher: code which sits at 0xFFC00000 astride both the + * Host and Guest to do the low-level Guest<->Host switch. It is as simple as + * it can be made, but it's naturally very specific to x86. * * You have now completed Preparation. If this has whet your appetite; if you * are feeling invigorated and refreshed then the next, more challenging stage @@ -189,7 +189,7 @@ ENTRY(switch_to_guest) // Interrupts are turned back on: we are Guest. iret -// We treat two paths to switch back to the Host +// We tread two paths to switch back to the Host // Yet both must save Guest state and restore Host // So we put the routine in a macro. #define SWITCH_TO_HOST \ diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index eeaaa9dce6ef..ad1880c67518 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -408,7 +408,6 @@ static int block2mtd_setup2(const char *val) if (token[1]) { ret = parse_num(&erase_size, token[1]); if (ret) { - kfree(name); parse_err("illegal erase size"); } } diff --git a/drivers/net/b44.c b/drivers/net/b44.c index ea2a2b548e3c..25f1337cd02c 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -2082,6 +2082,11 @@ static int __devinit b44_get_invariants(struct b44 *bp) addr = sdev->bus->sprom.et0mac; bp->phy_addr = sdev->bus->sprom.et0phyaddr; } + /* Some ROMs have buggy PHY addresses with the high + * bits set (sign extension?). Truncate them to a + * valid PHY address. */ + bp->phy_addr &= 0x1F; + memcpy(bp->dev->dev_addr, addr, 6); if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){ diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index cb3c6faa7888..d16e0e1d2b30 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -310,7 +310,7 @@ static inline int __check_agg_selection_timer(struct port *port) */ static inline void __get_rx_machine_lock(struct port *port) { - spin_lock(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); + spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); } /** @@ -320,7 +320,7 @@ static inline void __get_rx_machine_lock(struct port *port) */ static inline void __release_rx_machine_lock(struct port *port) { - spin_unlock(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); + spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); } /** diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index b57bc9467dbe..3f58c3d0b710 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -678,12 +678,8 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon } if (!list_empty(&bond->vlan_list)) { - unsigned short vlan_id; - int res = vlan_get_tag(skb, &vlan_id); - if (!res) { + if (!vlan_get_tag(skb, &client_info->vlan_id)) client_info->tag = 1; - client_info->vlan_id = vlan_id; - } } if (!client_info->assigned) { diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 0942d82f7cbf..0f0675319e9c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -383,7 +383,7 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) */ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev) { - unsigned short vlan_id; + unsigned short uninitialized_var(vlan_id); if (!list_empty(&bond->vlan_list) && !(slave_dev->features & NETIF_F_HW_VLAN_TX) && @@ -4528,8 +4528,7 @@ static void bond_free_all(void) netif_tx_unlock_bh(bond_dev); /* Release the bonded slaves */ bond_release_all(bond_dev); - bond_deinit(bond_dev); - unregister_netdevice(bond_dev); + bond_destroy(bond); } #ifdef CONFIG_PROC_FS diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 67ccad69d445..a3c74e20aa53 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.2.4" -#define DRV_RELDATE "January 28, 2008" +#define DRV_VERSION "3.2.5" +#define DRV_RELDATE "March 21, 2008" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index db586870c5f4..98a6bbd11d4c 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -557,9 +557,9 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q) for (i = 0; i < SGE_RXQ_PER_SET; ++i) if (q->fl[i].desc) { - spin_lock(&adapter->sge.reg_lock); + spin_lock_irq(&adapter->sge.reg_lock); t3_sge_disable_fl(adapter, q->fl[i].cntxt_id); - spin_unlock(&adapter->sge.reg_lock); + spin_unlock_irq(&adapter->sge.reg_lock); free_rx_bufs(pdev, &q->fl[i]); kfree(q->fl[i].sdesc); dma_free_coherent(&pdev->dev, @@ -570,9 +570,9 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q) for (i = 0; i < SGE_TXQ_PER_SET; ++i) if (q->txq[i].desc) { - spin_lock(&adapter->sge.reg_lock); + spin_lock_irq(&adapter->sge.reg_lock); t3_sge_enable_ecntxt(adapter, q->txq[i].cntxt_id, 0); - spin_unlock(&adapter->sge.reg_lock); + spin_unlock_irq(&adapter->sge.reg_lock); if (q->txq[i].sdesc) { free_tx_desc(adapter, &q->txq[i], q->txq[i].in_use); @@ -586,9 +586,9 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q) } if (q->rspq.desc) { - spin_lock(&adapter->sge.reg_lock); + spin_lock_irq(&adapter->sge.reg_lock); t3_sge_disable_rspcntxt(adapter, q->rspq.cntxt_id); - spin_unlock(&adapter->sge.reg_lock); + spin_unlock_irq(&adapter->sge.reg_lock); dma_free_coherent(&pdev->dev, q->rspq.size * sizeof(struct rsp_desc), q->rspq.desc, q->rspq.phys_addr); @@ -2667,7 +2667,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt); - spin_lock(&adapter->sge.reg_lock); + spin_lock_irq(&adapter->sge.reg_lock); /* FL threshold comparison uses < */ ret = t3_sge_init_rspcntxt(adapter, q->rspq.cntxt_id, irq_vec_idx, @@ -2711,7 +2711,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, goto err_unlock; } - spin_unlock(&adapter->sge.reg_lock); + spin_unlock_irq(&adapter->sge.reg_lock); q->adap = adapter; q->netdev = dev; @@ -2728,7 +2728,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, return 0; err_unlock: - spin_unlock(&adapter->sge.reg_lock); + spin_unlock_irq(&adapter->sge.reg_lock); err: t3_free_qset(adapter, q); return ret; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 1fe305ca2cf0..b09a53de1c53 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -798,8 +798,6 @@ dm9000_init_dm9000(struct net_device *dev) /* Set address filter table */ dm9000_hash_table(dev); - /* Activate DM9000 */ - iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* Enable TX/RX interrupt mask */ iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); @@ -1197,6 +1195,7 @@ dm9000_hash_table(struct net_device *dev) int i, oft; u32 hash_val; u16 hash_table[4]; + u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN; unsigned long flags; dm9000_dbg(db, 1, "entering %s\n", __func__); @@ -1213,6 +1212,12 @@ dm9000_hash_table(struct net_device *dev) /* broadcast address */ hash_table[3] = 0x8000; + if (dev->flags & IFF_PROMISC) + rcr |= RCR_PRMSC; + + if (dev->flags & IFF_ALLMULTI) + rcr |= RCR_ALL; + /* the multicast address in Hash Table : 64 bits */ for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f; @@ -1225,6 +1230,7 @@ dm9000_hash_table(struct net_device *dev) iow(db, oft++, hash_table[i] >> 8); } + iow(db, DM9000_RCR, rcr); spin_unlock_irqrestore(&db->lock, flags); } diff --git a/drivers/net/e100.c b/drivers/net/e100.c index cdf3090a1885..2d139ec79777 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -960,7 +960,7 @@ static void e100_get_defaults(struct nic *nic) /* Template for a freshly allocated RFD */ nic->blank_rfd.command = 0; - nic->blank_rfd.rbd = 0xFFFFFFFF; + nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); /* MII setup */ diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 7c4ead35cfa2..93b7fb246960 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0087" +#define DRV_VERSION "EHEA_0089" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 21af674b764e..07c742dd3f09 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3108,7 +3108,7 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, dev->vlan_rx_add_vid = ehea_vlan_rx_add_vid; dev->vlan_rx_kill_vid = ehea_vlan_rx_kill_vid; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO - | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX + | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER | NETIF_F_LLTX; dev->tx_timeout = &ehea_tx_watchdog; diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index 6604d96bd567..76ea846663db 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -61,28 +61,28 @@ /* Receive Descriptor - Advanced */ union e1000_adv_rx_desc { struct { - u64 pkt_addr; /* Packet buffer address */ - u64 hdr_addr; /* Header buffer address */ + __le64 pkt_addr; /* Packet buffer address */ + __le64 hdr_addr; /* Header buffer address */ } read; struct { struct { struct { - u16 pkt_info; /* RSS type, Packet type */ - u16 hdr_info; /* Split Header, - * header buffer length */ + __le16 pkt_info; /* RSS type, Packet type */ + __le16 hdr_info; /* Split Header, + * header buffer length */ } lo_dword; union { - u32 rss; /* RSS Hash */ + __le32 rss; /* RSS Hash */ struct { - u16 ip_id; /* IP id */ - u16 csum; /* Packet Checksum */ + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { - u32 status_error; /* ext status/error */ - u16 length; /* Packet length */ - u16 vlan; /* VLAN tag */ + __le32 status_error; /* ext status/error */ + __le16 length; /* Packet length */ + __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; @@ -97,14 +97,14 @@ union e1000_adv_rx_desc { /* Transmit Descriptor - Advanced */ union e1000_adv_tx_desc { struct { - u64 buffer_addr; /* Address of descriptor's data buf */ - u32 cmd_type_len; - u32 olinfo_status; + __le64 buffer_addr; /* Address of descriptor's data buf */ + __le32 cmd_type_len; + __le32 olinfo_status; } read; struct { - u64 rsvd; /* Reserved */ - u32 nxtseq_seed; - u32 status; + __le64 rsvd; /* Reserved */ + __le32 nxtseq_seed; + __le32 status; } wb; }; @@ -119,10 +119,10 @@ union e1000_adv_tx_desc { /* Context descriptors */ struct e1000_adv_tx_context_desc { - u32 vlan_macip_lens; - u32 seqnum_seed; - u32 type_tucmd_mlhl; - u32 mss_l4len_idx; + __le32 vlan_macip_lens; + __le32 seqnum_seed; + __le32 type_tucmd_mlhl; + __le32 mss_l4len_idx; }; #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 161fb68764af..7b2c70a3b8cc 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -143,35 +143,35 @@ enum e1000_fc_type { /* Receive Descriptor */ struct e1000_rx_desc { - u64 buffer_addr; /* Address of the descriptor's data buffer */ - u16 length; /* Length of data DMAed into data buffer */ - u16 csum; /* Packet checksum */ + __le64 buffer_addr; /* Address of the descriptor's data buffer */ + __le16 length; /* Length of data DMAed into data buffer */ + __le16 csum; /* Packet checksum */ u8 status; /* Descriptor status */ u8 errors; /* Descriptor Errors */ - u16 special; + __le16 special; }; /* Receive Descriptor - Extended */ union e1000_rx_desc_extended { struct { - u64 buffer_addr; - u64 reserved; + __le64 buffer_addr; + __le64 reserved; } read; struct { struct { - u32 mrq; /* Multiple Rx Queues */ + __le32 mrq; /* Multiple Rx Queues */ union { - u32 rss; /* RSS Hash */ + __le32 rss; /* RSS Hash */ struct { - u16 ip_id; /* IP id */ - u16 csum; /* Packet Checksum */ + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { - u32 status_error; /* ext status/error */ - u16 length; - u16 vlan; /* VLAN tag */ + __le32 status_error; /* ext status/error */ + __le16 length; + __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; @@ -181,49 +181,49 @@ union e1000_rx_desc_extended { union e1000_rx_desc_packet_split { struct { /* one buffer for protocol header(s), three data buffers */ - u64 buffer_addr[MAX_PS_BUFFERS]; + __le64 buffer_addr[MAX_PS_BUFFERS]; } read; struct { struct { - u32 mrq; /* Multiple Rx Queues */ + __le32 mrq; /* Multiple Rx Queues */ union { - u32 rss; /* RSS Hash */ + __le32 rss; /* RSS Hash */ struct { - u16 ip_id; /* IP id */ - u16 csum; /* Packet Checksum */ + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { - u32 status_error; /* ext status/error */ - u16 length0; /* length of buffer 0 */ - u16 vlan; /* VLAN tag */ + __le32 status_error; /* ext status/error */ + __le16 length0; /* length of buffer 0 */ + __le16 vlan; /* VLAN tag */ } middle; struct { - u16 header_status; - u16 length[3]; /* length of buffers 1-3 */ + __le16 header_status; + __le16 length[3]; /* length of buffers 1-3 */ } upper; - u64 reserved; + __le64 reserved; } wb; /* writeback */ }; /* Transmit Descriptor */ struct e1000_tx_desc { - u64 buffer_addr; /* Address of the descriptor's data buffer */ + __le64 buffer_addr; /* Address of the descriptor's data buffer */ union { - u32 data; + __le32 data; struct { - u16 length; /* Data buffer length */ + __le16 length; /* Data buffer length */ u8 cso; /* Checksum offset */ u8 cmd; /* Descriptor control */ } flags; } lower; union { - u32 data; + __le32 data; struct { u8 status; /* Descriptor status */ u8 css; /* Checksum start */ - u16 special; + __le16 special; } fields; } upper; }; @@ -231,49 +231,49 @@ struct e1000_tx_desc { /* Offload Context Descriptor */ struct e1000_context_desc { union { - u32 ip_config; + __le32 ip_config; struct { u8 ipcss; /* IP checksum start */ u8 ipcso; /* IP checksum offset */ - u16 ipcse; /* IP checksum end */ + __le16 ipcse; /* IP checksum end */ } ip_fields; } lower_setup; union { - u32 tcp_config; + __le32 tcp_config; struct { u8 tucss; /* TCP checksum start */ u8 tucso; /* TCP checksum offset */ - u16 tucse; /* TCP checksum end */ + __le16 tucse; /* TCP checksum end */ } tcp_fields; } upper_setup; - u32 cmd_and_length; + __le32 cmd_and_length; union { - u32 data; + __le32 data; struct { u8 status; /* Descriptor status */ u8 hdr_len; /* Header length */ - u16 mss; /* Maximum segment size */ + __le16 mss; /* Maximum segment size */ } fields; } tcp_seg_setup; }; /* Offload data descriptor */ struct e1000_data_desc { - u64 buffer_addr; /* Address of the descriptor's buffer address */ + __le64 buffer_addr; /* Address of the descriptor's buffer address */ union { - u32 data; + __le32 data; struct { - u16 length; /* Data buffer length */ + __le16 length; /* Data buffer length */ u8 typ_len_ext; u8 cmd; } flags; } lower; union { - u32 data; + __le32 data; struct { u8 status; /* Descriptor status */ u8 popts; /* Packet Options */ - u16 special; + __le16 special; } fields; } upper; }; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 928ce8287e69..aaee02e9e3f0 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3254,6 +3254,13 @@ quit_polling: return 1; } + +static inline u32 get_head(struct igb_ring *tx_ring) +{ + void *end = (struct e1000_tx_desc *)tx_ring->desc + tx_ring->count; + return le32_to_cpu(*(volatile __le32 *)end); +} + /** * igb_clean_tx_irq - Reclaim resources after transmit completes * @adapter: board private structure @@ -3275,9 +3282,7 @@ static bool igb_clean_tx_irq(struct igb_adapter *adapter, unsigned int total_bytes = 0, total_packets = 0; rmb(); - head = *(volatile u32 *)((struct e1000_tx_desc *)tx_ring->desc - + tx_ring->count); - head = le32_to_cpu(head); + head = get_head(tx_ring); i = tx_ring->next_to_clean; while (1) { while (i != head) { @@ -3312,9 +3317,7 @@ static bool igb_clean_tx_irq(struct igb_adapter *adapter, } oldhead = head; rmb(); - head = *(volatile u32 *)((struct e1000_tx_desc *)tx_ring->desc - + tx_ring->count); - head = le32_to_cpu(head); + head = get_head(tx_ring); if (head == oldhead) goto done_cleaning; } /* while (1) */ @@ -3388,7 +3391,7 @@ done_cleaning: * @vlan: descriptor vlan field as written by hardware (no le/be conversion) * @skb: pointer to sk_buff to be indicated to stack **/ -static void igb_receive_skb(struct igb_adapter *adapter, u8 status, u16 vlan, +static void igb_receive_skb(struct igb_adapter *adapter, u8 status, __le16 vlan, struct sk_buff *skb) { if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) @@ -3452,8 +3455,8 @@ static bool igb_clean_rx_irq_adv(struct igb_adapter *adapter, * that case, it fills the header buffer and spills the rest * into the page. */ - hlen = le16_to_cpu((rx_desc->wb.lower.lo_dword.hdr_info & - E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT); + hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & + E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; if (hlen > adapter->rx_ps_hdr_size) hlen = adapter->rx_ps_hdr_size; diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 269e6f805f47..6738b4d097fe 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -2088,14 +2088,12 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter) struct ixgb_buffer *buffer_info; struct sk_buff *skb; unsigned int i; - int num_group_tail_writes; long cleancount; i = rx_ring->next_to_use; buffer_info = &rx_ring->buffer_info[i]; cleancount = IXGB_DESC_UNUSED(rx_ring); - num_group_tail_writes = IXGB_RX_BUFFER_WRITE; /* leave three descriptors unused */ while(--cleancount > 2) { diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 2bc5eaae141f..7f20a03623a0 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -85,7 +85,7 @@ (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count) #define RCV_BUFFSIZE \ (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count) -#define find_diff_among(a,b,range) ((a)<=(b)?((b)-(a)):((b)+(range)-(a))) +#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) #define NETXEN_NETDEV_STATUS 0x1 #define NETXEN_RCV_PRODUCER_OFFSET 0 @@ -204,7 +204,7 @@ enum { ? RCV_DESC_LRO : \ (RCV_DESC_NORMAL))) -#define MAX_CMD_DESCRIPTORS 1024 +#define MAX_CMD_DESCRIPTORS 4096 #define MAX_RCV_DESCRIPTORS 16384 #define MAX_CMD_DESCRIPTORS_HOST (MAX_CMD_DESCRIPTORS / 4) #define MAX_RCV_DESCRIPTORS_1G (MAX_RCV_DESCRIPTORS / 4) @@ -818,15 +818,8 @@ struct netxen_adapter_stats { u64 badskblen; u64 nocmddescriptor; u64 polled; - u64 uphappy; - u64 updropped; - u64 uplcong; - u64 uphcong; - u64 upmcong; - u64 updunno; - u64 skbfreed; + u64 rxdropped; u64 txdropped; - u64 txnullskb; u64 csummed; u64 no_rcv; u64 rxbytes; @@ -842,7 +835,6 @@ struct netxen_rcv_desc_ctx { u32 flags; u32 producer; u32 rcv_pending; /* Num of bufs posted in phantom */ - u32 rcv_free; /* Num of bufs in free list */ dma_addr_t phys_addr; struct pci_dev *phys_pdev; struct rcv_desc *desc_head; /* address of rx ring in Phantom */ @@ -889,8 +881,6 @@ struct netxen_adapter { int mtu; int portnum; - spinlock_t tx_lock; - spinlock_t lock; struct work_struct watchdog_task; struct timer_list watchdog_timer; struct work_struct tx_timeout_task; @@ -899,16 +889,12 @@ struct netxen_adapter { u32 cmd_producer; __le32 *cmd_consumer; - u32 last_cmd_consumer; + u32 max_tx_desc_count; u32 max_rx_desc_count; u32 max_jumbo_rx_desc_count; u32 max_lro_rx_desc_count; - /* Num of instances active on cmd buffer ring */ - u32 proc_cmd_buf_counter; - - u32 num_threads, total_threads; /*Use to keep track of xmit threads */ u32 flags; u32 irq; @@ -942,6 +928,7 @@ struct netxen_adapter { struct pci_dev *ctx_desc_pdev; dma_addr_t ctx_desc_phys_addr; int intr_scheme; + int msi_mode; int (*enable_phy_interrupts) (struct netxen_adapter *); int (*disable_phy_interrupts) (struct netxen_adapter *); void (*handle_phy_intr) (struct netxen_adapter *); @@ -1075,12 +1062,10 @@ void netxen_tso_check(struct netxen_adapter *adapter, struct cmd_desc_type0 *desc, struct sk_buff *skb); int netxen_nic_hw_resources(struct netxen_adapter *adapter); void netxen_nic_clear_stats(struct netxen_adapter *adapter); -int netxen_nic_rx_has_work(struct netxen_adapter *adapter); -int netxen_nic_tx_has_work(struct netxen_adapter *adapter); void netxen_watchdog_task(struct work_struct *work); void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid); -int netxen_process_cmd_ring(unsigned long data); +int netxen_process_cmd_ring(struct netxen_adapter *adapter); u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); void netxen_nic_set_multi(struct net_device *netdev); int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 7a876f4b8db2..6e98d830eefb 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -64,15 +64,7 @@ static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = { {"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)}, {"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)}, {"polled", NETXEN_NIC_STAT(stats.polled)}, - {"uphappy", NETXEN_NIC_STAT(stats.uphappy)}, - {"updropped", NETXEN_NIC_STAT(stats.updropped)}, - {"uplcong", NETXEN_NIC_STAT(stats.uplcong)}, - {"uphcong", NETXEN_NIC_STAT(stats.uphcong)}, - {"upmcong", NETXEN_NIC_STAT(stats.upmcong)}, - {"updunno", NETXEN_NIC_STAT(stats.updunno)}, - {"skb_freed", NETXEN_NIC_STAT(stats.skbfreed)}, {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)}, - {"tx_null_skb", NETXEN_NIC_STAT(stats.txnullskb)}, {"csummed", NETXEN_NIC_STAT(stats.csummed)}, {"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)}, {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)}, diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index d72f8f8fcb50..160f605e58db 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -456,6 +456,12 @@ enum { #define ISR_INT_MASK_SLOW (NETXEN_PCIX_PS_REG(PCIX_INT_MASK)) #define ISR_INT_TARGET_STATUS (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS)) #define ISR_INT_TARGET_MASK (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK)) +#define ISR_INT_TARGET_STATUS_F1 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F1)) +#define ISR_INT_TARGET_MASK_F1 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F1)) +#define ISR_INT_TARGET_STATUS_F2 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F2)) +#define ISR_INT_TARGET_MASK_F2 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F2)) +#define ISR_INT_TARGET_STATUS_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F3)) +#define ISR_INT_TARGET_MASK_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F3)) #define NETXEN_PCI_MAPSIZE 128 #define NETXEN_PCI_DDR_NET (0x00000000UL) @@ -662,6 +668,12 @@ enum { #define PCIX_TARGET_STATUS (0x10118) #define PCIX_TARGET_MASK (0x10128) +#define PCIX_TARGET_STATUS_F1 (0x10160) +#define PCIX_TARGET_MASK_F1 (0x10170) +#define PCIX_TARGET_STATUS_F2 (0x10164) +#define PCIX_TARGET_MASK_F2 (0x10174) +#define PCIX_TARGET_STATUS_F3 (0x10168) +#define PCIX_TARGET_MASK_F3 (0x10178) #define PCIX_MSI_F0 (0x13000) #define PCIX_MSI_F1 (0x13004) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 01355701bf8e..05748ca6f216 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -398,6 +398,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW)); printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name, adapter->intr_scheme); + adapter->msi_mode = readl( + NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_FW)); DPRINTK(INFO, "Receive Peg ready too. starting stuff\n"); addr = netxen_alloc(adapter->ahw.pdev, diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 9e38bcb3fba9..45fa33e0cb90 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -145,6 +145,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter) /* Window 1 call */ writel(INTR_SCHEME_PERPORT, NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST)); + writel(MSI_MODE_MULTIFUNC, + NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_HOST)); writel(MPORT_MULTI_FUNCTION_MODE, NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE)); writel(PHAN_INITIALIZE_ACK, @@ -183,7 +185,6 @@ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter) for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { struct netxen_rx_buffer *rx_buf; rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring]; - rcv_desc->rcv_free = rcv_desc->max_rx_desc_count; rcv_desc->begin_alloc = 0; rx_buf = rcv_desc->rx_buf_arr; num_rx_bufs = rcv_desc->max_rx_desc_count; @@ -974,28 +975,6 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) return 0; } -int netxen_nic_rx_has_work(struct netxen_adapter *adapter) -{ - int ctx; - - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - struct netxen_recv_context *recv_ctx = - &(adapter->recv_ctx[ctx]); - u32 consumer; - struct status_desc *desc_head; - struct status_desc *desc; - - consumer = recv_ctx->status_rx_consumer; - desc_head = recv_ctx->rcv_status_desc_head; - desc = &desc_head[consumer]; - - if (netxen_get_sts_owner(desc) & STATUS_OWNER_HOST) - return 1; - } - - return 0; -} - static int netxen_nic_check_temp(struct netxen_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -1038,7 +1017,6 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) void netxen_watchdog_task(struct work_struct *work) { - struct net_device *netdev; struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, watchdog_task); @@ -1048,20 +1026,6 @@ void netxen_watchdog_task(struct work_struct *work) if (adapter->handle_phy_intr) adapter->handle_phy_intr(adapter); - netdev = adapter->netdev; - if ((netif_running(netdev)) && !netif_carrier_ok(netdev) && - netxen_nic_link_ok(adapter) ) { - printk(KERN_INFO "%s %s (port %d), Link is up\n", - netxen_nic_driver_name, netdev->name, adapter->portnum); - netif_carrier_on(netdev); - netif_wake_queue(netdev); - } else if(!(netif_running(netdev)) && netif_carrier_ok(netdev)) { - printk(KERN_ERR "%s %s Link is Down\n", - netxen_nic_driver_name, netdev->name); - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); } @@ -1125,7 +1089,7 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, skb = (struct sk_buff *)buffer->skb; if (likely(adapter->rx_csum && - netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) { + netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) { adapter->stats.csummed++; skb->ip_summed = CHECKSUM_UNNECESSARY; } else @@ -1142,40 +1106,8 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, skb->protocol = eth_type_trans(skb, netdev); ret = netif_receive_skb(skb); - - /* - * RH: Do we need these stats on a regular basis. Can we get it from - * Linux stats. - */ - switch (ret) { - case NET_RX_SUCCESS: - adapter->stats.uphappy++; - break; - - case NET_RX_CN_LOW: - adapter->stats.uplcong++; - break; - - case NET_RX_CN_MOD: - adapter->stats.upmcong++; - break; - - case NET_RX_CN_HIGH: - adapter->stats.uphcong++; - break; - - case NET_RX_DROP: - adapter->stats.updropped++; - break; - - default: - adapter->stats.updunno++; - break; - } - netdev->last_rx = jiffies; - rcv_desc->rcv_free++; rcv_desc->rcv_pending--; /* @@ -1200,13 +1132,6 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) u32 producer = 0; int count = 0, ring; - DPRINTK(INFO, "procesing receive\n"); - /* - * we assume in this case that there is only one port and that is - * port #1...changes need to be done in firmware to indicate port - * number as part of the descriptor. This way we will be able to get - * the netdev which is associated with that device. - */ while (count < max) { desc = &desc_head[consumer]; if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) { @@ -1219,11 +1144,8 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1); count++; } - if (count) { - for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { - netxen_post_rx_buffers_nodb(adapter, ctxid, ring); - } - } + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) + netxen_post_rx_buffers_nodb(adapter, ctxid, ring); /* update the consumer index in phantom */ if (count) { @@ -1233,108 +1155,60 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) /* Window = 1 */ writel(consumer, NETXEN_CRB_NORMALIZE(adapter, - recv_crb_registers[adapter->portnum]. + recv_crb_registers[adapter->portnum]. crb_rcv_status_consumer)); - wmb(); } return count; } /* Process Command status ring */ -int netxen_process_cmd_ring(unsigned long data) +int netxen_process_cmd_ring(struct netxen_adapter *adapter) { - u32 last_consumer; - u32 consumer; - struct netxen_adapter *adapter = (struct netxen_adapter *)data; - int count1 = 0; - int count2 = 0; + u32 last_consumer, consumer; + int count = 0, i; struct netxen_cmd_buffer *buffer; - struct pci_dev *pdev; + struct pci_dev *pdev = adapter->pdev; + struct net_device *netdev = adapter->netdev; struct netxen_skb_frag *frag; - u32 i; - int done; + int done = 0; - spin_lock(&adapter->tx_lock); last_consumer = adapter->last_cmd_consumer; - DPRINTK(INFO, "procesing xmit complete\n"); - /* we assume in this case that there is only one port and that is - * port #1...changes need to be done in firmware to indicate port - * number as part of the descriptor. This way we will be able to get - * the netdev which is associated with that device. - */ - consumer = le32_to_cpu(*(adapter->cmd_consumer)); - if (last_consumer == consumer) { /* Ring is empty */ - DPRINTK(INFO, "last_consumer %d == consumer %d\n", - last_consumer, consumer); - spin_unlock(&adapter->tx_lock); - return 1; - } - - adapter->proc_cmd_buf_counter++; - /* - * Not needed - does not seem to be used anywhere. - * adapter->cmd_consumer = consumer; - */ - spin_unlock(&adapter->tx_lock); - while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) { + while (last_consumer != consumer) { buffer = &adapter->cmd_buf_arr[last_consumer]; - pdev = adapter->pdev; if (buffer->skb) { frag = &buffer->frag_array[0]; pci_unmap_single(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE); frag->dma = 0ULL; for (i = 1; i < buffer->frag_count; i++) { - DPRINTK(INFO, "getting fragment no %d\n", i); frag++; /* Get the next frag */ pci_unmap_page(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE); frag->dma = 0ULL; } - adapter->stats.skbfreed++; + adapter->stats.xmitfinished++; dev_kfree_skb_any(buffer->skb); buffer->skb = NULL; - } else if (adapter->proc_cmd_buf_counter == 1) { - adapter->stats.txnullskb++; - } - if (unlikely(netif_queue_stopped(adapter->netdev) - && netif_carrier_ok(adapter->netdev)) - && ((jiffies - adapter->netdev->trans_start) > - adapter->netdev->watchdog_timeo)) { - SCHEDULE_WORK(&adapter->tx_timeout_task); } last_consumer = get_next_index(last_consumer, adapter->max_tx_desc_count); - count1++; + if (++count >= MAX_STATUS_HANDLE) + break; } - count2 = 0; - spin_lock(&adapter->tx_lock); - if ((--adapter->proc_cmd_buf_counter) == 0) { + if (count) { adapter->last_cmd_consumer = last_consumer; - while ((adapter->last_cmd_consumer != consumer) - && (count2 < MAX_STATUS_HANDLE)) { - buffer = - &adapter->cmd_buf_arr[adapter->last_cmd_consumer]; - count2++; - if (buffer->skb) - break; - else - adapter->last_cmd_consumer = - get_next_index(adapter->last_cmd_consumer, - adapter->max_tx_desc_count); - } - } - if (count1 || count2) { - if (netif_queue_stopped(adapter->netdev) - && (adapter->flags & NETXEN_NETDEV_STATUS)) { - netif_wake_queue(adapter->netdev); - adapter->flags &= ~NETXEN_NETDEV_STATUS; + smp_mb(); + if (netif_queue_stopped(netdev) && netif_running(netdev)) { + netif_tx_lock(netdev); + netif_wake_queue(netdev); + smp_mb(); + netif_tx_unlock(netdev); } } /* @@ -1350,16 +1224,9 @@ int netxen_process_cmd_ring(unsigned long data) * There is still a possible race condition and the host could miss an * interrupt. The card has to take care of this. */ - if (adapter->last_cmd_consumer == consumer && - (((adapter->cmd_producer + 1) % - adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) { - consumer = le32_to_cpu(*(adapter->cmd_consumer)); - } - done = (adapter->last_cmd_consumer == consumer); + consumer = le32_to_cpu(*(adapter->cmd_consumer)); + done = (last_consumer == consumer); - spin_unlock(&adapter->tx_lock); - DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer, - __FUNCTION__); return (done); } @@ -1433,8 +1300,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) rcv_desc->begin_alloc = index; rcv_desc->rcv_pending += count; rcv_desc->producer = producer; - if (rcv_desc->rcv_free >= 32) { - rcv_desc->rcv_free = 0; /* Window = 1 */ writel((producer - 1) & (rcv_desc->max_rx_desc_count - 1), @@ -1458,8 +1323,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) writel(msg, DB_NORMALIZE(adapter, NETXEN_RCV_PRODUCER_OFFSET)); - wmb(); - } } } @@ -1523,8 +1386,6 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, rcv_desc->begin_alloc = index; rcv_desc->rcv_pending += count; rcv_desc->producer = producer; - if (rcv_desc->rcv_free >= 32) { - rcv_desc->rcv_free = 0; /* Window = 1 */ writel((producer - 1) & (rcv_desc->max_rx_desc_count - 1), @@ -1534,21 +1395,9 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, rcv_desc_crb[ringid]. crb_rcv_producer_offset)); wmb(); - } } } -int netxen_nic_tx_has_work(struct netxen_adapter *adapter) -{ - if (find_diff_among(adapter->last_cmd_consumer, - adapter->cmd_producer, - adapter->max_tx_desc_count) > 0) - return 1; - - return 0; -} - - void netxen_nic_clear_stats(struct netxen_adapter *adapter) { memset(&adapter->stats, 0, sizeof(adapter->stats)); diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c index 48a404aa66ce..c81313b717bd 100644 --- a/drivers/net/netxen/netxen_nic_isr.c +++ b/drivers/net/netxen/netxen_nic_isr.c @@ -59,7 +59,7 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) /* packet transmit problems */ stats->tx_errors = adapter->stats.nocmddescriptor; /* no space in linux buffers */ - stats->rx_dropped = adapter->stats.updropped; + stats->rx_dropped = adapter->stats.rxdropped; /* no space available in linux */ stats->tx_dropped = adapter->stats.txdropped; @@ -193,14 +193,14 @@ int netxen_nic_link_ok(struct netxen_adapter *adapter) void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) { struct net_device *netdev = adapter->netdev; - u32 val, val1; + u32 val; /* WINDOW = 1 */ val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE)); val >>= (physical_port[adapter->portnum] * 8); - val1 = val & 0xff; + val &= 0xff; - if (adapter->ahw.xg_linkup == 1 && val1 != XG_LINK_UP) { + if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) { printk(KERN_INFO "%s: %s NIC Link is down\n", netxen_nic_driver_name, netdev->name); adapter->ahw.xg_linkup = 0; @@ -208,16 +208,7 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) netif_carrier_off(netdev); netif_stop_queue(netdev); } - /* read twice to clear sticky bits */ - /* WINDOW = 0 */ - netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1); - netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1); - - if ((val & 0xffb) != 0xffb) { - printk(KERN_INFO "%s ISR: Sync/Align BAD: 0x%08x\n", - netxen_nic_driver_name, val1); - } - } else if (adapter->ahw.xg_linkup == 0 && val1 == XG_LINK_UP) { + } else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) { printk(KERN_INFO "%s: %s NIC Link is up\n", netxen_nic_driver_name, netdev->name); adapter->ahw.xg_linkup = 1; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9737eae5ef11..a8fb439a4d03 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -63,12 +63,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *); static void netxen_tx_timeout(struct net_device *netdev); static void netxen_tx_timeout_task(struct work_struct *work); static void netxen_watchdog(unsigned long); -static int netxen_handle_int(struct netxen_adapter *, struct net_device *); static int netxen_nic_poll(struct napi_struct *napi, int budget); #ifdef CONFIG_NET_POLL_CONTROLLER static void netxen_nic_poll_controller(struct net_device *netdev); #endif static irqreturn_t netxen_intr(int irq, void *data); +static irqreturn_t netxen_msi_intr(int irq, void *data); int physical_port[] = {0, 1, 2, 3}; @@ -149,33 +149,30 @@ static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, #define ADAPTER_LIST_SIZE 12 +static uint32_t msi_tgt_status[4] = { + ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1, + ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3 +}; + +static uint32_t sw_int_mask[4] = { + CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1, + CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3 +}; + static void netxen_nic_disable_int(struct netxen_adapter *adapter) { - uint32_t mask = 0x7ff; + u32 mask = 0x7ff; int retries = 32; + int port = adapter->portnum; + int pci_fn = adapter->ahw.pci_func; - DPRINTK(1, INFO, "Entered ISR Disable \n"); - - switch (adapter->portnum) { - case 0: - writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); - break; - case 1: - writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); - break; - case 2: - writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); - break; - case 3: - writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); - break; - } + if (adapter->msi_mode != MSI_MODE_MULTIFUNC) + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port])); if (adapter->intr_scheme != -1 && adapter->intr_scheme != INTR_SCHEME_PERPORT) writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); - /* Window = 0 or 1 */ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { do { writel(0xffffffff, @@ -190,14 +187,18 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter) printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n", netxen_nic_driver_name); } + } else { + if (adapter->msi_mode == MSI_MODE_MULTIFUNC) { + writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter, + msi_tgt_status[pci_fn])); + } } - - DPRINTK(1, INFO, "Done with Disable Int\n"); } static void netxen_nic_enable_int(struct netxen_adapter *adapter) { u32 mask; + int port = adapter->portnum; DPRINTK(1, INFO, "Entered ISR Enable \n"); @@ -218,20 +219,7 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter) writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); } - switch (adapter->portnum) { - case 0: - writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); - break; - case 1: - writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); - break; - case 2: - writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); - break; - case 3: - writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); - break; - } + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port])); if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { mask = 0xbff; @@ -328,7 +316,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ahw.pdev = pdev; adapter->ahw.pci_func = pci_func_id; - spin_lock_init(&adapter->tx_lock); /* remap phys address */ mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ @@ -401,6 +388,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* this will be read from FW later */ adapter->intr_scheme = -1; + adapter->msi_mode = -1; /* This will be reset for mezz cards */ adapter->portnum = pci_func_id; @@ -415,7 +403,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->set_mac_address = netxen_nic_set_mac; netdev->change_mtu = netxen_nic_change_mtu; netdev->tx_timeout = netxen_tx_timeout; - netdev->watchdog_timeo = HZ; + netdev->watchdog_timeo = 2*HZ; netxen_nic_change_mtu(netdev, netdev->mtu); @@ -543,7 +531,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->watchdog_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); adapter->ahw.pdev = pdev; - adapter->proc_cmd_buf_counter = 0; adapter->ahw.revision_id = pdev->revision; /* make sure Window == 1 */ @@ -833,6 +820,8 @@ static int netxen_nic_open(struct net_device *netdev) struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv; int err = 0; int ctx, ring; + irq_handler_t handler; + unsigned long flags = IRQF_SAMPLE_RANDOM; if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { err = netxen_init_firmware(adapter); @@ -856,9 +845,14 @@ static int netxen_nic_open(struct net_device *netdev) netxen_post_rx_buffers(adapter, ctx, ring); } adapter->irq = adapter->ahw.pdev->irq; - err = request_irq(adapter->ahw.pdev->irq, netxen_intr, - IRQF_SHARED|IRQF_SAMPLE_RANDOM, netdev->name, - adapter); + if (adapter->flags & NETXEN_NIC_MSI_ENABLED) + handler = netxen_msi_intr; + else { + flags |= IRQF_SHARED; + handler = netxen_intr; + } + err = request_irq(adapter->irq, handler, + flags, netdev->name, adapter); if (err) { printk(KERN_ERR "request_irq failed with: %d\n", err); netxen_free_hw_resources(adapter); @@ -867,21 +861,12 @@ static int netxen_nic_open(struct net_device *netdev) adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; } - if (!adapter->driver_mismatch) - mod_timer(&adapter->watchdog_timer, jiffies); - - napi_enable(&adapter->napi); - - netxen_nic_enable_int(adapter); - /* Done here again so that even if phantom sw overwrote it, * we set it */ if (adapter->init_port && adapter->init_port(adapter, adapter->portnum) != 0) { - del_timer_sync(&adapter->watchdog_timer); printk(KERN_ERR "%s: Failed to initialize port %d\n", netxen_nic_driver_name, adapter->portnum); - napi_disable(&adapter->napi); return -EIO; } if (adapter->macaddr_set) @@ -894,6 +879,12 @@ static int netxen_nic_open(struct net_device *netdev) adapter->set_mtu(adapter, netdev->mtu); if (!adapter->driver_mismatch) + mod_timer(&adapter->watchdog_timer, jiffies); + + napi_enable(&adapter->napi); + netxen_nic_enable_int(adapter); + + if (!adapter->driver_mismatch) netif_start_queue(netdev); return 0; @@ -958,41 +949,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct netxen_skb_frag *buffrag; unsigned int i; - u32 producer = 0; + u32 producer, consumer; u32 saved_producer = 0; struct cmd_desc_type0 *hwdesc; int k; struct netxen_cmd_buffer *pbuf = NULL; - static int dropped_packet = 0; int frag_count; - u32 local_producer = 0; - u32 max_tx_desc_count = 0; - u32 last_cmd_consumer = 0; int no_of_desc; + u32 num_txd = adapter->max_tx_desc_count; - adapter->stats.xmitcalled++; frag_count = skb_shinfo(skb)->nr_frags + 1; - if (unlikely(skb->len <= 0)) { - dev_kfree_skb_any(skb); - adapter->stats.badskblen++; - return NETDEV_TX_OK; - } - - if (frag_count > MAX_BUFFERS_PER_CMD) { - printk("%s: %s netxen_nic_xmit_frame: frag_count (%d) " - "too large, can handle only %d frags\n", - netxen_nic_driver_name, netdev->name, - frag_count, MAX_BUFFERS_PER_CMD); - adapter->stats.txdropped++; - if ((++dropped_packet & 0xff) == 0xff) - printk("%s: %s droppped packets = %d\n", - netxen_nic_driver_name, netdev->name, - dropped_packet); - - return NETDEV_TX_OK; - } - /* There 4 fragments per descriptor */ no_of_desc = (frag_count + 3) >> 2; if (netdev->features & NETIF_F_TSO) { @@ -1007,27 +974,16 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } } - spin_lock_bh(&adapter->tx_lock); - if (adapter->total_threads >= MAX_XMIT_PRODUCERS) { - goto out_requeue; - } - local_producer = adapter->cmd_producer; - k = adapter->cmd_producer; - max_tx_desc_count = adapter->max_tx_desc_count; - last_cmd_consumer = adapter->last_cmd_consumer; - if ((k + no_of_desc) >= - ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count : - last_cmd_consumer)) { - goto out_requeue; + producer = adapter->cmd_producer; + smp_mb(); + consumer = adapter->last_cmd_consumer; + if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) { + netif_stop_queue(netdev); + smp_mb(); + return NETDEV_TX_BUSY; } - k = get_index_range(k, max_tx_desc_count, no_of_desc); - adapter->cmd_producer = k; - adapter->total_threads++; - adapter->num_threads++; - spin_unlock_bh(&adapter->tx_lock); /* Copy the descriptors into the hardware */ - producer = local_producer; saved_producer = producer; hwdesc = &hw->cmd_desc_head[producer]; memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); @@ -1067,8 +1023,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* move to next desc. if there is a need */ if ((i & 0x3) == 0) { k = 0; - producer = get_next_index(producer, - adapter->max_tx_desc_count); + producer = get_next_index(producer, num_txd); hwdesc = &hw->cmd_desc_head[producer]; memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); pbuf = &adapter->cmd_buf_arr[producer]; @@ -1086,7 +1041,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) buffrag->dma = temp_dma; buffrag->length = temp_len; - DPRINTK(INFO, "for loop. i=%d k=%d\n", i, k); switch (k) { case 0: hwdesc->buffer1_length = cpu_to_le16(temp_len); @@ -1107,7 +1061,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } frag++; } - producer = get_next_index(producer, adapter->max_tx_desc_count); + producer = get_next_index(producer, num_txd); /* might change opcode to TX_TCP_LSO */ netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb); @@ -1134,7 +1088,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* copy the first 64 bytes */ memcpy(((void *)hwdesc) + 2, (void *)(skb->data), first_hdr_len); - producer = get_next_index(producer, max_tx_desc_count); + producer = get_next_index(producer, num_txd); if (more_hdr) { hwdesc = &hw->cmd_desc_head[producer]; @@ -1147,35 +1101,19 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) hwdesc, (hdr_len - first_hdr_len)); - producer = get_next_index(producer, max_tx_desc_count); + producer = get_next_index(producer, num_txd); } } - spin_lock_bh(&adapter->tx_lock); + adapter->cmd_producer = producer; adapter->stats.txbytes += skb->len; - /* Code to update the adapter considering how many producer threads - are currently working */ - if ((--adapter->num_threads) == 0) { - /* This is the last thread */ - u32 crb_producer = adapter->cmd_producer; - netxen_nic_update_cmd_producer(adapter, crb_producer); - wmb(); - adapter->total_threads = 0; - } + netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); - adapter->stats.xmitfinished++; + adapter->stats.xmitcalled++; netdev->trans_start = jiffies; - spin_unlock_bh(&adapter->tx_lock); return NETDEV_TX_OK; - -out_requeue: - netif_stop_queue(netdev); - adapter->flags |= NETXEN_NETDEV_STATUS; - - spin_unlock_bh(&adapter->tx_lock); - return NETDEV_TX_BUSY; } static void netxen_watchdog(unsigned long v) @@ -1200,87 +1138,60 @@ static void netxen_tx_timeout_task(struct work_struct *work) printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", netxen_nic_driver_name, adapter->netdev->name); - netxen_nic_close(adapter->netdev); - netxen_nic_open(adapter->netdev); + netxen_nic_disable_int(adapter); + napi_disable(&adapter->napi); + adapter->netdev->trans_start = jiffies; + + napi_enable(&adapter->napi); + netxen_nic_enable_int(adapter); netif_wake_queue(adapter->netdev); } -static int -netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) +static inline void +netxen_handle_int(struct netxen_adapter *adapter) { - u32 ret = 0; - - DPRINTK(INFO, "Entered handle ISR\n"); - adapter->stats.ints++; - netxen_nic_disable_int(adapter); - - if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { - if (netif_rx_schedule_prep(netdev, &adapter->napi)) { - /* - * Interrupts are already disabled. - */ - __netif_rx_schedule(netdev, &adapter->napi); - } else { - static unsigned int intcount = 0; - if ((++intcount & 0xfff) == 0xfff) - DPRINTK(KERN_ERR - "%s: %s interrupt %d while in poll\n", - netxen_nic_driver_name, netdev->name, - intcount); - } - ret = 1; - } - - if (ret == 0) { - netxen_nic_enable_int(adapter); - } - - return ret; + napi_schedule(&adapter->napi); } -/* - * netxen_intr - Interrupt Handler - * @irq: interrupt number - * data points to adapter stucture (which may be handling more than 1 port - */ irqreturn_t netxen_intr(int irq, void *data) { struct netxen_adapter *adapter = data; - struct net_device *netdev = adapter->netdev; u32 our_int = 0; - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - /* not our interrupt */ - if ((our_int & (0x80 << adapter->portnum)) == 0) - return IRQ_NONE; - } + our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + /* not our interrupt */ + if ((our_int & (0x80 << adapter->portnum)) == 0) + return IRQ_NONE; if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { /* claim interrupt */ - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - writel(our_int & ~((u32)(0x80 << adapter->portnum)), + writel(our_int & ~((u32)(0x80 << adapter->portnum)), NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - } } - if (netif_running(netdev)) - netxen_handle_int(adapter, netdev); + netxen_handle_int(adapter); return IRQ_HANDLED; } +irqreturn_t netxen_msi_intr(int irq, void *data) +{ + struct netxen_adapter *adapter = data; + + netxen_handle_int(adapter); + return IRQ_HANDLED; +} + static int netxen_nic_poll(struct napi_struct *napi, int budget) { struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi); - struct net_device *netdev = adapter->netdev; - int done = 1; + int tx_complete; int ctx; int work_done; - DPRINTK(INFO, "polling for %d descriptors\n", *budget); + tx_complete = netxen_process_cmd_ring(adapter); work_done = 0; for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { @@ -1300,16 +1211,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) budget / MAX_RCV_CTX); } - if (work_done >= budget) - done = 0; - - if (netxen_process_cmd_ring((unsigned long)adapter) == 0) - done = 0; - - DPRINTK(INFO, "new work_done: %d work_to_do: %d\n", - work_done, work_to_do); - if (done) { - netif_rx_complete(netdev, napi); + if ((work_done < budget) && tx_complete) { + netif_rx_complete(adapter->netdev, &adapter->napi); netxen_nic_enable_int(adapter); } diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index ffa3b7215ce8..a566b50f36f5 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -126,8 +126,11 @@ */ #define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) #define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) +#define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) +#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) #define INTR_SCHEME_PERPORT 0x1 +#define MSI_MODE_MULTIFUNC 0x1 /* used for ethtool tests */ #define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index f0574073a2a3..33539917e9b8 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -58,9 +58,25 @@ #define MII_M1111_RX_DELAY 0x80 #define MII_M1111_TX_DELAY 0x2 #define MII_M1111_PHY_EXT_SR 0x1b -#define MII_M1111_HWCFG_MODE_MASK 0xf -#define MII_M1111_HWCFG_MODE_RGMII 0xb + +#define MII_M1111_HWCFG_MODE_MASK 0xf +#define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb +#define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3 #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 +#define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000 +#define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000 + +#define MII_M1111_COPPER 0 +#define MII_M1111_FIBER 1 + +#define MII_M1011_PHY_STATUS 0x11 +#define MII_M1011_PHY_STATUS_1000 0x8000 +#define MII_M1011_PHY_STATUS_100 0x4000 +#define MII_M1011_PHY_STATUS_SPD_MASK 0xc000 +#define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000 +#define MII_M1011_PHY_STATUS_RESOLVED 0x0800 +#define MII_M1011_PHY_STATUS_LINK 0x0400 + MODULE_DESCRIPTION("Marvell PHY driver"); MODULE_AUTHOR("Andy Fleming"); @@ -141,12 +157,22 @@ static int marvell_config_aneg(struct phy_device *phydev) static int m88e1111_config_init(struct phy_device *phydev) { int err; + int temp; + int mode; + + /* Enable Fiber/Copper auto selection */ + temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); + temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO; + phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); + + temp = phy_read(phydev, MII_BMCR); + temp |= BMCR_RESET; + phy_write(phydev, MII_BMCR, temp); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { - int temp; temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); if (temp < 0) @@ -171,7 +197,13 @@ static int m88e1111_config_init(struct phy_device *phydev) return temp; temp &= ~(MII_M1111_HWCFG_MODE_MASK); - temp |= MII_M1111_HWCFG_MODE_RGMII; + + mode = phy_read(phydev, MII_M1111_PHY_EXT_CR); + + if (mode & MII_M1111_HWCFG_FIBER_COPPER_RES) + temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII; + else + temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII; err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); if (err < 0) @@ -262,6 +294,93 @@ static int m88e1145_config_init(struct phy_device *phydev) return 0; } +/* marvell_read_status + * + * Generic status code does not detect Fiber correctly! + * Description: + * Check the link, then figure out the current state + * by comparing what we advertise with what the link partner + * advertises. Start by checking the gigabit possibilities, + * then move on to 10/100. + */ +static int marvell_read_status(struct phy_device *phydev) +{ + int adv; + int err; + int lpa; + int status = 0; + + /* Update the link, but return if there + * was an error */ + err = genphy_update_link(phydev); + if (err) + return err; + + if (AUTONEG_ENABLE == phydev->autoneg) { + status = phy_read(phydev, MII_M1011_PHY_STATUS); + if (status < 0) + return status; + + lpa = phy_read(phydev, MII_LPA); + if (lpa < 0) + return lpa; + + adv = phy_read(phydev, MII_ADVERTISE); + if (adv < 0) + return adv; + + lpa &= adv; + + if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) + phydev->duplex = DUPLEX_FULL; + else + phydev->duplex = DUPLEX_HALF; + + status = status & MII_M1011_PHY_STATUS_SPD_MASK; + phydev->pause = phydev->asym_pause = 0; + + switch (status) { + case MII_M1011_PHY_STATUS_1000: + phydev->speed = SPEED_1000; + break; + + case MII_M1011_PHY_STATUS_100: + phydev->speed = SPEED_100; + break; + + default: + phydev->speed = SPEED_10; + break; + } + + if (phydev->duplex == DUPLEX_FULL) { + phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; + phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; + } + } else { + int bmcr = phy_read(phydev, MII_BMCR); + + if (bmcr < 0) + return bmcr; + + if (bmcr & BMCR_FULLDPLX) + phydev->duplex = DUPLEX_FULL; + else + phydev->duplex = DUPLEX_HALF; + + if (bmcr & BMCR_SPEED1000) + phydev->speed = SPEED_1000; + else if (bmcr & BMCR_SPEED100) + phydev->speed = SPEED_100; + else + phydev->speed = SPEED_10; + + phydev->pause = phydev->asym_pause = 0; + } + + return 0; +} + static struct phy_driver marvell_drivers[] = { { .phy_id = 0x01410c60, @@ -296,7 +415,7 @@ static struct phy_driver marvell_drivers[] = { .flags = PHY_HAS_INTERRUPT, .config_init = &m88e1111_config_init, .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, + .read_status = &marvell_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, .driver = { .owner = THIS_MODULE }, diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index c72787adeba3..3c915b82e199 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -4172,6 +4172,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; spin_unlock_irqrestore(&fifo->tx_lock, flags); + if (sp->config.intr_type == MSI_X) + tx_intr_handler(fifo); + return 0; pci_map_failed: stats->pci_map_fail_cnt++; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 186eb8ebfda6..2e26dced13a1 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -3199,12 +3199,14 @@ static int skge_poll(struct napi_struct *napi, int to_do) skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START); if (work_done < to_do) { - spin_lock_irq(&hw->hw_lock); + unsigned long flags; + + spin_lock_irqsave(&hw->hw_lock, flags); __netif_rx_complete(dev, napi); hw->intr_mask |= napimask[skge->port]; skge_write32(hw, B0_IMSK, hw->intr_mask); skge_read32(hw, B0_IMSK); - spin_unlock_irq(&hw->hw_lock); + spin_unlock_irqrestore(&hw->hw_lock, flags); } return work_done; diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 51d4134b37b1..98a832a75539 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -92,14 +92,14 @@ #define SMC_insw(a, r, p, l) insw ((unsigned long *)((a) + (r)), p, l) # endif /* check if the mac in reg is valid */ -#define SMC_GET_MAC_ADDR(addr) \ +#define SMC_GET_MAC_ADDR(lp, addr) \ do { \ unsigned int __v; \ - __v = SMC_inw(ioaddr, ADDR0_REG); \ + __v = SMC_inw(ioaddr, ADDR0_REG(lp)); \ addr[0] = __v; addr[1] = __v >> 8; \ - __v = SMC_inw(ioaddr, ADDR1_REG); \ + __v = SMC_inw(ioaddr, ADDR1_REG(lp)); \ addr[2] = __v; addr[3] = __v >> 8; \ - __v = SMC_inw(ioaddr, ADDR2_REG); \ + __v = SMC_inw(ioaddr, ADDR2_REG(lp)); \ addr[4] = __v; addr[5] = __v >> 8; \ if (*(u32 *)(&addr[0]) == 0xFFFFFFFF) { \ random_ether_addr(addr); \ diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 8909050b8ea7..5f1c5072b96f 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -3413,7 +3413,7 @@ static int smctr_make_tx_status_code(struct net_device *dev, tsv->svi = TRANSMIT_STATUS_CODE; tsv->svl = S_TRANSMIT_STATUS_CODE; - tsv->svv[0] = ((tx_fstatus & 0x0100 >> 6) || IBM_PASS_SOURCE_ADDR); + tsv->svv[0] = ((tx_fstatus & 0x0100 >> 6) | IBM_PASS_SOURCE_ADDR); /* Stripped frame status of Transmitted Frame */ tsv->svv[1] = tx_fstatus & 0xff; diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 4b131a6c6b70..0343b00cf1fd 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -341,7 +341,7 @@ static void dm9601_set_multicast(struct net_device *net) /* We use the 20 byte dev->data for our 8 byte filter buffer * to avoid allocating memory that is tricky to free later */ u8 *hashes = (u8 *) & dev->data; - u8 rx_ctl = 0x01; + u8 rx_ctl = 0x31; memset(hashes, 0x00, DM_MCAST_SIZE); hashes[DM_MCAST_SIZE - 1] |= 0x80; /* broadcast address */ @@ -562,6 +562,10 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0a46, 0x8515), /* ADMtek ADM8515 USB NIC */ .driver_info = (unsigned long)&dm9601_info, }, + { + USB_DEVICE(0x0a47, 0x9601), /* Hirose USB-100 */ + .driver_info = (unsigned long)&dm9601_info, + }, {}, // END }; diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 727547a28992..369c731114b3 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -283,7 +283,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) struct rndis_set_c *set_c; struct rndis_halt *halt; } u; - u32 tmp, *phym; + u32 tmp, phym_unspec, *phym; int reply_len; unsigned char *bp; @@ -363,12 +363,15 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) goto halt_fail_and_release; /* Check physical medium */ + phym = NULL; reply_len = sizeof *phym; retval = rndis_query(dev, intf, u.buf, OID_GEN_PHYSICAL_MEDIUM, 0, (void **) &phym, &reply_len); - if (retval != 0) + if (retval != 0 || !phym) { /* OID is optional so don't fail here. */ - *phym = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED; + phym_unspec = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED; + phym = &phym_unspec; + } if ((flags & FLAG_RNDIS_PHYM_WIRELESS) && *phym != RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) { if (netif_msg_probe(dev)) diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 7e1f00131f91..df56a518691c 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -376,7 +376,7 @@ static int alloc_all_urbs(rtl8150_t * dev) return 0; } dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->intr_urb) { + if (!dev->ctrl_urb) { usb_free_urb(dev->rx_urb); usb_free_urb(dev->tx_urb); usb_free_urb(dev->intr_urb); diff --git a/drivers/net/wireless/arlan-proc.c b/drivers/net/wireless/arlan-proc.c index c6e70dbc5de8..2ab1d59870f4 100644 --- a/drivers/net/wireless/arlan-proc.c +++ b/drivers/net/wireless/arlan-proc.c @@ -1202,13 +1202,6 @@ static ctl_table arlan_table[MAX_ARLANS + 1] = { .ctl_name = 0 } }; #endif -#else - -static ctl_table arlan_table[MAX_ARLANS + 1] = -{ - { .ctl_name = 0 } -}; -#endif // static int mmtu = 1234; @@ -1233,7 +1226,6 @@ static ctl_table arlan_root_table[] = //}; -#ifdef CONFIG_PROC_FS static struct ctl_table_header *arlan_device_sysctl_header; int __init init_arlan_proc(void) diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index e38ed0fe72e9..7fca2ebc747f 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -618,6 +618,7 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) kfree(e); } +/* Called with IRQs disabled. */ void b43_debugfs_log_txstat(struct b43_wldev *dev, const struct b43_txstatus *status) { @@ -629,8 +630,7 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev, if (!e) return; log = &e->txstatlog; - B43_WARN_ON(!irqs_disabled()); - spin_lock(&log->lock); + spin_lock(&log->lock); /* IRQs are already disabled. */ i = log->end + 1; if (i == B43_NR_LOGGED_TXSTATUS) i = 0; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3dfb28a34be9..cfbc1a26f601 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -560,7 +560,7 @@ static int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, /* Check if a DMA mapping address is invalid. */ static bool b43_dma_mapping_error(struct b43_dmaring *ring, dma_addr_t addr, - size_t buffersize) + size_t buffersize, bool dma_to_device) { if (unlikely(dma_mapping_error(addr))) return 1; @@ -568,11 +568,11 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, switch (ring->type) { case B43_DMA_30BIT: if ((u64)addr + buffersize > (1ULL << 30)) - return 1; + goto address_error; break; case B43_DMA_32BIT: if ((u64)addr + buffersize > (1ULL << 32)) - return 1; + goto address_error; break; case B43_DMA_64BIT: /* Currently we can't have addresses beyond @@ -582,6 +582,12 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, /* The address is OK. */ return 0; + +address_error: + /* We can't support this address. Unmap it again. */ + unmap_descbuffer(ring, addr, buffersize, dma_to_device); + + return 1; } static int setup_rx_descbuffer(struct b43_dmaring *ring, @@ -599,7 +605,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, if (unlikely(!skb)) return -ENOMEM; dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); - if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { + if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { /* ugh. try to realloc in zone_dma */ gfp_flags |= GFP_DMA; @@ -612,7 +618,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, ring->rx_buffersize, 0); } - if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { + if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { dev_kfree_skb_any(skb); return -EIO; } @@ -852,7 +858,8 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, b43_txhdr_size(dev), DMA_TO_DEVICE); - if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev))) { + if (b43_dma_mapping_error(ring, dma_test, + b43_txhdr_size(dev), 1)) { /* ugh realloc */ kfree(ring->txhdr_cache); ring->txhdr_cache = kcalloc(nr_slots, @@ -867,7 +874,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, DMA_TO_DEVICE); if (b43_dma_mapping_error(ring, dma_test, - b43_txhdr_size(dev))) + b43_txhdr_size(dev), 1)) goto err_kfree_txhdr_cache; } @@ -1189,7 +1196,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, hdrsize, 1); - if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize)) { + if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize, 1)) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; return -EIO; @@ -1208,7 +1215,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); /* create a bounce buffer in zone_dma on mapping failure. */ - if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { + if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) { ring->current_slot = old_top_slot; @@ -1222,7 +1229,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, skb = bounce_skb; meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { + if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; err = -EIO; @@ -1337,6 +1344,7 @@ out_unlock: return err; } +/* Called with IRQs disabled. */ void b43_dma_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status) { @@ -1349,8 +1357,8 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, ring = parse_cookie(dev, status->cookie, &slot); if (unlikely(!ring)) return; - B43_WARN_ON(!irqs_disabled()); - spin_lock(&ring->lock); + + spin_lock(&ring->lock); /* IRQs are already disabled. */ B43_WARN_ON(!ring->tx); ops = ring->ops; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 51dfce16178a..c73a75b24cd6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2049,7 +2049,6 @@ void b43_mac_enable(struct b43_wldev *dev) { dev->mac_suspended--; B43_WARN_ON(dev->mac_suspended < 0); - B43_WARN_ON(irqs_disabled()); if (dev->mac_suspended == 0) { b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) @@ -2075,7 +2074,6 @@ void b43_mac_suspend(struct b43_wldev *dev) u32 tmp; might_sleep(); - B43_WARN_ON(irqs_disabled()); B43_WARN_ON(dev->mac_suspended < 0); if (dev->mac_suspended == 0) { diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index d1af938b9aa6..b79a35a40ab6 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -20,7 +20,7 @@ config IWL4965 runs. If you want to compile the driver as a module ( = code which can be - inserted in and remvoed from the running kernel whenever you want), + inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/kbuild/modules.txt>. The module will be called iwl4965.ko. @@ -101,7 +101,7 @@ config IWL3945 runs. If you want to compile the driver as a module ( = code which can be - inserted in and remvoed from the running kernel whenever you want), + inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/kbuild/modules.txt>. The module will be called iwl3945.ko. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 40b71bc2c4a4..cbaeaf186494 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6206,11 +6206,11 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) /* At this point, the NIC is initialized and operational */ priv->notif_missed_beacons = 0; - set_bit(STATUS_READY, &priv->status); iwl3945_reg_txpower_periodic(priv); IWL_DEBUG_INFO("ALIVE processing complete.\n"); + set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); if (priv->error_recovering) @@ -8706,7 +8706,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e return err; } -static void iwl3945_pci_remove(struct pci_dev *pdev) +static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) { struct iwl3945_priv *priv = pci_get_drvdata(pdev); struct list_head *p, *q; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index a23d4798653b..60ec29eab85a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6628,11 +6628,11 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv) /* At this point, the NIC is initialized and operational */ priv->notif_missed_beacons = 0; - set_bit(STATUS_READY, &priv->status); iwl4965_rf_kill_ct_config(priv); IWL_DEBUG_INFO("ALIVE processing complete.\n"); + set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); if (priv->error_recovering) @@ -9282,7 +9282,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e return err; } -static void iwl4965_pci_remove(struct pci_dev *pdev) +static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) { struct iwl4965_priv *priv = pci_get_drvdata(pdev); struct list_head *p, *q; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 8103d41a1543..3909cf42f472 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2095,6 +2095,8 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, /* Conceptronic */ { USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Corega */ + { USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) }, /* D-Link */ { USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) }, diff --git a/drivers/net/wireless/wavelan_cs.h b/drivers/net/wireless/wavelan_cs.h index fabc63ee153c..2e4bfe4147c6 100644 --- a/drivers/net/wireless/wavelan_cs.h +++ b/drivers/net/wireless/wavelan_cs.h @@ -309,7 +309,7 @@ struct mmw_t #define MMW_EXT_ANT_INTERNAL 0x00 /* Internal antenna */ #define MMW_EXT_ANT_EXTERNAL 0x03 /* External antenna */ #define MMW_EXT_ANT_IQ_TEST 0x1C /* IQ test pattern (set to 0) */ -}; +} __attribute__((packed)); /* Size for structure checking (if padding is correct) */ #define MMW_SIZE 37 diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 977d29b32295..4cb949f0ebd9 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1097,6 +1097,8 @@ static void iommu_free_domain(struct dmar_domain *domain) } static struct iova_domain reserved_iova_list; +static struct lock_class_key reserved_alloc_key; +static struct lock_class_key reserved_rbtree_key; static void dmar_init_reserved_ranges(void) { @@ -1107,6 +1109,11 @@ static void dmar_init_reserved_ranges(void) init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); + lockdep_set_class(&reserved_iova_list.iova_alloc_lock, + &reserved_alloc_key); + lockdep_set_class(&reserved_iova_list.iova_rbtree_lock, + &reserved_rbtree_key); + /* IOAPIC ranges shouldn't be accessed by DMA */ iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START), IOVA_PFN(IOAPIC_RANGE_END)); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 183fddaa38b7..a4445b7210bf 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -314,24 +314,6 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap) } EXPORT_SYMBOL_GPL(pci_find_ht_capability); -void pcie_wait_pending_transaction(struct pci_dev *dev) -{ - int pos; - u16 reg16; - - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - if (!pos) - return; - while (1) { - pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, ®16); - if (!(reg16 & PCI_EXP_DEVSTA_TRPND)) - break; - cpu_relax(); - } - -} -EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction); - /** * pci_find_parent_resource - return resource region of parent bus of given region * @dev: PCI device structure contains resources to be searched @@ -936,9 +918,6 @@ pci_disable_device(struct pci_dev *dev) if (atomic_sub_return(1, &dev->enable_cnt) != 0) return; - /* Wait for all transactions are finished before disabling the device */ - pcie_wait_pending_transaction(dev); - pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 125e7b7f34ff..f7cb8e0758b4 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -486,12 +486,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) break; case PCI_CLASS_BRIDGE_PCI: - /* don't size subtractive decoding (transparent) - * PCI-to-PCI bridges */ - if (bus->self->transparent) - break; pci_bridge_check_ranges(bus); - /* fall through */ default: pbus_size_io(bus); /* If the bridge supports prefetchable range, size it diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 6aa231ef642d..2dcd1960aca8 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -85,7 +85,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, i < PNP_MAX_IRQ) i++; if (i >= PNP_MAX_IRQ && !warned) { - printk(KERN_ERR "pnpacpi: exceeded the max number of IRQ " + printk(KERN_WARNING "pnpacpi: exceeded the max number of IRQ " "resources: %d \n", PNP_MAX_IRQ); warned = 1; return; @@ -187,7 +187,7 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, res->dma_resource[i].start = dma; res->dma_resource[i].end = dma; } else if (!warned) { - printk(KERN_ERR "pnpacpi: exceeded the max number of DMA " + printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA " "resources: %d \n", PNP_MAX_DMA); warned = 1; } @@ -213,7 +213,7 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, res->port_resource[i].start = io; res->port_resource[i].end = io + len - 1; } else if (!warned) { - printk(KERN_ERR "pnpacpi: exceeded the max number of IO " + printk(KERN_WARNING "pnpacpi: exceeded the max number of IO " "resources: %d \n", PNP_MAX_PORT); warned = 1; } @@ -241,7 +241,7 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, res->mem_resource[i].start = mem; res->mem_resource[i].end = mem + len - 1; } else if (!warned) { - printk(KERN_ERR "pnpacpi: exceeded the max number of mem " + printk(KERN_WARNING "pnpacpi: exceeded the max number of mem " "resources: %d\n", PNP_MAX_MEM); warned = 1; } diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index e8a01f264540..11759080ca54 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -470,6 +470,8 @@ static int uio_mmap_physical(struct vm_area_struct *vma) vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + return remap_pfn_range(vma, vma->vm_start, idev->info->mem[mi].addr >> PAGE_SHIFT, diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index fefb92296e8f..c311f67b7f08 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1206,7 +1206,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) return -EINVAL; } - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + if (dev->quirks & USB_QUIRK_NO_SET_INTF) + ret = -EPIPE; + else + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, interface, NULL, 0, 5000); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index d9d1eb19f2a1..dfc5418ea10c 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -50,6 +50,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, + /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */ + { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF }, + /* Action Semiconductor flash disk */ { USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255 }, diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 805602a687cb..0a6feafc8d28 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1458,7 +1458,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) /* currently one config, two speeds */ case USB_REQ_SET_CONFIGURATION: if (ctrl->bRequestType != 0) - break; + goto unrecognized; if (0 == (u8) w_value) { value = 0; dev->current_config = 0; @@ -1505,7 +1505,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) /* PXA automagically handles this request too */ case USB_REQ_GET_CONFIGURATION: if (ctrl->bRequestType != 0x80) - break; + goto unrecognized; *(u8 *)req->buf = dev->current_config; value = min (w_length, (u16) 1); break; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 3ba01664f821..72ccd56e36dd 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -152,6 +152,20 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } break; + case PCI_VENDOR_ID_VIA: + if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x60) { + u8 tmp; + + /* The VT6212 defaults to a 1 usec EHCI sleep time which + * hogs the PCI bus *badly*. Setting bit 5 of 0x4B makes + * that sleep time use the conventional 10 usec. + */ + pci_read_config_byte(pdev, 0x4b, &tmp); + if (tmp & 0x20) + break; + pci_write_config_byte(pdev, 0x4b, tmp | 0x20); + } + break; } ehci_reset(ehci); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ae3ec1a64008..2af778555bdc 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -55,6 +55,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 237a41f6638a..10cf872e5ecb 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -13,6 +13,7 @@ #define PL2303_PRODUCT_ID_DCU11 0x1234 #define PL2303_PRODUCT_ID_PHAROS 0xaaa0 #define PL2303_PRODUCT_ID_RSAQ3 0xaaa2 +#define PL2303_PRODUCT_ID_ALDIGA 0x0611 #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index e3d44ae8d448..ed678811e6a6 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -14,7 +14,7 @@ Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> */ -#define DRIVER_VERSION "v.1.2.7" +#define DRIVER_VERSION "v.1.2.8" #define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>" #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -163,6 +163,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */ + { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/ { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/ @@ -196,9 +197,9 @@ struct sierra_port_private { spinlock_t lock; /* lock the structure */ int outstanding_urbs; /* number of out urbs in flight */ - /* Input endpoints and buffer for this port */ + /* Input endpoints and buffers for this port */ struct urb *in_urbs[N_IN_URB]; - char in_buffer[N_IN_URB][IN_BUFLEN]; + char *in_buffer[N_IN_URB]; /* Settings for the port */ int rts_state; /* Handshaking pins (outputs) */ @@ -638,6 +639,15 @@ static int sierra_startup(struct usb_serial *serial) return -ENOMEM; } spin_lock_init(&portdata->lock); + for (j = 0; j < N_IN_URB; j++) { + portdata->in_buffer[j] = kmalloc(IN_BUFLEN, GFP_KERNEL); + if (!portdata->in_buffer[j]) { + for (--j; j >= 0; j--) + kfree(portdata->in_buffer[j]); + kfree(portdata); + return -ENOMEM; + } + } usb_set_serial_port_data(port, portdata); @@ -681,7 +691,7 @@ static void sierra_shutdown(struct usb_serial *serial) for (j = 0; j < N_IN_URB; j++) { usb_kill_urb(portdata->in_urbs[j]); usb_free_urb(portdata->in_urbs[j]); - portdata->in_urbs[j] = NULL; + kfree(portdata->in_buffer[j]); } kfree(portdata); usb_set_serial_port_data(port, NULL); diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 9d3f28b92cbe..971d13dd5e65 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1230,6 +1230,7 @@ static int isd200_get_inquiry_data( struct us_data *us ) /* Free driver structure */ us->extra_destructor(info); + kfree(info); us->extra = NULL; us->extra_destructor = NULL; } diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 5780ed15f1ad..bdd4334bed5a 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1009,7 +1009,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, residue, bcs->Status); - if (bcs->Tag != us->tag || bcs->Status > US_BULK_STAT_PHASE) { + if (!(bcs->Tag == us->tag || (us->flags & US_FL_BULK_IGNORE_TAG)) || + bcs->Status > US_BULK_STAT_PHASE) { US_DEBUGP("Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 99679a8cfa02..e5219a56947c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1589,6 +1589,17 @@ UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* + * Patch by Constantin Baranov <const@tltsu.ru> + * Report by Andreas Koenecke. + * Motorola ROKR Z6. + */ +UNUSUAL_DEV( 0x22b8, 0x6426, 0x0101, 0x0101, + "Motorola", + "MSnc.", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY | US_FL_BULK_IGNORE_TAG), + /* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, "MPIO", diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 59a8f73dec73..6c8ecde6aad1 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -388,6 +388,7 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev) { struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); + unregister_virtio_device(&vp_dev->vdev); free_irq(pci_dev->irq, vp_dev); pci_set_drvdata(pci_dev, NULL); pci_iounmap(pci_dev, vp_dev->ioaddr); diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 23321889d9b0..f42be069e085 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -81,13 +81,10 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, if (IS_ERR(anon_inode_inode)) return -ENODEV; - file = get_empty_filp(); - if (!file) - return -ENFILE; error = get_unused_fd(); if (error < 0) - goto err_put_filp; + return error; fd = error; /* @@ -114,14 +111,15 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, dentry->d_flags &= ~DCACHE_UNHASHED; d_instantiate(dentry, anon_inode_inode); - file->f_path.mnt = mntget(anon_inode_mnt); - file->f_path.dentry = dentry; + error = -ENFILE; + file = alloc_file(anon_inode_mnt, dentry, + FMODE_READ | FMODE_WRITE, fops); + if (!file) + goto err_dput; file->f_mapping = anon_inode_inode->i_mapping; file->f_pos = 0; file->f_flags = O_RDWR; - file->f_op = fops; - file->f_mode = FMODE_READ | FMODE_WRITE; file->f_version = 0; file->private_data = priv; @@ -132,10 +130,10 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, *pfile = file; return 0; +err_dput: + dput(dentry); err_put_unused_fd: put_unused_fd(fd); -err_put_filp: - put_filp(file); return error; } EXPORT_SYMBOL_GPL(anon_inode_getfd); diff --git a/fs/file_table.c b/fs/file_table.c index 6d27befe2d48..986ff4ed0a7c 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -83,6 +83,12 @@ int proc_nr_files(ctl_table *table, int write, struct file *filp, /* Find an unused file structure and return a pointer to it. * Returns NULL, if there are no more free file structures or * we run out of memory. + * + * Be very careful using this. You are responsible for + * getting write access to any mount that you might assign + * to this filp, if it is opened for write. If this is not + * done, you will imbalance int the mount's writer count + * and a warning at __fput() time. */ struct file *get_empty_filp(void) { diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index a1e1f0f61aa5..8601d8ef3b55 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -1,23 +1,24 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <linux/fs.h> +#include <linux/ctype.h> +#include <linux/dcache.h> #include <linux/file.h> -#include <linux/module.h> +#include <linux/fs.h> #include <linux/init.h> -#include <linux/slab.h> -#include <linux/list.h> #include <linux/kernel.h> -#include <linux/ctype.h> -#include <linux/dcache.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/mount.h> +#include <linux/slab.h> #include <linux/statfs.h> +#include <linux/types.h> #include <asm/uaccess.h> -#include <asm/fcntl.h> #include "os.h" -static int init_inode(struct inode *inode, struct dentry *dentry); +static struct inode *get_inode(struct super_block *, struct dentry *); struct hppfs_data { struct list_head list; @@ -51,14 +52,14 @@ static int is_pid(struct dentry *dentry) int i; sb = dentry->d_sb; - if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) - return(0); + if ((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) + return 0; - for(i = 0; i < dentry->d_name.len; i++){ - if(!isdigit(dentry->d_name.name[i])) - return(0); + for (i = 0; i < dentry->d_name.len; i++) { + if (!isdigit(dentry->d_name.name[i])) + return 0; } - return(1); + return 1; } static char *dentry_name(struct dentry *dentry, int extra) @@ -70,8 +71,8 @@ static char *dentry_name(struct dentry *dentry, int extra) len = 0; parent = dentry; - while(parent->d_parent != parent){ - if(is_pid(parent)) + while (parent->d_parent != parent) { + if (is_pid(parent)) len += strlen("pid") + 1; else len += parent->d_name.len + 1; parent = parent->d_parent; @@ -80,12 +81,13 @@ static char *dentry_name(struct dentry *dentry, int extra) root = "proc"; len += strlen(root); name = kmalloc(len + extra + 1, GFP_KERNEL); - if(name == NULL) return(NULL); + if (name == NULL) + return NULL; name[len] = '\0'; parent = dentry; - while(parent->d_parent != parent){ - if(is_pid(parent)){ + while (parent->d_parent != parent) { + if (is_pid(parent)) { seg_name = "pid"; seg_len = strlen("pid"); } @@ -100,27 +102,25 @@ static char *dentry_name(struct dentry *dentry, int extra) parent = parent->d_parent; } strncpy(name, root, strlen(root)); - return(name); + return name; } -struct dentry_operations hppfs_dentry_ops = { -}; - static int file_removed(struct dentry *dentry, const char *file) { char *host_file; int extra, fd; extra = 0; - if(file != NULL) extra += strlen(file) + 1; + if (file != NULL) + extra += strlen(file) + 1; host_file = dentry_name(dentry, extra + strlen("/remove")); - if(host_file == NULL){ - printk("file_removed : allocation failed\n"); - return(-ENOMEM); + if (host_file == NULL) { + printk(KERN_ERR "file_removed : allocation failed\n"); + return -ENOMEM; } - if(file != NULL){ + if (file != NULL) { strcat(host_file, "/"); strcat(host_file, file); } @@ -128,45 +128,11 @@ static int file_removed(struct dentry *dentry, const char *file) fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); kfree(host_file); - if(fd > 0){ + if (fd > 0) { os_close_file(fd); - return(1); - } - return(0); -} - -static void hppfs_read_inode(struct inode *ino) -{ - struct inode *proc_ino; - - if(HPPFS_I(ino)->proc_dentry == NULL) - return; - - proc_ino = HPPFS_I(ino)->proc_dentry->d_inode; - ino->i_uid = proc_ino->i_uid; - ino->i_gid = proc_ino->i_gid; - ino->i_atime = proc_ino->i_atime; - ino->i_mtime = proc_ino->i_mtime; - ino->i_ctime = proc_ino->i_ctime; - ino->i_ino = proc_ino->i_ino; - ino->i_mode = proc_ino->i_mode; - ino->i_nlink = proc_ino->i_nlink; - ino->i_size = proc_ino->i_size; - ino->i_blocks = proc_ino->i_blocks; -} - -static struct inode *hppfs_iget(struct super_block *sb) -{ - struct inode *inode; - - inode = iget_locked(sb, 0); - if (!inode) - return ERR_PTR(-ENOMEM); - if (inode->i_state & I_NEW) { - hppfs_read_inode(inode); - unlock_new_inode(inode); + return 1; } - return inode; + return 0; } static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, @@ -177,55 +143,45 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, int err, deleted; deleted = file_removed(dentry, NULL); - if(deleted < 0) - return(ERR_PTR(deleted)); - else if(deleted) - return(ERR_PTR(-ENOENT)); + if (deleted < 0) + return ERR_PTR(deleted); + else if (deleted) + return ERR_PTR(-ENOENT); err = -ENOMEM; parent = HPPFS_I(ino)->proc_dentry; mutex_lock(&parent->d_inode->i_mutex); proc_dentry = d_lookup(parent, &dentry->d_name); - if(proc_dentry == NULL){ + if (proc_dentry == NULL) { proc_dentry = d_alloc(parent, &dentry->d_name); - if(proc_dentry == NULL){ + if (proc_dentry == NULL) { mutex_unlock(&parent->d_inode->i_mutex); goto out; } new = (*parent->d_inode->i_op->lookup)(parent->d_inode, proc_dentry, NULL); - if(new){ + if (new) { dput(proc_dentry); proc_dentry = new; } } mutex_unlock(&parent->d_inode->i_mutex); - if(IS_ERR(proc_dentry)) - return(proc_dentry); + if (IS_ERR(proc_dentry)) + return proc_dentry; - inode = hppfs_iget(ino->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); + err = -ENOMEM; + inode = get_inode(ino->i_sb, proc_dentry); + if (!inode) goto out_dput; - } - - err = init_inode(inode, proc_dentry); - if(err) - goto out_put; - - hppfs_read_inode(inode); d_add(dentry, inode); - dentry->d_op = &hppfs_dentry_ops; - return(NULL); + return NULL; - out_put: - iput(inode); out_dput: dput(proc_dentry); out: - return(ERR_PTR(err)); + return ERR_PTR(err); } static const struct inode_operations hppfs_file_iops = { @@ -239,15 +195,16 @@ static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, read = file->f_path.dentry->d_inode->i_fop->read; - if(!is_user) + if (!is_user) set_fs(KERNEL_DS); n = (*read)(file, buf, count, &file->f_pos); - if(!is_user) + if (!is_user) set_fs(USER_DS); - if(ppos) *ppos = file->f_pos; + if (ppos) + *ppos = file->f_pos; return n; } @@ -259,24 +216,23 @@ static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count) n = -ENOMEM; new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if(new_buf == NULL){ - printk("hppfs_read_file : kmalloc failed\n"); + if (new_buf == NULL) { + printk(KERN_ERR "hppfs_read_file : kmalloc failed\n"); goto out; } n = 0; - while(count > 0){ + while (count > 0) { cur = min_t(ssize_t, count, PAGE_SIZE); err = os_read_file(fd, new_buf, cur); - if(err < 0){ - printk("hppfs_read : read failed, errno = %d\n", - err); + if (err < 0) { + printk(KERN_ERR "hppfs_read : read failed, " + "errno = %d\n", err); n = err; goto out_free; - } - else if(err == 0) + } else if (err == 0) break; - if(copy_to_user(buf, new_buf, err)){ + if (copy_to_user(buf, new_buf, err)) { n = -EFAULT; goto out_free; } @@ -297,35 +253,36 @@ static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, loff_t off; int err; - if(hppfs->contents != NULL){ - if(*ppos >= hppfs->len) return(0); + if (hppfs->contents != NULL) { + if (*ppos >= hppfs->len) + return 0; data = hppfs->contents; off = *ppos; - while(off >= sizeof(data->contents)){ + while (off >= sizeof(data->contents)) { data = list_entry(data->list.next, struct hppfs_data, list); off -= sizeof(data->contents); } - if(off + count > hppfs->len) + if (off + count > hppfs->len) count = hppfs->len - off; copy_to_user(buf, &data->contents[off], count); *ppos += count; - } - else if(hppfs->host_fd != -1){ + } else if (hppfs->host_fd != -1) { err = os_seek_file(hppfs->host_fd, *ppos); - if(err){ - printk("hppfs_read : seek failed, errno = %d\n", err); - return(err); + if (err) { + printk(KERN_ERR "hppfs_read : seek failed, " + "errno = %d\n", err); + return err; } count = hppfs_read_file(hppfs->host_fd, buf, count); - if(count > 0) + if (count > 0) *ppos += count; } else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); - return(count); + return count; } static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len, @@ -342,7 +299,7 @@ static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len err = (*write)(proc_file, buf, len, &proc_file->f_pos); file->f_pos = proc_file->f_pos; - return(err); + return err; } static int open_host_sock(char *host_file, int *filter_out) @@ -354,13 +311,13 @@ static int open_host_sock(char *host_file, int *filter_out) strcpy(end, "/rw"); *filter_out = 1; fd = os_connect_socket(host_file); - if(fd > 0) - return(fd); + if (fd > 0) + return fd; strcpy(end, "/r"); *filter_out = 0; fd = os_connect_socket(host_file); - return(fd); + return fd; } static void free_contents(struct hppfs_data *head) @@ -368,9 +325,10 @@ static void free_contents(struct hppfs_data *head) struct hppfs_data *data; struct list_head *ele, *next; - if(head == NULL) return; + if (head == NULL) + return; - list_for_each_safe(ele, next, &head->list){ + list_for_each_safe(ele, next, &head->list) { data = list_entry(ele, struct hppfs_data, list); kfree(data); } @@ -387,8 +345,8 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter, err = -ENOMEM; data = kmalloc(sizeof(*data), GFP_KERNEL); - if(data == NULL){ - printk("hppfs_get_data : head allocation failed\n"); + if (data == NULL) { + printk(KERN_ERR "hppfs_get_data : head allocation failed\n"); goto failed; } @@ -397,36 +355,36 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter, head = data; *size_out = 0; - if(filter){ - while((n = read_proc(proc_file, data->contents, + if (filter) { + while ((n = read_proc(proc_file, data->contents, sizeof(data->contents), NULL, 0)) > 0) os_write_file(fd, data->contents, n); err = os_shutdown_socket(fd, 0, 1); - if(err){ - printk("hppfs_get_data : failed to shut down " + if (err) { + printk(KERN_ERR "hppfs_get_data : failed to shut down " "socket\n"); goto failed_free; } } - while(1){ + while (1) { n = os_read_file(fd, data->contents, sizeof(data->contents)); - if(n < 0){ + if (n < 0) { err = n; - printk("hppfs_get_data : read failed, errno = %d\n", - err); + printk(KERN_ERR "hppfs_get_data : read failed, " + "errno = %d\n", err); goto failed_free; - } - else if(n == 0) + } else if (n == 0) break; *size_out += n; - if(n < sizeof(data->contents)) + if (n < sizeof(data->contents)) break; new = kmalloc(sizeof(*data), GFP_KERNEL); - if(new == 0){ - printk("hppfs_get_data : data allocation failed\n"); + if (new == 0) { + printk(KERN_ERR "hppfs_get_data : data allocation " + "failed\n"); err = -ENOMEM; goto failed_free; } @@ -435,12 +393,12 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter, list_add(&new->list, &data->list); data = new; } - return(head); + return head; failed_free: free_contents(head); failed: - return(ERR_PTR(err)); + return ERR_PTR(err); } static struct hppfs_private *hppfs_data(void) @@ -448,77 +406,79 @@ static struct hppfs_private *hppfs_data(void) struct hppfs_private *data; data = kmalloc(sizeof(*data), GFP_KERNEL); - if(data == NULL) - return(data); + if (data == NULL) + return data; *data = ((struct hppfs_private ) { .host_fd = -1, .len = -1, .contents = NULL } ); - return(data); + return data; } static int file_mode(int fmode) { - if(fmode == (FMODE_READ | FMODE_WRITE)) - return(O_RDWR); - if(fmode == FMODE_READ) - return(O_RDONLY); - if(fmode == FMODE_WRITE) - return(O_WRONLY); - return(0); + if (fmode == (FMODE_READ | FMODE_WRITE)) + return O_RDWR; + if (fmode == FMODE_READ) + return O_RDONLY; + if (fmode == FMODE_WRITE) + return O_WRONLY; + return 0; } static int hppfs_open(struct inode *inode, struct file *file) { struct hppfs_private *data; struct dentry *proc_dentry; + struct vfsmount *proc_mnt; char *host_file; int err, fd, type, filter; err = -ENOMEM; data = hppfs_data(); - if(data == NULL) + if (data == NULL) goto out; host_file = dentry_name(file->f_path.dentry, strlen("/rw")); - if(host_file == NULL) + if (host_file == NULL) goto out_free2; proc_dentry = HPPFS_I(inode)->proc_dentry; + proc_mnt = inode->i_sb->s_fs_info; /* XXX This isn't closed anywhere */ - data->proc_file = dentry_open(dget(proc_dentry), NULL, + data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), file_mode(file->f_mode)); err = PTR_ERR(data->proc_file); - if(IS_ERR(data->proc_file)) + if (IS_ERR(data->proc_file)) goto out_free1; type = os_file_type(host_file); - if(type == OS_TYPE_FILE){ + if (type == OS_TYPE_FILE) { fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); - if(fd >= 0) + if (fd >= 0) data->host_fd = fd; - else printk("hppfs_open : failed to open '%s', errno = %d\n", - host_file, -fd); + else + printk(KERN_ERR "hppfs_open : failed to open '%s', " + "errno = %d\n", host_file, -fd); data->contents = NULL; - } - else if(type == OS_TYPE_DIR){ + } else if (type == OS_TYPE_DIR) { fd = open_host_sock(host_file, &filter); - if(fd > 0){ + if (fd > 0) { data->contents = hppfs_get_data(fd, filter, data->proc_file, file, &data->len); - if(!IS_ERR(data->contents)) + if (!IS_ERR(data->contents)) data->host_fd = fd; - } - else printk("hppfs_open : failed to open a socket in " - "'%s', errno = %d\n", host_file, -fd); + } else + printk(KERN_ERR "hppfs_open : failed to open a socket " + "in '%s', errno = %d\n", host_file, -fd); } kfree(host_file); file->private_data = data; - return(0); + return 0; out_free1: kfree(host_file); @@ -526,34 +486,36 @@ static int hppfs_open(struct inode *inode, struct file *file) free_contents(data->contents); kfree(data); out: - return(err); + return err; } static int hppfs_dir_open(struct inode *inode, struct file *file) { struct hppfs_private *data; struct dentry *proc_dentry; + struct vfsmount *proc_mnt; int err; err = -ENOMEM; data = hppfs_data(); - if(data == NULL) + if (data == NULL) goto out; proc_dentry = HPPFS_I(inode)->proc_dentry; - data->proc_file = dentry_open(dget(proc_dentry), NULL, + proc_mnt = inode->i_sb->s_fs_info; + data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), file_mode(file->f_mode)); err = PTR_ERR(data->proc_file); - if(IS_ERR(data->proc_file)) + if (IS_ERR(data->proc_file)) goto out_free; file->private_data = data; - return(0); + return 0; out_free: kfree(data); out: - return(err); + return err; } static loff_t hppfs_llseek(struct file *file, loff_t off, int where) @@ -564,13 +526,13 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where) loff_t ret; llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; - if(llseek != NULL){ + if (llseek != NULL) { ret = (*llseek)(proc_file, off, where); - if(ret < 0) - return(ret); + if (ret < 0) + return ret; } - return(default_llseek(file, off, where)); + return default_llseek(file, off, where); } static const struct file_operations hppfs_file_fops = { @@ -592,11 +554,11 @@ static int hppfs_filldir(void *d, const char *name, int size, { struct hppfs_dirent *dirent = d; - if(file_removed(dirent->dentry, name)) - return(0); + if (file_removed(dirent->dentry, name)) + return 0; - return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, - inode, type)); + return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, + inode, type); } static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) @@ -607,7 +569,8 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) struct hppfs_dirent dirent = ((struct hppfs_dirent) { .vfs_dirent = ent, .filldir = filldir, - .dentry = file->f_path.dentry } ); + .dentry = file->f_path.dentry + }); int err; readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; @@ -616,12 +579,12 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) err = (*readdir)(proc_file, &dirent, hppfs_filldir); file->f_pos = proc_file->f_pos; - return(err); + return err; } static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) { - return(0); + return 0; } static const struct file_operations hppfs_dir_fops = { @@ -639,7 +602,7 @@ static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) sf->f_files = 0; sf->f_ffree = 0; sf->f_type = HPPFS_SUPER_MAGIC; - return(0); + return 0; } static struct inode *hppfs_alloc_inode(struct super_block *sb) @@ -647,12 +610,12 @@ static struct inode *hppfs_alloc_inode(struct super_block *sb) struct hppfs_inode_info *hi; hi = kmalloc(sizeof(*hi), GFP_KERNEL); - if(hi == NULL) - return(NULL); + if (!hi) + return NULL; - *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL }); + hi->proc_dentry = NULL; inode_init_once(&hi->vfs_inode); - return(&hi->vfs_inode); + return &hi->vfs_inode; } void hppfs_delete_inode(struct inode *ino) @@ -665,21 +628,31 @@ static void hppfs_destroy_inode(struct inode *inode) kfree(HPPFS_I(inode)); } +static void hppfs_put_super(struct super_block *sb) +{ + mntput(sb->s_fs_info); +} + static const struct super_operations hppfs_sbops = { .alloc_inode = hppfs_alloc_inode, .destroy_inode = hppfs_destroy_inode, .delete_inode = hppfs_delete_inode, .statfs = hppfs_statfs, + .put_super = hppfs_put_super, }; -static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) +static int hppfs_readlink(struct dentry *dentry, char __user *buffer, + int buflen) { struct file *proc_file; struct dentry *proc_dentry; + struct vfsmount *proc_mnt; int ret; proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); + proc_mnt = dentry->d_sb->s_fs_info; + + proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); if (IS_ERR(proc_file)) return PTR_ERR(proc_file); @@ -694,10 +667,13 @@ static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct file *proc_file; struct dentry *proc_dentry; + struct vfsmount *proc_mnt; void *ret; proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); + proc_mnt = dentry->d_sb->s_fs_info; + + proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); if (IS_ERR(proc_file)) return proc_file; @@ -717,70 +693,72 @@ static const struct inode_operations hppfs_link_iops = { .follow_link = hppfs_follow_link, }; -static int init_inode(struct inode *inode, struct dentry *dentry) +static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) { - if(S_ISDIR(dentry->d_inode->i_mode)){ + struct inode *proc_ino = dentry->d_inode; + struct inode *inode = new_inode(sb); + + if (!inode) + return ERR_PTR(-ENOMEM); + + if (S_ISDIR(dentry->d_inode->i_mode)) { inode->i_op = &hppfs_dir_iops; inode->i_fop = &hppfs_dir_fops; - } - else if(S_ISLNK(dentry->d_inode->i_mode)){ + } else if (S_ISLNK(dentry->d_inode->i_mode)) { inode->i_op = &hppfs_link_iops; inode->i_fop = &hppfs_file_fops; - } - else { + } else { inode->i_op = &hppfs_file_iops; inode->i_fop = &hppfs_file_fops; } HPPFS_I(inode)->proc_dentry = dentry; - return(0); + inode->i_uid = proc_ino->i_uid; + inode->i_gid = proc_ino->i_gid; + inode->i_atime = proc_ino->i_atime; + inode->i_mtime = proc_ino->i_mtime; + inode->i_ctime = proc_ino->i_ctime; + inode->i_ino = proc_ino->i_ino; + inode->i_mode = proc_ino->i_mode; + inode->i_nlink = proc_ino->i_nlink; + inode->i_size = proc_ino->i_size; + inode->i_blocks = proc_ino->i_blocks; + + return 0; } static int hppfs_fill_super(struct super_block *sb, void *d, int silent) { struct inode *root_inode; - struct file_system_type *procfs; - struct super_block *proc_sb; - int err; + struct vfsmount *proc_mnt; + int err = -ENOENT; - err = -ENOENT; - procfs = get_fs_type("proc"); - if(procfs == NULL) + proc_mnt = do_kern_mount("proc", 0, "proc", NULL); + if (IS_ERR(proc_mnt)) goto out; - if(list_empty(&procfs->fs_supers)) - goto out; - - proc_sb = list_entry(procfs->fs_supers.next, struct super_block, - s_instances); - sb->s_blocksize = 1024; sb->s_blocksize_bits = 10; sb->s_magic = HPPFS_SUPER_MAGIC; sb->s_op = &hppfs_sbops; - - root_inode = hppfs_iget(sb); - if (IS_ERR(root_inode)) { - err = PTR_ERR(root_inode); - goto out; - } - - err = init_inode(root_inode, proc_sb->s_root); - if(err) - goto out_put; + sb->s_fs_info = proc_mnt; err = -ENOMEM; - sb->s_root = d_alloc_root(root_inode); - if(sb->s_root == NULL) - goto out_put; + root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root); + if (!root_inode) + goto out_mntput; - hppfs_read_inode(root_inode); + sb->s_root = d_alloc_root(root_inode); + if (!sb->s_root) + goto out_iput; - return(0); + return 0; - out_put: + out_iput: iput(root_inode); + out_mntput: + mntput(proc_mnt); out: return(err); } @@ -802,7 +780,7 @@ static struct file_system_type hppfs_type = { static int __init init_hppfs(void) { - return(register_filesystem(&hppfs_type)); + return register_filesystem(&hppfs_type); } static void __exit exit_hppfs(void) @@ -813,14 +791,3 @@ static void __exit exit_hppfs(void) module_init(init_hppfs) module_exit(exit_hppfs) MODULE_LICENSE("GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index eee9487ae47f..6846785fe904 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -954,7 +954,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size) FMODE_WRITE | FMODE_READ, &hugetlbfs_file_operations); if (!file) - goto out_inode; + goto out_dentry; /* inode is already attached */ return file; diff --git a/fs/namei.c b/fs/namei.c index 6b7a0eef4090..8cf9bb9c2fc0 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -106,7 +106,7 @@ * any extra contention... */ -static int link_path_walk(const char *name, struct nameidata *nd); +static int __link_path_walk(const char *name, struct nameidata *nd); /* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the @@ -563,6 +563,37 @@ walk_init_root(const char *name, struct nameidata *nd) return 1; } +/* + * Wrapper to retry pathname resolution whenever the underlying + * file system returns an ESTALE. + * + * Retry the whole path once, forcing real lookup requests + * instead of relying on the dcache. + */ +static __always_inline int link_path_walk(const char *name, struct nameidata *nd) +{ + struct path save = nd->path; + int result; + + /* make sure the stuff we saved doesn't go away */ + dget(save.dentry); + mntget(save.mnt); + + result = __link_path_walk(name, nd); + if (result == -ESTALE) { + /* nd->path had been dropped */ + nd->path = save; + dget(nd->path.dentry); + mntget(nd->path.mnt); + nd->flags |= LOOKUP_REVAL; + result = __link_path_walk(name, nd); + } + + path_put(&save); + + return result; +} + static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) { int res = 0; @@ -1020,36 +1051,6 @@ return_err: return err; } -/* - * Wrapper to retry pathname resolution whenever the underlying - * file system returns an ESTALE. - * - * Retry the whole path once, forcing real lookup requests - * instead of relying on the dcache. - */ -static int link_path_walk(const char *name, struct nameidata *nd) -{ - struct nameidata save = *nd; - int result; - - /* make sure the stuff we saved doesn't go away */ - dget(save.path.dentry); - mntget(save.path.mnt); - - result = __link_path_walk(name, nd); - if (result == -ESTALE) { - *nd = save; - dget(nd->path.dentry); - mntget(nd->path.mnt); - nd->flags |= LOOKUP_REVAL; - result = __link_path_walk(name, nd); - } - - path_put(&save.path); - - return result; -} - static int path_walk(const char *name, struct nameidata *nd) { current->total_link_count = 0; diff --git a/fs/open.c b/fs/open.c index 54198538b67e..a4b12022edaa 100644 --- a/fs/open.c +++ b/fs/open.c @@ -903,6 +903,18 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) int error; struct file *f; + /* + * We must always pass in a valid mount pointer. Historically + * callers got away with not passing it, but we must enforce this at + * the earliest possible point now to avoid strange problems deep in the + * filesystem stack. + */ + if (!mnt) { + printk(KERN_WARNING "%s called with NULL vfsmount\n", __func__); + dump_stack(); + return ERR_PTR(-EINVAL); + } + error = -ENFILE; f = get_empty_filp(); if (f == NULL) { diff --git a/fs/pipe.c b/fs/pipe.c index 3c185b6527bc..8be381bbcb54 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -957,13 +957,10 @@ struct file *create_write_pipe(void) struct dentry *dentry; struct qstr name = { .name = "" }; - f = get_empty_filp(); - if (!f) - return ERR_PTR(-ENFILE); err = -ENFILE; inode = get_pipe_inode(); if (!inode) - goto err_file; + goto err; err = -ENOMEM; dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); @@ -978,22 +975,24 @@ struct file *create_write_pipe(void) */ dentry->d_flags &= ~DCACHE_UNHASHED; d_instantiate(dentry, inode); - f->f_path.mnt = mntget(pipe_mnt); - f->f_path.dentry = dentry; + + err = -ENFILE; + f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipe_fops); + if (!f) + goto err_dentry; f->f_mapping = inode->i_mapping; f->f_flags = O_WRONLY; - f->f_op = &write_pipe_fops; - f->f_mode = FMODE_WRITE; f->f_version = 0; return f; + err_dentry: + dput(dentry); err_inode: free_pipe_info(inode); iput(inode); - err_file: - put_filp(f); + err: return ERR_PTR(err); } diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index eba037b3338f..344b9b96cc56 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -191,28 +191,11 @@ static struct dentry *get_xa_file_dentry(const struct inode *inode, dput(xadir); if (err) xafile = ERR_PTR(err); - return xafile; -} - -/* Opens a file pointer to the attribute associated with inode */ -static struct file *open_xa_file(const struct inode *inode, const char *name, - int flags) -{ - struct dentry *xafile; - struct file *fp; - - xafile = get_xa_file_dentry(inode, name, flags); - if (IS_ERR(xafile)) - return ERR_PTR(PTR_ERR(xafile)); else if (!xafile->d_inode) { dput(xafile); - return ERR_PTR(-ENODATA); + xafile = ERR_PTR(-ENODATA); } - - fp = dentry_open(xafile, NULL, O_RDWR); - /* dentry_open dputs the dentry if it fails */ - - return fp; + return xafile; } /* @@ -228,9 +211,8 @@ static struct file *open_xa_file(const struct inode *inode, const char *name, * we're called with i_mutex held, so there are no worries about the directory * changing underneath us. */ -static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) +static int __xattr_readdir(struct inode *inode, void *dirent, filldir_t filldir) { - struct inode *inode = filp->f_path.dentry->d_inode; struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ INITIALIZE_PATH(path_to_entry); struct buffer_head *bh; @@ -374,23 +356,16 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) * */ static -int xattr_readdir(struct file *file, filldir_t filler, void *buf) +int xattr_readdir(struct inode *inode, filldir_t filler, void *buf) { - struct inode *inode = file->f_path.dentry->d_inode; - int res = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out; + int res = -ENOENT; mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); -// down(&inode->i_zombie); - res = -ENOENT; if (!IS_DEADDIR(inode)) { lock_kernel(); - res = __xattr_readdir(file, buf, filler); + res = __xattr_readdir(inode, buf, filler); unlock_kernel(); } -// up(&inode->i_zombie); mutex_unlock(&inode->i_mutex); - out: return res; } @@ -442,7 +417,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, size_t buffer_size, int flags) { int err = 0; - struct file *fp; + struct dentry *dentry; struct page *page; char *data; struct address_space *mapping; @@ -460,18 +435,18 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, xahash = xattr_hash(buffer, buffer_size); open_file: - fp = open_xa_file(inode, name, flags); - if (IS_ERR(fp)) { - err = PTR_ERR(fp); + dentry = get_xa_file_dentry(inode, name, flags); + if (IS_ERR(dentry)) { + err = PTR_ERR(dentry); goto out; } - xinode = fp->f_path.dentry->d_inode; + xinode = dentry->d_inode; REISERFS_I(inode)->i_flags |= i_has_xattr_dir; /* we need to copy it off.. */ if (xinode->i_nlink > 1) { - fput(fp); + dput(dentry); err = reiserfs_xattr_del(inode, name); if (err < 0) goto out; @@ -485,7 +460,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, newattrs.ia_size = buffer_size; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR); - err = notify_change(fp->f_path.dentry, &newattrs); + err = notify_change(dentry, &newattrs); if (err) goto out_filp; @@ -518,15 +493,14 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, rxh->h_hash = cpu_to_le32(xahash); } - err = reiserfs_prepare_write(fp, page, page_offset, + err = reiserfs_prepare_write(NULL, page, page_offset, page_offset + chunk + skip); if (!err) { if (buffer) memcpy(data + skip, buffer + buffer_pos, chunk); - err = - reiserfs_commit_write(fp, page, page_offset, - page_offset + chunk + - skip); + err = reiserfs_commit_write(NULL, page, page_offset, + page_offset + chunk + + skip); } unlock_page(page); reiserfs_put_page(page); @@ -548,7 +522,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, out_filp: mutex_unlock(&xinode->i_mutex); - fput(fp); + dput(dentry); out: return err; @@ -562,7 +536,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, size_t buffer_size) { ssize_t err = 0; - struct file *fp; + struct dentry *dentry; size_t isize; size_t file_pos = 0; size_t buffer_pos = 0; @@ -578,13 +552,13 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, if (get_inode_sd_version(inode) == STAT_DATA_V1) return -EOPNOTSUPP; - fp = open_xa_file(inode, name, FL_READONLY); - if (IS_ERR(fp)) { - err = PTR_ERR(fp); + dentry = get_xa_file_dentry(inode, name, FL_READONLY); + if (IS_ERR(dentry)) { + err = PTR_ERR(dentry); goto out; } - xinode = fp->f_path.dentry->d_inode; + xinode = dentry->d_inode; isize = xinode->i_size; REISERFS_I(inode)->i_flags |= i_has_xattr_dir; @@ -652,7 +626,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, } out_dput: - fput(fp); + dput(dentry); out: return err; @@ -742,7 +716,6 @@ reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen, /* This is called w/ inode->i_mutex downed */ int reiserfs_delete_xattrs(struct inode *inode) { - struct file *fp; struct dentry *dir, *root; int err = 0; @@ -763,15 +736,8 @@ int reiserfs_delete_xattrs(struct inode *inode) return 0; } - fp = dentry_open(dir, NULL, O_RDWR); - if (IS_ERR(fp)) { - err = PTR_ERR(fp); - /* dentry_open dputs the dentry if it fails */ - goto out; - } - lock_kernel(); - err = xattr_readdir(fp, reiserfs_delete_xattrs_filler, dir); + err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir); if (err) { unlock_kernel(); goto out_dir; @@ -791,7 +757,7 @@ int reiserfs_delete_xattrs(struct inode *inode) unlock_kernel(); out_dir: - fput(fp); + dput(dir); out: if (!err) @@ -833,7 +799,6 @@ reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen, int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) { - struct file *fp; struct dentry *dir; int err = 0; struct reiserfs_chown_buf buf; @@ -857,13 +822,6 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) goto out; } - fp = dentry_open(dir, NULL, O_RDWR); - if (IS_ERR(fp)) { - err = PTR_ERR(fp); - /* dentry_open dputs the dentry if it fails */ - goto out; - } - lock_kernel(); attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); @@ -871,7 +829,7 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) buf.attrs = attrs; buf.inode = inode; - err = xattr_readdir(fp, reiserfs_chown_xattrs_filler, &buf); + err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf); if (err) { unlock_kernel(); goto out_dir; @@ -881,7 +839,7 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) unlock_kernel(); out_dir: - fput(fp); + dput(dir); out: attrs->ia_valid = ia_valid; @@ -1029,7 +987,6 @@ reiserfs_listxattr_filler(void *buf, const char *name, int namelen, */ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) { - struct file *fp; struct dentry *dir; int err = 0; struct reiserfs_listxattr_buf buf; @@ -1052,13 +1009,6 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) goto out; } - fp = dentry_open(dir, NULL, O_RDWR); - if (IS_ERR(fp)) { - err = PTR_ERR(fp); - /* dentry_open dputs the dentry if it fails */ - goto out; - } - buf.r_buf = buffer; buf.r_size = buffer ? size : 0; buf.r_pos = 0; @@ -1066,7 +1016,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; - err = xattr_readdir(fp, reiserfs_listxattr_filler, &buf); + err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf); if (err) goto out_dir; @@ -1076,7 +1026,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) err = buf.r_pos; out_dir: - fput(fp); + dput(dir); out: reiserfs_read_unlock_xattr_i(dentry->d_inode); diff --git a/fs/super.c b/fs/super.c index d0a941a4e620..09008dbd264e 100644 --- a/fs/super.c +++ b/fs/super.c @@ -945,6 +945,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) put_filesystem(type); return mnt; } +EXPORT_SYMBOL_GPL(do_kern_mount); struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) { diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index a271c87c4472..baa663e69388 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/kobject.h> +#include <linux/kallsyms.h> #include <linux/namei.h> #include <linux/poll.h> #include <linux/list.h> @@ -86,7 +87,12 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer * The code works fine with PAGE_SIZE return but it's likely to * indicate truncated result or overflow in normal use cases. */ - BUG_ON(count >= (ssize_t)PAGE_SIZE); + if (count >= (ssize_t)PAGE_SIZE) { + print_symbol("fill_read_buffer: %s returned bad count\n", + (unsigned long)ops->show); + /* Try to struggle along */ + count = PAGE_SIZE - 1; + } if (count >= 0) { buffer->needs_read_fill = 0; buffer->count = count; diff --git a/include/asm-avr32/byteorder.h b/include/asm-avr32/byteorder.h index 402ff4125cdc..d77b48ba7338 100644 --- a/include/asm-avr32/byteorder.h +++ b/include/asm-avr32/byteorder.h @@ -12,8 +12,14 @@ extern unsigned long __builtin_bswap_32(unsigned long x); extern unsigned short __builtin_bswap_16(unsigned short x); #endif +/* + * avr32-linux-gcc versions earlier than 4.2 improperly sign-extends + * the result. + */ +#if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2) #define __arch__swab32(x) __builtin_bswap_32(x) #define __arch__swab16(x) __builtin_bswap_16(x) +#endif #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) # define __BYTEORDER_HAS_U64__ diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h index 542421460a12..532975ecfe10 100644 --- a/include/asm-sparc64/cpudata.h +++ b/include/asm-sparc64/cpudata.h @@ -86,6 +86,8 @@ extern struct trap_per_cpu trap_block[NR_CPUS]; extern void init_cur_cpu_trap(struct thread_info *); extern void setup_tba(void); extern int ncpus_probed; +extern void __init cpu_probe(void); +extern const struct seq_operations cpuinfo_op; extern unsigned long real_hard_smp_processor_id(void); diff --git a/include/asm-sparc64/dcu.h b/include/asm-sparc64/dcu.h index ecbed2ae548f..0f704e106a1b 100644 --- a/include/asm-sparc64/dcu.h +++ b/include/asm-sparc64/dcu.h @@ -1,26 +1,27 @@ -/* $Id: dcu.h,v 1.2 2001/03/01 23:23:33 davem Exp $ */ #ifndef _SPARC64_DCU_H #define _SPARC64_DCU_H +#include <linux/const.h> + /* UltraSparc-III Data Cache Unit Control Register */ -#define DCU_CP 0x0002000000000000 /* Physical Cache Enable w/o mmu*/ -#define DCU_CV 0x0001000000000000 /* Virtual Cache Enable w/o mmu */ -#define DCU_ME 0x0000800000000000 /* NC-store Merging Enable */ -#define DCU_RE 0x0000400000000000 /* RAW bypass Enable */ -#define DCU_PE 0x0000200000000000 /* PCache Enable */ -#define DCU_HPE 0x0000100000000000 /* HW prefetch Enable */ -#define DCU_SPE 0x0000080000000000 /* SW prefetch Enable */ -#define DCU_SL 0x0000040000000000 /* Secondary load steering Enab */ -#define DCU_WE 0x0000020000000000 /* WCache enable */ -#define DCU_PM 0x000001fe00000000 /* PA Watchpoint Byte Mask */ -#define DCU_VM 0x00000001fe000000 /* VA Watchpoint Byte Mask */ -#define DCU_PR 0x0000000001000000 /* PA Watchpoint Read Enable */ -#define DCU_PW 0x0000000000800000 /* PA Watchpoint Write Enable */ -#define DCU_VR 0x0000000000400000 /* VA Watchpoint Read Enable */ -#define DCU_VW 0x0000000000200000 /* VA Watchpoint Write Enable */ -#define DCU_DM 0x0000000000000008 /* DMMU Enable */ -#define DCU_IM 0x0000000000000004 /* IMMU Enable */ -#define DCU_DC 0x0000000000000002 /* Data Cache Enable */ -#define DCU_IC 0x0000000000000001 /* Instruction Cache Enable */ +#define DCU_CP _AC(0x0002000000000000,UL) /* Phys Cache Enable w/o mmu */ +#define DCU_CV _AC(0x0001000000000000,UL) /* Virt Cache Enable w/o mmu */ +#define DCU_ME _AC(0x0000800000000000,UL) /* NC-store Merging Enable */ +#define DCU_RE _AC(0x0000400000000000,UL) /* RAW bypass Enable */ +#define DCU_PE _AC(0x0000200000000000,UL) /* PCache Enable */ +#define DCU_HPE _AC(0x0000100000000000,UL) /* HW prefetch Enable */ +#define DCU_SPE _AC(0x0000080000000000,UL) /* SW prefetch Enable */ +#define DCU_SL _AC(0x0000040000000000,UL) /* Secondary ld-steering Enab*/ +#define DCU_WE _AC(0x0000020000000000,UL) /* WCache enable */ +#define DCU_PM _AC(0x000001fe00000000,UL) /* PA Watchpoint Byte Mask */ +#define DCU_VM _AC(0x00000001fe000000,UL) /* VA Watchpoint Byte Mask */ +#define DCU_PR _AC(0x0000000001000000,UL) /* PA Watchpoint Read Enable */ +#define DCU_PW _AC(0x0000000000800000,UL) /* PA Watchpoint Write Enable*/ +#define DCU_VR _AC(0x0000000000400000,UL) /* VA Watchpoint Read Enable */ +#define DCU_VW _AC(0x0000000000200000,UL) /* VA Watchpoint Write Enable*/ +#define DCU_DM _AC(0x0000000000000008,UL) /* DMMU Enable */ +#define DCU_IM _AC(0x0000000000000004,UL) /* IMMU Enable */ +#define DCU_DC _AC(0x0000000000000002,UL) /* Data Cache Enable */ +#define DCU_IC _AC(0x0000000000000001,UL) /* Instruction Cache Enable */ #endif /* _SPARC64_DCU_H */ diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index 30cb76b47be1..0bb9bf531745 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -64,6 +64,7 @@ extern unsigned char virt_irq_alloc(unsigned int dev_handle, extern void virt_irq_free(unsigned int virt_irq); #endif +extern void __init init_IRQ(void); extern void fixup_irqs(void); static inline void set_softint(unsigned long bits) diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 3167ccff64f8..549e45266b68 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -23,9 +23,9 @@ #include <asm/page.h> #include <asm/processor.h> -/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB). - * The page copy blockops can use 0x2000000 to 0x4000000. - * The TSB is mapped in the 0x4000000 to 0x6000000 range. +/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). + * The page copy blockops can use 0x6000000 to 0x8000000. + * The TSB is mapped in the 0x8000000 to 0xa000000 range. * The PROM resides in an area spanning 0xf0000000 to 0x100000000. * The vmalloc area spans 0x100000000 to 0x200000000. * Since modules need to be in the lowest 32-bits of the address space, @@ -33,8 +33,8 @@ * There is a single static kernel PMD which maps from 0x0 to address * 0x400000000. */ -#define TLBTEMP_BASE _AC(0x0000000002000000,UL) -#define TSBMAP_BASE _AC(0x0000000004000000,UL) +#define TLBTEMP_BASE _AC(0x0000000006000000,UL) +#define TSBMAP_BASE _AC(0x0000000008000000,UL) #define MODULES_VADDR _AC(0x0000000010000000,UL) #define MODULES_LEN _AC(0x00000000e0000000,UL) #define MODULES_END _AC(0x00000000f0000000,UL) @@ -761,6 +761,8 @@ extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long, extern void pgtable_cache_init(void); extern void sun4v_register_fault_status(void); extern void sun4v_ktsb_register(void); +extern void __init cheetah_ecache_flush_init(void); +extern void sun4v_patch_tlb_handlers(void); extern unsigned long cmdline_memory_size; diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h index 8da484c19822..885b6a1dcae4 100644 --- a/include/asm-sparc64/processor.h +++ b/include/asm-sparc64/processor.h @@ -37,6 +37,9 @@ #endif #define TASK_SIZE ((unsigned long)-VPTE_SIZE) +#define TASK_SIZE_OF(tsk) \ + (test_tsk_thread_flag(tsk,TIF_32BIT) ? \ + (1UL << 32UL) : TASK_SIZE) #ifdef __KERNEL__ #define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE) diff --git a/include/asm-sparc64/stacktrace.h b/include/asm-sparc64/stacktrace.h new file mode 100644 index 000000000000..6cee39adf6d6 --- /dev/null +++ b/include/asm-sparc64/stacktrace.h @@ -0,0 +1,6 @@ +#ifndef _SPARC64_STACKTRACE_H +#define _SPARC64_STACKTRACE_H + +extern void stack_trace_flush(void); + +#endif /* _SPARC64_STACKTRACE_H */ diff --git a/include/asm-sparc64/timer.h b/include/asm-sparc64/timer.h index ccbd69448866..5b779fd1f788 100644 --- a/include/asm-sparc64/timer.h +++ b/include/asm-sparc64/timer.h @@ -1,14 +1,13 @@ -/* $Id: timer.h,v 1.3 2000/05/09 17:40:15 davem Exp $ - * timer.h: System timer definitions for sun5. +/* timer.h: System timer definitions for sun5. * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net) */ #ifndef _SPARC64_TIMER_H #define _SPARC64_TIMER_H #include <linux/types.h> - +#include <linux/init.h> struct sparc64_tick_ops { unsigned long (*get_tick)(void); @@ -25,5 +24,7 @@ struct sparc64_tick_ops { extern struct sparc64_tick_ops *tick_ops; extern unsigned long sparc64_get_clock_tick(unsigned int cpu); +extern void __devinit setup_sparc64_timer(void); +extern void __init time_init(void); #endif /* _SPARC64_TIMER_H */ diff --git a/include/asm-x86/lguest_hcall.h b/include/asm-x86/lguest_hcall.h index 758b9a5d4539..f239e7069cab 100644 --- a/include/asm-x86/lguest_hcall.h +++ b/include/asm-x86/lguest_hcall.h @@ -27,7 +27,7 @@ #ifndef __ASSEMBLY__ #include <asm/hw_irq.h> -/*G:031 First, how does our Guest contact the Host to ask for privileged +/*G:031 But first, how does our Guest contact the Host to ask for privileged * operations? There are two ways: the direct way is to make a "hypercall", * to make requests of the Host Itself. * diff --git a/include/asm-x86/mach-rdc321x/gpio.h b/include/asm-x86/mach-rdc321x/gpio.h index db31b929b990..acce0b7d397b 100644 --- a/include/asm-x86/mach-rdc321x/gpio.h +++ b/include/asm-x86/mach-rdc321x/gpio.h @@ -5,19 +5,20 @@ extern int rdc_gpio_get_value(unsigned gpio); extern void rdc_gpio_set_value(unsigned gpio, int value); extern int rdc_gpio_direction_input(unsigned gpio); extern int rdc_gpio_direction_output(unsigned gpio, int value); - +extern int rdc_gpio_request(unsigned gpio, const char *label); +extern void rdc_gpio_free(unsigned gpio); +extern void __init rdc321x_gpio_setup(void); /* Wrappers for the arch-neutral GPIO API */ static inline int gpio_request(unsigned gpio, const char *label) { - /* Not yet implemented */ - return 0; + return rdc_gpio_request(gpio, label); } static inline void gpio_free(unsigned gpio) { - /* Not yet implemented */ + rdc_gpio_free(gpio); } static inline int gpio_direction_input(unsigned gpio) diff --git a/include/asm-x86/mach-rdc321x/rdc321x_defs.h b/include/asm-x86/mach-rdc321x/rdc321x_defs.h index 838ba8f64fd3..c8e9c8bed3d0 100644 --- a/include/asm-x86/mach-rdc321x/rdc321x_defs.h +++ b/include/asm-x86/mach-rdc321x/rdc321x_defs.h @@ -3,4 +3,10 @@ /* General purpose configuration and data registers */ #define RDC3210_CFGREG_ADDR 0x0CF8 #define RDC3210_CFGREG_DATA 0x0CFC -#define RDC_MAX_GPIO 0x3A + +#define RDC321X_GPIO_CTRL_REG1 0x48 +#define RDC321X_GPIO_CTRL_REG2 0x84 +#define RDC321X_GPIO_DATA_REG1 0x4c +#define RDC321X_GPIO_DATA_REG2 0x88 + +#define RDC321X_MAX_GPIO 58 diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 174b87738714..9cf472aeb9ce 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h @@ -85,6 +85,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC; #define __PAGE_KERNEL_RX (__PAGE_KERNEL_EXEC & ~_PAGE_RW) #define __PAGE_KERNEL_EXEC_NOCACHE (__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT) #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT) +#define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD) #define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER) #define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT) #define __PAGE_KERNEL_LARGE (__PAGE_KERNEL | _PAGE_PSE) @@ -101,6 +102,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC; #define PAGE_KERNEL_EXEC MAKE_GLOBAL(__PAGE_KERNEL_EXEC) #define PAGE_KERNEL_RX MAKE_GLOBAL(__PAGE_KERNEL_RX) #define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE) +#define PAGE_KERNEL_UC_MINUS MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS) #define PAGE_KERNEL_EXEC_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE) #define PAGE_KERNEL_LARGE MAKE_GLOBAL(__PAGE_KERNEL_LARGE) #define PAGE_KERNEL_LARGE_EXEC MAKE_GLOBAL(__PAGE_KERNEL_LARGE_EXEC) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6b72a4584086..51e6b1e520e6 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -38,8 +38,8 @@ struct cpuidle_state { unsigned int power_usage; /* in mW */ unsigned int target_residency; /* in US */ - unsigned int usage; - unsigned int time; /* in US */ + unsigned long long usage; + unsigned long long time; /* in US */ int (*enter) (struct cpuidle_device *dev, struct cpuidle_state *state); diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h index 589be3e1f3ac..e7217dc58f39 100644 --- a/include/linux/lguest_launcher.h +++ b/include/linux/lguest_launcher.h @@ -16,6 +16,10 @@ * a new device, we simply need to write a new virtio driver and create support * for it in the Launcher: this code won't need to change. * + * Virtio devices are also used by kvm, so we can simply reuse their optimized + * device drivers. And one day when everyone uses virtio, my plan will be + * complete. Bwahahahah! + * * Devices are described by a simplified ID, a status byte, and some "config" * bytes which describe this device's configuration. This is placed by the * Launcher just above the top of physical memory: @@ -26,7 +30,7 @@ struct lguest_device_desc { /* The number of virtqueues (first in config array) */ __u8 num_vq; /* The number of bytes of feature bits. Multiply by 2: one for host - * features and one for guest acknowledgements. */ + * features and one for Guest acknowledgements. */ __u8 feature_len; /* The number of bytes of the config array after virtqueues. */ __u8 config_len; diff --git a/include/linux/libata.h b/include/linux/libata.h index a05f60013642..269cdba09578 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -463,6 +463,7 @@ struct ata_queued_cmd { unsigned int sect_size; unsigned int nbytes; + unsigned int extrabytes; unsigned int curbytes; struct scatterlist *cursg; @@ -1336,6 +1337,11 @@ static inline struct ata_queued_cmd *ata_qc_from_tag(struct ata_port *ap, return NULL; } +static inline unsigned int ata_qc_raw_nbytes(struct ata_queued_cmd *qc) +{ + return qc->nbytes - min(qc->extrabytes, qc->nbytes); +} + static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf) { memset(tf, 0, sizeof(*tf)); @@ -1354,7 +1360,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->flags = 0; qc->cursg = NULL; qc->cursg_ofs = 0; - qc->nbytes = qc->curbytes = 0; + qc->nbytes = qc->extrabytes = qc->curbytes = 0; qc->n_elem = 0; qc->err_mask = 0; qc->sect_size = ATA_SECT_SIZE; diff --git a/include/linux/pci.h b/include/linux/pci.h index b7e4b633c69b..ea760e519c46 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -513,7 +513,6 @@ int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap); int pci_find_ext_capability(struct pci_dev *dev, int cap); int pci_find_ht_capability(struct pci_dev *dev, int ht_cap); int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap); -void pcie_wait_pending_transaction(struct pci_dev *dev); struct pci_bus *pci_find_next_bus(const struct pci_bus *from); struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, @@ -884,9 +883,6 @@ static inline int pci_find_ext_capability(struct pci_dev *dev, int cap) return 0; } -static inline void pcie_wait_pending_transaction(struct pci_dev *dev) -{ } - /* Power management related routines */ static inline int pci_save_state(struct pci_dev *dev) { diff --git a/include/linux/sched.h b/include/linux/sched.h index fed07d03364e..6a1e7afb099b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1541,6 +1541,12 @@ static inline void idle_task_exit(void) {} extern void sched_idle_next(void); +#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP) +extern void wake_up_idle_cpu(int cpu); +#else +static inline void wake_up_idle_cpu(int cpu) { } +#endif + #ifdef CONFIG_SCHED_DEBUG extern unsigned int sysctl_sched_latency; extern unsigned int sysctl_sched_min_granularity; diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index 2692ec9389ca..1f999ec8d08c 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h @@ -9,3 +9,6 @@ /* device can't resume correctly so reset it instead */ #define USB_QUIRK_RESET_RESUME 0x00000002 + +/* device can't handle Set-Interface requests */ +#define USB_QUIRK_NO_SET_INTF 0x00000004 diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index cee0623b3c7b..0a40dfa44c9f 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -50,7 +50,9 @@ US_FLAG(CAPACITY_HEURISTICS, 0x00001000) \ /* sometimes sizes is too big */ \ US_FLAG(MAX_SECTORS_MIN,0x00002000) \ - /* Sets max_sectors to arch min */ + /* Sets max_sectors to arch min */ \ + US_FLAG(BULK_IGNORE_TAG,0x00004000) \ + /* Ignore tag mismatch in bulk operations */ #define US_FLAG(name, value) US_FL_##name = value , diff --git a/include/net/neighbour.h b/include/net/neighbour.h index ebbfb509822e..64a5f0120b52 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -218,6 +218,10 @@ extern unsigned long neigh_rand_reach_time(unsigned long base); extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, struct sk_buff *skb); extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat); +extern struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, + struct net *net, + const void *key, + struct net_device *dev); extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev); extern void neigh_app_ns(struct neighbour *n); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 619c53bc3cd2..0d255ae008b6 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -204,6 +204,7 @@ struct xfrm_state * transformer. */ const struct xfrm_type *type; struct xfrm_mode *inner_mode; + struct xfrm_mode *inner_mode_iaf; struct xfrm_mode *outer_mode; /* Security context */ @@ -387,6 +388,27 @@ enum { extern int xfrm_register_mode(struct xfrm_mode *mode, int family); extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family); +static inline int xfrm_af2proto(unsigned int family) +{ + switch(family) { + case AF_INET: + return IPPROTO_IPIP; + case AF_INET6: + return IPPROTO_IPV6; + default: + return 0; + } +} + +static inline struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto) +{ + if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) || + (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6)) + return x->inner_mode; + else + return x->inner_mode_iaf; +} + struct xfrm_tmpl { /* id in template is interpreted as: @@ -530,6 +552,9 @@ struct xfrm_mode_skb_cb { __be16 id; __be16 frag_off; + /* IP header length (excluding options or extension headers). */ + u8 ihl; + /* TOS for IPv4, class for IPv6. */ u8 tos; @@ -539,6 +564,9 @@ struct xfrm_mode_skb_cb { /* Protocol for IPv4, NH for IPv6. */ u8 protocol; + /* Option length for IPv4, zero for IPv6. */ + u8 optlen; + /* Used by IPv6 only, zero for IPv4. */ u8 flow_lbl[3]; }; @@ -1253,6 +1281,7 @@ extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr); extern int xfrm_output_resume(struct sk_buff *skb, int err); extern int xfrm_output(struct sk_buff *skb); +extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm4_extract_header(struct sk_buff *skb); extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, diff --git a/kernel/acct.c b/kernel/acct.c index 521dfa53cb99..91e1cfd734d2 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -58,6 +58,7 @@ #include <asm/uaccess.h> #include <asm/div64.h> #include <linux/blkdev.h> /* sector_div */ +#include <linux/pid_namespace.h> /* * These constants control the amount of freespace that suspend and @@ -74,7 +75,7 @@ int acct_parm[3] = {4, 2, 30}; /* * External references and all of the globals. */ -static void do_acct_process(struct file *); +static void do_acct_process(struct pid_namespace *ns, struct file *); /* * This structure is used so that all the data protected by lock @@ -86,6 +87,7 @@ struct acct_glbs { volatile int active; volatile int needcheck; struct file *file; + struct pid_namespace *ns; struct timer_list timer; }; @@ -175,9 +177,11 @@ out: static void acct_file_reopen(struct file *file) { struct file *old_acct = NULL; + struct pid_namespace *old_ns = NULL; if (acct_globals.file) { old_acct = acct_globals.file; + old_ns = acct_globals.ns; del_timer(&acct_globals.timer); acct_globals.active = 0; acct_globals.needcheck = 0; @@ -185,6 +189,7 @@ static void acct_file_reopen(struct file *file) } if (file) { acct_globals.file = file; + acct_globals.ns = get_pid_ns(task_active_pid_ns(current)); acct_globals.needcheck = 0; acct_globals.active = 1; /* It's been deleted if it was used before so this is safe */ @@ -196,8 +201,9 @@ static void acct_file_reopen(struct file *file) if (old_acct) { mnt_unpin(old_acct->f_path.mnt); spin_unlock(&acct_globals.lock); - do_acct_process(old_acct); + do_acct_process(old_ns, old_acct); filp_close(old_acct, NULL); + put_pid_ns(old_ns); spin_lock(&acct_globals.lock); } } @@ -419,7 +425,7 @@ static u32 encode_float(u64 value) /* * do_acct_process does all actual work. Caller holds the reference to file. */ -static void do_acct_process(struct file *file) +static void do_acct_process(struct pid_namespace *ns, struct file *file) { struct pacct_struct *pacct = ¤t->signal->pacct; acct_t ac; @@ -481,8 +487,10 @@ static void do_acct_process(struct file *file) ac.ac_gid16 = current->gid; #endif #if ACCT_VERSION==3 - ac.ac_pid = current->tgid; - ac.ac_ppid = current->real_parent->tgid; + ac.ac_pid = task_tgid_nr_ns(current, ns); + rcu_read_lock(); + ac.ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), ns); + rcu_read_unlock(); #endif spin_lock_irq(¤t->sighand->siglock); @@ -578,6 +586,7 @@ void acct_collect(long exitcode, int group_dead) void acct_process(void) { struct file *file = NULL; + struct pid_namespace *ns; /* * accelerate the common fastpath: @@ -592,8 +601,10 @@ void acct_process(void) return; } get_file(file); + ns = get_pid_ns(acct_globals.ns); spin_unlock(&acct_globals.lock); - do_acct_process(file); + do_acct_process(ns, file); fput(file); + put_pid_ns(ns); } diff --git a/kernel/futex.c b/kernel/futex.c index 06968cd79200..87a6428cb5b6 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2158,7 +2158,7 @@ static struct file_system_type futex_fs_type = { .kill_sb = kill_anon_super, }; -static int __init init(void) +static int __init futex_init(void) { u32 curval; int i; @@ -2194,4 +2194,4 @@ static int __init init(void) return 0; } -__initcall(init); +__initcall(futex_init); diff --git a/kernel/marker.c b/kernel/marker.c index 48a4ea5afffd..041c33e3e95c 100644 --- a/kernel/marker.c +++ b/kernel/marker.c @@ -104,18 +104,18 @@ void marker_probe_cb(const struct marker *mdata, void *call_private, char ptype; /* - * disabling preemption to make sure the teardown of the callbacks can - * be done correctly when they are in modules and they insure RCU read - * coherency. + * preempt_disable does two things : disabling preemption to make sure + * the teardown of the callbacks can be done correctly when they are in + * modules and they insure RCU read coherency. */ preempt_disable(); - ptype = ACCESS_ONCE(mdata->ptype); + ptype = mdata->ptype; if (likely(!ptype)) { marker_probe_func *func; /* Must read the ptype before ptr. They are not data dependant, * so we put an explicit smp_rmb() here. */ smp_rmb(); - func = ACCESS_ONCE(mdata->single.func); + func = mdata->single.func; /* Must read the ptr before private data. They are not data * dependant, so we put an explicit smp_rmb() here. */ smp_rmb(); @@ -133,7 +133,7 @@ void marker_probe_cb(const struct marker *mdata, void *call_private, * in the fast path, so put the explicit barrier here. */ smp_read_barrier_depends(); - multi = ACCESS_ONCE(mdata->multi); + multi = mdata->multi; for (i = 0; multi[i].func; i++) { va_start(args, fmt); multi[i].func(multi[i].probe_private, call_private, fmt, @@ -161,13 +161,13 @@ void marker_probe_cb_noarg(const struct marker *mdata, char ptype; preempt_disable(); - ptype = ACCESS_ONCE(mdata->ptype); + ptype = mdata->ptype; if (likely(!ptype)) { marker_probe_func *func; /* Must read the ptype before ptr. They are not data dependant, * so we put an explicit smp_rmb() here. */ smp_rmb(); - func = ACCESS_ONCE(mdata->single.func); + func = mdata->single.func; /* Must read the ptr before private data. They are not data * dependant, so we put an explicit smp_rmb() here. */ smp_rmb(); @@ -183,7 +183,7 @@ void marker_probe_cb_noarg(const struct marker *mdata, * in the fast path, so put the explicit barrier here. */ smp_read_barrier_depends(); - multi = ACCESS_ONCE(mdata->multi); + multi = mdata->multi; for (i = 0; multi[i].func; i++) multi[i].func(multi[i].probe_private, call_private, fmt, &args); @@ -551,9 +551,9 @@ static int set_marker(struct marker_entry **entry, struct marker *elem, /* * Disable a marker and its probe callback. - * Note: only after a synchronize_sched() issued after setting elem->call to the - * empty function insures that the original callback is not used anymore. This - * insured by preemption disabling around the call site. + * Note: only waiting an RCU period after setting elem->call to the empty + * function insures that the original callback is not used anymore. This insured + * by preempt_disable around the call site. */ static void disable_marker(struct marker *elem) { @@ -565,8 +565,8 @@ static void disable_marker(struct marker *elem) elem->ptype = 0; /* single probe */ /* * Leave the private data and id there, because removal is racy and - * should be done only after a synchronize_sched(). These are never used - * until the next initialization anyway. + * should be done only after an RCU period. These are never used until + * the next initialization anyway. */ } @@ -601,9 +601,6 @@ void marker_update_probe_range(struct marker *begin, /* * Update probes, removing the faulty probes. - * Issues a synchronize_sched() when no reference to the module passed - * as parameter is found in the probes so the probe module can be - * safely unloaded from now on. * * Internal callback only changed before the first probe is connected to it. * Single probe private data can only be changed on 0 -> 1 and 2 -> 1 diff --git a/kernel/printk.c b/kernel/printk.c index 9adc2a473e6e..c46a20a19a15 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -616,6 +616,40 @@ asmlinkage int printk(const char *fmt, ...) /* cpu currently holding logbuf_lock */ static volatile unsigned int printk_cpu = UINT_MAX; +/* + * Can we actually use the console at this time on this cpu? + * + * Console drivers may assume that per-cpu resources have + * been allocated. So unless they're explicitly marked as + * being able to cope (CON_ANYTIME) don't call them until + * this CPU is officially up. + */ +static inline int can_use_console(unsigned int cpu) +{ + return cpu_online(cpu) || have_callable_console(); +} + +/* + * Try to get console ownership to actually show the kernel + * messages from a 'printk'. Return true (and with the + * console_semaphore held, and 'console_locked' set) if it + * is successful, false otherwise. + * + * This gets called with the 'logbuf_lock' spinlock held and + * interrupts disabled. It should return with 'lockbuf_lock' + * released but interrupts still disabled. + */ +static int acquire_console_semaphore_for_printk(unsigned int cpu) +{ + int retval = 0; + + if (can_use_console(cpu)) + retval = !try_acquire_console_sem(); + printk_cpu = UINT_MAX; + spin_unlock(&logbuf_lock); + return retval; +} + const char printk_recursion_bug_msg [] = KERN_CRIT "BUG: recent printk recursion!\n"; static int printk_recursion_bug; @@ -725,43 +759,22 @@ asmlinkage int vprintk(const char *fmt, va_list args) log_level_unknown = 1; } - if (!down_trylock(&console_sem)) { - /* - * We own the drivers. We can drop the spinlock and - * let release_console_sem() print the text, maybe ... - */ - console_locked = 1; - printk_cpu = UINT_MAX; - spin_unlock(&logbuf_lock); + /* + * Try to acquire and then immediately release the + * console semaphore. The release will do all the + * actual magic (print out buffers, wake up klogd, + * etc). + * + * The acquire_console_semaphore_for_printk() function + * will release 'logbuf_lock' regardless of whether it + * actually gets the semaphore or not. + */ + if (acquire_console_semaphore_for_printk(this_cpu)) + release_console_sem(); - /* - * Console drivers may assume that per-cpu resources have - * been allocated. So unless they're explicitly marked as - * being able to cope (CON_ANYTIME) don't call them until - * this CPU is officially up. - */ - if (cpu_online(smp_processor_id()) || have_callable_console()) { - console_may_schedule = 0; - release_console_sem(); - } else { - /* Release by hand to avoid flushing the buffer. */ - console_locked = 0; - up(&console_sem); - } - lockdep_on(); - raw_local_irq_restore(flags); - } else { - /* - * Someone else owns the drivers. We drop the spinlock, which - * allows the semaphore holder to proceed and to call the - * console drivers with the output which we just produced. - */ - printk_cpu = UINT_MAX; - spin_unlock(&logbuf_lock); - lockdep_on(); + lockdep_on(); out_restore_irqs: - raw_local_irq_restore(flags); - } + raw_local_irq_restore(flags); preempt_enable(); return printed_len; diff --git a/kernel/relay.c b/kernel/relay.c index 4c035a8a248c..d6204a485818 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -736,7 +736,7 @@ static int relay_file_open(struct inode *inode, struct file *filp) kref_get(&buf->kref); filp->private_data = buf; - return 0; + return nonseekable_open(inode, filp); } /** @@ -1056,6 +1056,10 @@ static struct pipe_buf_operations relay_pipe_buf_ops = { .get = generic_pipe_buf_get, }; +static void relay_page_release(struct splice_pipe_desc *spd, unsigned int i) +{ +} + /* * subbuf_splice_actor - splice up to one subbuf's worth of data */ @@ -1083,6 +1087,7 @@ static int subbuf_splice_actor(struct file *in, .partial = partial, .flags = flags, .ops = &relay_pipe_buf_ops, + .spd_release = relay_page_release, }; if (rbuf->subbufs_produced == rbuf->subbufs_consumed) diff --git a/kernel/sched.c b/kernel/sched.c index 28c73f07efb2..8dcdec6fe0fe 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1052,6 +1052,49 @@ static void resched_cpu(int cpu) resched_task(cpu_curr(cpu)); spin_unlock_irqrestore(&rq->lock, flags); } + +#ifdef CONFIG_NO_HZ +/* + * When add_timer_on() enqueues a timer into the timer wheel of an + * idle CPU then this timer might expire before the next timer event + * which is scheduled to wake up that CPU. In case of a completely + * idle system the next event might even be infinite time into the + * future. wake_up_idle_cpu() ensures that the CPU is woken up and + * leaves the inner idle loop so the newly added timer is taken into + * account when the CPU goes back to idle and evaluates the timer + * wheel for the next timer event. + */ +void wake_up_idle_cpu(int cpu) +{ + struct rq *rq = cpu_rq(cpu); + + if (cpu == smp_processor_id()) + return; + + /* + * This is safe, as this function is called with the timer + * wheel base lock of (cpu) held. When the CPU is on the way + * to idle and has not yet set rq->curr to idle then it will + * be serialized on the timer wheel base lock and take the new + * timer into account automatically. + */ + if (rq->curr != rq->idle) + return; + + /* + * We can set TIF_RESCHED on the idle task of the other CPU + * lockless. The worst case is that the other CPU runs the + * idle task through an additional NOOP schedule() + */ + set_tsk_thread_flag(rq->idle, TIF_NEED_RESCHED); + + /* NEED_RESCHED must be visible before we test polling */ + smp_mb(); + if (!tsk_is_polling(rq->idle)) + smp_send_reschedule(cpu); +} +#endif + #else static void __resched_task(struct task_struct *p, int tif_bit) { diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 278534bbca95..7f60097d443a 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -174,7 +174,7 @@ static void clocksource_check_watchdog(struct clocksource *cs) if (watchdog) del_timer(&watchdog_timer); watchdog = cs; - init_timer_deferrable(&watchdog_timer); + init_timer(&watchdog_timer); watchdog_timer.function = clocksource_watchdog; /* Reset watchdog cycles */ diff --git a/kernel/timer.c b/kernel/timer.c index 99b00a25f88b..b024106daa70 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -451,10 +451,18 @@ void add_timer_on(struct timer_list *timer, int cpu) spin_lock_irqsave(&base->lock, flags); timer_set_base(timer, base); internal_add_timer(base, timer); + /* + * Check whether the other CPU is idle and needs to be + * triggered to reevaluate the timer wheel when nohz is + * active. We are protected against the other CPU fiddling + * with the timer by holding the timer base lock. This also + * makes sure that a CPU on the way to idle can not evaluate + * the timer wheel. + */ + wake_up_idle_cpu(cpu); spin_unlock_irqrestore(&base->lock, flags); } - /** * mod_timer - modify a timer's timeout * @timer: the timer to be modified diff --git a/mm/bootmem.c b/mm/bootmem.c index f6ff4337b424..2ccea700968f 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -125,6 +125,7 @@ static int __init reserve_bootmem_core(bootmem_data_t *bdata, BUG_ON(!size); BUG_ON(PFN_DOWN(addr) >= bdata->node_low_pfn); BUG_ON(PFN_UP(addr + size) > bdata->node_low_pfn); + BUG_ON(addr < bdata->node_boot_start); sidx = PFN_DOWN(addr - bdata->node_boot_start); eidx = PFN_UP(addr + size - bdata->node_boot_start); @@ -156,21 +157,31 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, unsigned long sidx, eidx; unsigned long i; + BUG_ON(!size); + + /* out range */ + if (addr + size < bdata->node_boot_start || + PFN_DOWN(addr) > bdata->node_low_pfn) + return; /* * round down end of usable mem, partially free pages are * considered reserved. */ - BUG_ON(!size); - BUG_ON(PFN_DOWN(addr + size) > bdata->node_low_pfn); - if (addr < bdata->last_success) + if (addr >= bdata->node_boot_start && addr < bdata->last_success) bdata->last_success = addr; /* - * Round up the beginning of the address. + * Round up to index to the range. */ - sidx = PFN_UP(addr) - PFN_DOWN(bdata->node_boot_start); + if (PFN_UP(addr) > PFN_DOWN(bdata->node_boot_start)) + sidx = PFN_UP(addr) - PFN_DOWN(bdata->node_boot_start); + else + sidx = 0; + eidx = PFN_DOWN(addr + size - bdata->node_boot_start); + if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start)) + eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start); for (i = sidx; i < eidx; i++) { if (unlikely(!test_and_clear_bit(i, bdata->node_bootmem_map))) @@ -421,7 +432,9 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size, void __init free_bootmem(unsigned long addr, unsigned long size) { - free_bootmem_core(NODE_DATA(0)->bdata, addr, size); + bootmem_data_t *bdata; + list_for_each_entry(bdata, &bdata_list, list) + free_bootmem_core(bdata, addr, size); } unsigned long __init free_all_bootmem(void) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 74c1b6b0b37b..51c9e2c01640 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -401,12 +401,20 @@ static void return_unused_surplus_pages(unsigned long unused_resv_pages) struct page *page; unsigned long nr_pages; + /* + * We want to release as many surplus pages as possible, spread + * evenly across all nodes. Iterate across all nodes until we + * can no longer free unreserved surplus pages. This occurs when + * the nodes with surplus pages have no free pages. + */ + unsigned long remaining_iterations = num_online_nodes(); + /* Uncommit the reservation */ resv_huge_pages -= unused_resv_pages; nr_pages = min(unused_resv_pages, surplus_huge_pages); - while (nr_pages) { + while (remaining_iterations-- && nr_pages) { nid = next_node(nid, node_online_map); if (nid == MAX_NUMNODES) nid = first_node(node_online_map); @@ -424,6 +432,7 @@ static void return_unused_surplus_pages(unsigned long unused_resv_pages) surplus_huge_pages--; surplus_huge_pages_node[nid]--; nr_pages--; + remaining_iterations = num_online_nodes(); } } } @@ -671,9 +680,11 @@ int hugetlb_report_node_meminfo(int nid, char *buf) { return sprintf(buf, "Node %d HugePages_Total: %5u\n" - "Node %d HugePages_Free: %5u\n", + "Node %d HugePages_Free: %5u\n" + "Node %d HugePages_Surp: %5u\n", nid, nr_huge_pages_node[nid], - nid, free_huge_pages_node[nid]); + nid, free_huge_pages_node[nid], + nid, surplus_huge_pages_node[nid]); } /* Return the number pages of memory we physically have, in PAGE_SIZE units. */ diff --git a/mm/slab.c b/mm/slab.c index bb4070e1079f..04b308c3bc54 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1481,7 +1481,7 @@ void __init kmem_cache_init(void) list_add(&cache_cache.next, &cache_chain); cache_cache.colour_off = cache_line_size(); cache_cache.array[smp_processor_id()] = &initarray_cache.cache; - cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE]; + cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node]; /* * struct kmem_cache size depends on nr_node_ids, which @@ -1602,7 +1602,7 @@ void __init kmem_cache_init(void) int nid; for_each_online_node(nid) { - init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], nid); + init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid); init_list(malloc_sizes[INDEX_AC].cs_cachep, &initkmem_list3[SIZE_AC + nid], nid); diff --git a/mm/slub.c b/mm/slub.c index ca71d5b81e4a..84ed734b96b3 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1470,6 +1470,9 @@ static void *__slab_alloc(struct kmem_cache *s, void **object; struct page *new; + /* We handle __GFP_ZERO in the caller */ + gfpflags &= ~__GFP_ZERO; + if (!c->page) goto new_slab; @@ -2685,6 +2688,7 @@ void kfree(const void *x) } EXPORT_SYMBOL(kfree); +#if defined(SLUB_DEBUG) || defined(CONFIG_SLABINFO) static unsigned long count_partial(struct kmem_cache_node *n) { unsigned long flags; @@ -2697,6 +2701,7 @@ static unsigned long count_partial(struct kmem_cache_node *n) spin_unlock_irqrestore(&n->list_lock, flags); return x; } +#endif /* * kmem_cache_shrink removes empty slabs from the partial lists and sorts diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index f0f55875dd6a..ae532f501943 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c @@ -88,6 +88,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) close_file: put_filp(file); + return ERR_PTR(error); + put_dentry: dput(dentry); put_memory: diff --git a/mm/vmscan.c b/mm/vmscan.c index 45711585684e..4046434046e6 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -70,13 +70,6 @@ struct scan_control { int order; - /* - * Pages that have (or should have) IO pending. If we run into - * a lot of these, we're better off waiting a little for IO to - * finish rather than scanning more pages in the VM. - */ - int nr_io_pages; - /* Which cgroup do we reclaim from */ struct mem_cgroup *mem_cgroup; @@ -512,10 +505,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, */ if (sync_writeback == PAGEOUT_IO_SYNC && may_enter_fs) wait_on_page_writeback(page); - else { - sc->nr_io_pages++; + else goto keep_locked; - } } referenced = page_referenced(page, 1, sc->mem_cgroup); @@ -554,10 +545,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, if (PageDirty(page)) { if (sc->order <= PAGE_ALLOC_COSTLY_ORDER && referenced) goto keep_locked; - if (!may_enter_fs) { - sc->nr_io_pages++; + if (!may_enter_fs) goto keep_locked; - } if (!sc->may_writepage) goto keep_locked; @@ -568,10 +557,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, case PAGE_ACTIVATE: goto activate_locked; case PAGE_SUCCESS: - if (PageWriteback(page) || PageDirty(page)) { - sc->nr_io_pages++; + if (PageWriteback(page) || PageDirty(page)) goto keep; - } /* * A synchronous write - probably a ramdisk. Go * ahead and try to reclaim the page. @@ -1344,7 +1331,6 @@ static unsigned long do_try_to_free_pages(struct zone **zones, gfp_t gfp_mask, for (priority = DEF_PRIORITY; priority >= 0; priority--) { sc->nr_scanned = 0; - sc->nr_io_pages = 0; if (!priority) disable_swap_token(); nr_reclaimed += shrink_zones(priority, zones, sc); @@ -1379,8 +1365,7 @@ static unsigned long do_try_to_free_pages(struct zone **zones, gfp_t gfp_mask, } /* Take a nap, wait for some writeback to complete */ - if (sc->nr_scanned && priority < DEF_PRIORITY - 2 && - sc->nr_io_pages > sc->swap_cluster_max) + if (sc->nr_scanned && priority < DEF_PRIORITY - 2) congestion_wait(WRITE, HZ/10); } /* top priority shrink_caches still had more to do? don't OOM, then */ @@ -1514,7 +1499,6 @@ loop_again: if (!priority) disable_swap_token(); - sc.nr_io_pages = 0; all_zones_ok = 1; /* @@ -1607,8 +1591,7 @@ loop_again: * OK, kswapd is getting into trouble. Take a nap, then take * another pass across the zones. */ - if (total_scanned && priority < DEF_PRIORITY - 2 && - sc.nr_io_pages > sc.swap_cluster_max) + if (total_scanned && priority < DEF_PRIORITY - 2) congestion_wait(WRITE, HZ/10); /* diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 8fbcefe10c9f..480ea90e7dcd 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -660,7 +660,7 @@ static int vlan_dev_init(struct net_device *dev) int subclass = 0; /* IFF_BROADCAST|IFF_MULTICAST; ??? */ - dev->flags = real_dev->flags & ~IFF_UP; + dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI); dev->iflink = real_dev->ifindex; dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))) | diff --git a/net/ax25/TODO b/net/ax25/TODO index 4089c49e45cc..69fb4e368d92 100644 --- a/net/ax25/TODO +++ b/net/ax25/TODO @@ -9,10 +9,6 @@ being used. Routes to a device being taken down might be deleted by ax25_rt_device_down but added by somebody else before the device has been deleted fully. -Massive amounts of lock_kernel / unlock_kernel are just a temporary solution to -get around the removal of SOCKOPS_WRAP. A serious locking strategy has to be -implemented. - The ax25_rt_find_route synopsys is pervert but I somehow had to deal with the race caused by the static variable in it's previous implementation. diff --git a/net/core/dev.c b/net/core/dev.c index fcdf03cf3b3f..460e7f99ce3e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3329,7 +3329,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) return -EOPNOTSUPP; case SIOCADDMULTI: - if (!dev->set_multicast_list || + if ((!dev->set_multicast_list && !dev->set_rx_mode) || ifr->ifr_hwaddr.sa_family != AF_UNSPEC) return -EINVAL; if (!netif_device_present(dev)) @@ -3338,7 +3338,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) dev->addr_len, 1); case SIOCDELMULTI: - if (!dev->set_multicast_list || + if ((!dev->set_multicast_list && !dev->set_rx_mode) || ifr->ifr_hwaddr.sa_family != AF_UNSPEC) return -EINVAL; if (!netif_device_present(dev)) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index d9a02b2cc289..19b8e003f150 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -466,6 +466,28 @@ out_neigh_release: goto out; } +struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, + struct net *net, const void *pkey, struct net_device *dev) +{ + struct pneigh_entry *n; + int key_len = tbl->key_len; + u32 hash_val = *(u32 *)(pkey + key_len - 4); + + hash_val ^= (hash_val >> 16); + hash_val ^= hash_val >> 8; + hash_val ^= hash_val >> 4; + hash_val &= PNEIGH_HASHMASK; + + for (n = tbl->phash_buckets[hash_val]; n; n = n->next) { + if (!memcmp(n->key, pkey, key_len) && + (n->net == net) && + (n->dev == dev || !n->dev)) + break; + } + + return n; +} + struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *pkey, struct net_device *dev, int creat) @@ -2803,6 +2825,7 @@ EXPORT_SYMBOL(neigh_table_init_no_netlink); EXPORT_SYMBOL(neigh_update); EXPORT_SYMBOL(pneigh_enqueue); EXPORT_SYMBOL(pneigh_lookup); +EXPORT_SYMBOL_GPL(__pneigh_lookup); #ifdef CONFIG_ARPD EXPORT_SYMBOL(neigh_app_ns); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a13c074dac09..a944e8053e28 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -591,7 +591,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) } if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET)) - goto out_unlock; + goto ende; if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) err = __ip_route_output_key(net, &rt2, &fl); @@ -601,7 +601,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) fl2.fl4_dst = fl.fl4_src; if (ip_route_output_key(net, &rt2, &fl2)) - goto out_unlock; + goto ende; /* Ugh! */ odst = skb_in->dst; @@ -614,7 +614,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) } if (err) - goto out_unlock; + goto ende; err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL, XFRM_LOOKUP_ICMP); diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index b47030ba162b..9c798abce736 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c @@ -39,13 +39,11 @@ static void xfrm4_beet_make_header(struct sk_buff *skb) static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) { struct ip_beet_phdr *ph; - struct iphdr *iph, *top_iph; + struct iphdr *top_iph; int hdrlen, optlen; - iph = ip_hdr(skb); - hdrlen = 0; - optlen = iph->ihl * 4 - sizeof(*iph); + optlen = XFRM_MODE_SKB_CB(skb)->optlen; if (unlikely(optlen)) hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); @@ -53,11 +51,12 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) hdrlen); skb->mac_header = skb->network_header + offsetof(struct iphdr, protocol); - skb->transport_header = skb->network_header + sizeof(*iph); + skb->transport_header = skb->network_header + sizeof(*top_iph); xfrm4_beet_make_header(skb); - ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen); + ph = (struct ip_beet_phdr *) + __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen); top_iph = ip_hdr(skb); diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index 8dee617ee900..584e6d74e3a9 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c @@ -41,7 +41,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) top_iph->ihl = 5; top_iph->version = 4; - top_iph->protocol = x->inner_mode->afinfo->proto; + top_iph->protocol = xfrm_af2proto(skb->dst->ops->family); /* DS disclosed */ top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos, diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index d5a58a818021..8c3180adddbf 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -56,7 +56,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb) { int err; - err = x->inner_mode->afinfo->extract_output(x, skb); + err = xfrm_inner_extract_output(x, skb); if (err) return err; diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index fdeebe68a379..07735ed280d7 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -52,10 +52,12 @@ int xfrm4_extract_header(struct sk_buff *skb) { struct iphdr *iph = ip_hdr(skb); + XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); XFRM_MODE_SKB_CB(skb)->id = iph->id; XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off; XFRM_MODE_SKB_CB(skb)->tos = iph->tos; XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl; + XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph); memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0, sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 51557c27a0cd..452a2ac4eec8 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -676,6 +676,20 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) } } +static struct pneigh_entry *pndisc_check_router(struct net_device *dev, + struct in6_addr *addr, int *is_router) +{ + struct pneigh_entry *n; + + read_lock_bh(&nd_tbl.lock); + n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev); + if (n != NULL) + *is_router = (n->flags & NTF_ROUTER); + read_unlock_bh(&nd_tbl.lock); + + return n; +} + static void ndisc_recv_ns(struct sk_buff *skb) { struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); @@ -692,7 +706,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) struct pneigh_entry *pneigh = NULL; int dad = ipv6_addr_any(saddr); int inc; - int is_router; + int is_router = 0; if (ipv6_addr_is_multicast(&msg->target)) { ND_PRINTK2(KERN_WARNING @@ -790,8 +804,8 @@ static void ndisc_recv_ns(struct sk_buff *skb) if (ipv6_chk_acast_addr(dev, &msg->target) || (idev->cnf.forwarding && (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && - (pneigh = pneigh_lookup(&nd_tbl, &init_net, - &msg->target, dev, 0)) != NULL)) { + (pneigh = pndisc_check_router(dev, &msg->target, + &is_router)) != NULL)) { if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && skb->pkt_type != PACKET_HOST && inc != 0 && @@ -812,7 +826,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) goto out; } - is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding); + is_router = !!(pneigh ? is_router : idev->cnf.forwarding); if (dad) { struct in6_addr maddr; diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index 0527d11c1ae3..d6ce400f585f 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c @@ -45,6 +45,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) skb->mac_header = skb->network_header + offsetof(struct ipv6hdr, nexthdr); skb->transport_header = skb->network_header + sizeof(*top_iph); + __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl); xfrm6_beet_make_header(skb); diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 0c742faaa30b..e20529b4c825 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c @@ -45,7 +45,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl, sizeof(top_iph->flow_lbl)); - top_iph->nexthdr = x->inner_mode->afinfo->proto; + top_iph->nexthdr = xfrm_af2proto(skb->dst->ops->family); dsfield = XFRM_MODE_SKB_CB(skb)->tos; dsfield = INET_ECN_encapsulate(dsfield, dsfield); diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 79ccfb080733..0af823cf7f1f 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -62,7 +62,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) { int err; - err = x->inner_mode->afinfo->extract_output(x, skb); + err = xfrm_inner_extract_output(x, skb); if (err) return err; diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index dc817e035e23..ff1e1db8e236 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -174,10 +174,12 @@ int xfrm6_extract_header(struct sk_buff *skb) { struct ipv6hdr *iph = ipv6_hdr(skb); + XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); XFRM_MODE_SKB_CB(skb)->id = 0; XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; + XFRM_MODE_SKB_CB(skb)->optlen = 0; memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index bc2e15ce7004..7873c392ab4c 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h @@ -405,7 +405,7 @@ typedef struct irnet_socket /* "pppd" interact directly with us on a /dev/ file */ struct file * file; /* File descriptor of this instance */ /* TTY stuff - to keep "pppd" happy */ - struct termios termios; /* Various tty flags */ + struct ktermios termios; /* Various tty flags */ /* Stuff for the control channel */ int event_index; /* Last read in the event log */ diff --git a/net/key/af_key.c b/net/key/af_key.c index 8b5f486ac80f..e9ef9af4a53b 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1219,7 +1219,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, x->sel.prefixlen_s = addr->sadb_address_prefixlen; } - if (!x->sel.family) + if (x->props.mode == XFRM_MODE_TRANSPORT) x->sel.family = x->props.family; if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) { diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 971271602dd0..c22d6b6f2db4 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -322,15 +322,6 @@ next_sge: ctxt->direction = DMA_FROM_DEVICE; clear_bit(RDMACTXT_F_READ_DONE, &ctxt->flags); clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); - if ((ch+1)->rc_discrim == 0) { - /* - * Checked in sq_cq_reap to see if we need to - * be enqueued - */ - set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); - ctxt->next = hdr_ctxt; - hdr_ctxt->next = head; - } /* Prepare READ WR */ memset(&read_wr, 0, sizeof read_wr); @@ -348,7 +339,17 @@ next_sge: rdma_set_ctxt_sge(ctxt, &sge[ch_sge_ary[ch_no].start], &sgl_offset, read_wr.num_sge); - + if (((ch+1)->rc_discrim == 0) && + (read_wr.num_sge == ch_sge_ary[ch_no].count)) { + /* + * Mark the last RDMA_READ with a bit to + * indicate all RPC data has been fetched from + * the client and the RPC needs to be enqueued. + */ + set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags); + ctxt->next = hdr_ctxt; + hdr_ctxt->next = head; + } /* Post the read */ err = svc_rdma_send(xprt, &read_wr); if (err) { diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 62188c6a06dd..75279402ccf4 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -84,14 +84,21 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) { + struct xfrm_mode *inner_mode = x->inner_mode; int err; err = x->outer_mode->afinfo->extract_input(x, skb); if (err) return err; - skb->protocol = x->inner_mode->afinfo->eth_proto; - return x->inner_mode->input2(x, skb); + if (x->sel.family == AF_UNSPEC) { + inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); + if (inner_mode == NULL) + return -EAFNOSUPPORT; + } + + skb->protocol = inner_mode->afinfo->eth_proto; + return inner_mode->input2(x, skb); } EXPORT_SYMBOL(xfrm_prepare_input); @@ -101,6 +108,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) __be32 seq; struct xfrm_state *x; xfrm_address_t *daddr; + struct xfrm_mode *inner_mode; unsigned int family; int decaps = 0; int async = 0; @@ -207,7 +215,15 @@ resume: XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; - if (x->inner_mode->input(x, skb)) { + inner_mode = x->inner_mode; + + if (x->sel.family == AF_UNSPEC) { + inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); + if (inner_mode == NULL) + goto drop; + } + + if (inner_mode->input(x, skb)) { XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR); goto drop; } diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 569d377932c4..2519129c6d21 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -124,7 +124,7 @@ int xfrm_output_resume(struct sk_buff *skb, int err) if (!x) return dst_output(skb); - err = nf_hook(x->inner_mode->afinfo->family, + err = nf_hook(skb->dst->ops->family, NF_INET_POST_ROUTING, skb, NULL, skb->dst->dev, xfrm_output2); if (unlikely(err != 1)) @@ -193,4 +193,20 @@ int xfrm_output(struct sk_buff *skb) return xfrm_output2(skb); } + +int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb) +{ + struct xfrm_mode *inner_mode; + if (x->sel.family == AF_UNSPEC) + inner_mode = xfrm_ip2inner_mode(x, + xfrm_af2proto(skb->dst->ops->family)); + else + inner_mode = x->inner_mode; + + if (inner_mode == NULL) + return -EAFNOSUPPORT; + return inner_mode->afinfo->extract_output(x, skb); +} + EXPORT_SYMBOL_GPL(xfrm_output); +EXPORT_SYMBOL_GPL(xfrm_inner_extract_output); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 7ba65e82941c..58f1f9347b54 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -388,6 +388,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) kfree(x->coaddr); if (x->inner_mode) xfrm_put_mode(x->inner_mode); + if (x->inner_mode_iaf) + xfrm_put_mode(x->inner_mode_iaf); if (x->outer_mode) xfrm_put_mode(x->outer_mode); if (x->type) { @@ -523,6 +525,8 @@ struct xfrm_state *xfrm_state_alloc(void) x->lft.hard_packet_limit = XFRM_INF; x->replay_maxage = 0; x->replay_maxdiff = 0; + x->inner_mode = NULL; + x->inner_mode_iaf = NULL; spin_lock_init(&x->lock); } return x; @@ -796,7 +800,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, selector. */ if (x->km.state == XFRM_STATE_VALID) { - if (!xfrm_selector_match(&x->sel, fl, x->sel.family) || + if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) || !security_xfrm_state_pol_flow_match(x, pol, fl)) continue; if (!best || @@ -1944,6 +1948,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) int xfrm_init_state(struct xfrm_state *x) { struct xfrm_state_afinfo *afinfo; + struct xfrm_mode *inner_mode; int family = x->props.family; int err; @@ -1962,13 +1967,48 @@ int xfrm_init_state(struct xfrm_state *x) goto error; err = -EPROTONOSUPPORT; - x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); - if (x->inner_mode == NULL) - goto error; - if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && - family != x->sel.family) - goto error; + if (x->sel.family != AF_UNSPEC) { + inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); + if (inner_mode == NULL) + goto error; + + if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && + family != x->sel.family) { + xfrm_put_mode(inner_mode); + goto error; + } + + x->inner_mode = inner_mode; + } else { + struct xfrm_mode *inner_mode_iaf; + + inner_mode = xfrm_get_mode(x->props.mode, AF_INET); + if (inner_mode == NULL) + goto error; + + if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) { + xfrm_put_mode(inner_mode); + goto error; + } + + inner_mode_iaf = xfrm_get_mode(x->props.mode, AF_INET6); + if (inner_mode_iaf == NULL) + goto error; + + if (!(inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)) { + xfrm_put_mode(inner_mode_iaf); + goto error; + } + + if (x->props.family == AF_INET) { + x->inner_mode = inner_mode; + x->inner_mode_iaf = inner_mode_iaf; + } else { + x->inner_mode = inner_mode_iaf; + x->inner_mode_iaf = inner_mode; + } + } x->type = xfrm_get_type(x->id.proto, family); if (x->type == NULL) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f971ca5645f8..5d96f2728dc6 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -288,12 +288,9 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); x->props.flags = p->flags; - /* - * Set inner address family if the KM left it as zero. - * See comment in validate_tmpl. - */ - if (!x->sel.family) + if (x->props.mode == XFRM_MODE_TRANSPORT) x->sel.family = p->family; + } /* diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index cfc004e04417..2d20640854b7 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -58,6 +58,9 @@ modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o))) # Stop after building .o files if NOFINAL is set. Makes compile tests quicker _modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules)) +ifneq ($(KBUILD_BUILDHOST),$(ARCH)) + cross_build := 1 +endif # Step 2), invoke modpost # Includes step 3,4 @@ -70,7 +73,8 @@ modpost = scripts/mod/modpost \ $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \ $(if $(CONFIG_MARKERS),-M $(markersfile)) \ - $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) + $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \ + $(if $(cross_build),-c) quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules cmd_modpost = $(modpost) -s diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 9ddf944cce29..348d8687b7c9 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -51,11 +51,13 @@ do { \ sprintf(str + strlen(str), "*"); \ } while(0) +unsigned int cross_build = 0; /** * Check that sizeof(device_id type) are consistent with size of section * in .o file. If in-consistent then userspace and kernel does not agree * on actual size which is a bug. * Also verify that the final entry in the table is all zeros. + * Ignore both checks if build host differ from target host and size differs. **/ static void device_id_check(const char *modname, const char *device_id, unsigned long size, unsigned long id_size, @@ -64,6 +66,8 @@ static void device_id_check(const char *modname, const char *device_id, int i; if (size % id_size || size < id_size) { + if (cross_build != 0) + return; fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo " "of the size of section __mod_%s_device_table=%lu.\n" "Fix definition of struct %s_device_id " diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 695b5d657cf5..110cf243fa4e 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2026,7 +2026,7 @@ int main(int argc, char **argv) int opt; int err; - while ((opt = getopt(argc, argv, "i:I:msSo:awM:K:")) != -1) { + while ((opt = getopt(argc, argv, "i:I:cmsSo:awM:K:")) != -1) { switch (opt) { case 'i': kernel_read = optarg; @@ -2035,6 +2035,9 @@ int main(int argc, char **argv) module_read = optarg; external_module = 1; break; + case 'c': + cross_build = 1; + break; case 'm': modversions = 1; break; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 565c5872407e..09f58e33d227 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -135,6 +135,7 @@ struct elf_info { }; /* file2alias.c */ +extern unsigned int cross_build; void handle_moddevtable(struct module *mod, struct elf_info *info, Elf_Sym *sym, const char *symname); void add_moddevtable(struct buffer *buf, struct module *mod); diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index afe7c9b0732a..cfae8afcc262 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -74,11 +74,6 @@ struct smk_list_entry *smack_list; #define SEQ_READ_FINISHED 1 /* - * Disable concurrent writing open() operations - */ -static struct semaphore smack_write_sem; - -/* * Values for parsing cipso rules * SMK_DIGITLEN: Length of a digit field in a rule. * SMK_CIPSOMIN: Minimum possible cipso rule length. @@ -168,32 +163,7 @@ static struct seq_operations load_seq_ops = { */ static int smk_open_load(struct inode *inode, struct file *file) { - if ((file->f_flags & O_ACCMODE) == O_RDONLY) - return seq_open(file, &load_seq_ops); - - if (down_interruptible(&smack_write_sem)) - return -ERESTARTSYS; - - return 0; -} - -/** - * smk_release_load - release() for /smack/load - * @inode: inode structure representing file - * @file: "load" file pointer - * - * For a reading session, use the seq_file release - * implementation. - * Otherwise, we are at the end of a writing session so - * clean everything up. - */ -static int smk_release_load(struct inode *inode, struct file *file) -{ - if ((file->f_flags & O_ACCMODE) == O_RDONLY) - return seq_release(inode, file); - - up(&smack_write_sem); - return 0; + return seq_open(file, &load_seq_ops); } /** @@ -341,7 +311,7 @@ static const struct file_operations smk_load_ops = { .read = seq_read, .llseek = seq_lseek, .write = smk_write_load, - .release = smk_release_load, + .release = seq_release, }; /** @@ -1011,7 +981,6 @@ static int __init init_smk_fs(void) } } - sema_init(&smack_write_sem, 1); smk_cipso_doi(); smk_unlbl_ambient(NULL); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 569ecaca0e8b..889a897d41ac 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1187,10 +1187,8 @@ static struct i2c_driver aic3x_i2c_driver = { .name = "aic3x I2C Codec", .owner = THIS_MODULE, }, - .id = I2C_DRIVERID_I2CDEV, .attach_adapter = aic3x_i2c_attach, .detach_client = aic3x_i2c_detach, - .command = NULL, }; static struct i2c_client client_template = { |