Commit 58fccf09 authored by James Simmons's avatar James Simmons

Merge bk://linux.bkbits.net/linux-2.5

into maxwell.earthlink.net:/usr/src/linus-2.5
parents d1c8fac1 d632a316
......@@ -162,7 +162,6 @@ LOG := $(patsubst %.sgml, %.log, $(BOOKS))
OUT := $(patsubst %.sgml, %.out, $(BOOKS))
clean:
@rm -f core *~
@rm -f $(BOOKS)
@rm -f $(DVI) $(AUX) $(TEX) $(LOG) $(OUT)
@rm -f $(PNG-parportbook) $(EPS-parportbook)
......
......@@ -4,9 +4,9 @@ SUBLEVEL = 41
EXTRAVERSION =
# *DOCUMENTATION*
# Too see a list of typical targets execute "make help"
# To see a list of typical targets execute "make help"
# More info can be located in ./Documentation/kbuild
# Comments in this file is targeted only to the developer, do not
# Comments in this file are targeted only to the developer, do not
# expect to learn how to build the kernel reading this file.
# We are using a recursive build, so we need to do a little thinking
......@@ -142,7 +142,7 @@ NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
MAKEFILES = $(TOPDIR)/.config
MAKEFILES = .config
GENKSYMS = /sbin/genksyms
DEPMOD = /sbin/depmod
KALLSYMS = /sbin/kallsyms
......@@ -387,17 +387,17 @@ targets += arch/$(ARCH)/vmlinux.lds.s
# Single targets
# ---------------------------------------------------------------------------
%.s: %.c FORCE
%.s: %.c scripts FORCE
+@$(call descend,$(@D),$@)
%.i: %.c FORCE
%.i: %.c scripts FORCE
+@$(call descend,$(@D),$@)
%.o: %.c FORCE
%.o: %.c scripts FORCE
+@$(call descend,$(@D),$@)
%.lst: %.c FORCE
%.lst: %.c scripts FORCE
+@$(call descend,$(@D),$@)
%.s: %.S FORCE
%.s: %.S scripts FORCE
+@$(call descend,$(@D),$@)
%.o: %.S FORCE
%.o: %.S scripts FORCE
+@$(call descend,$(@D),$@)
# FIXME: The asm symlink changes when $(ARCH) changes. That's
......@@ -883,7 +883,7 @@ if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
@set -e; \
$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))';) \
$(cmd_$(1)); \
$(TOPDIR)/scripts/fixdep $(depfile) $@ $(TOPDIR) '$(cmd_$(1))' > $(@D)/.$(@F).tmp; \
scripts/fixdep $(depfile) $@ '$(cmd_$(1))' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
......
......@@ -209,10 +209,10 @@ define rule_cc_ver_c
$(if $($(quiet)cmd_cc_ver_c),echo ' $($(quiet)cmd_cc_ver_c)';) \
$(cmd_cc_ver_c); \
if [ ! -r $(depfile) ]; then exit 1; fi; \
$(TOPDIR)/scripts/fixdep $(depfile) $@ $(TOPDIR) '$(cmd_cc_ver_c)' > $(@D)/.$(@F).tmp; \
scripts/fixdep $(depfile) $@ '$(cmd_cc_ver_c)' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
if [ ! -r $@ ] || cmp -s $@ $@.tmp; then \
touch $(TOPDIR)/include/linux/modversions.h; \
touch include/linux/modversions.h; \
fi; \
mv -f $@.tmp $@
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
......@@ -312,7 +312,7 @@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
$(call if_changed_dep,cc_o_c)
quiet_cmd_cc_lst_c = MKLST $(echo_target)
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && $(TOPDIR)/scripts/makelst $*.o $(TOPDIR)/System.map $(OBJDUMP) > $@
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && sh scripts/makelst $*.o System.map $(OBJDUMP) > $@
%.lst: %.c FORCE
$(call if_changed_dep,cc_lst_c)
......@@ -561,7 +561,7 @@ if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
@set -e; \
$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))';) \
$(cmd_$(1)); \
$(TOPDIR)/scripts/fixdep $(depfile) $@ $(TOPDIR) '$(cmd_$(1))' > $(@D)/.$(@F).tmp; \
scripts/fixdep $(depfile) $@ '$(cmd_$(1))' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
......
......@@ -65,6 +65,14 @@ CONFIG_X86_NUMAQ
You will need a new lynxer.elf file to flash your firmware with - send
email to Martin.Bligh@us.ibm.com
CONFIG_X86_CYCLONE
This patch used the Cyclone performance counter on IBM x440, x360,
and other Summit based systems for calculating gettimeofday. This
fixes problems resulting from TSC skew found in multi-CEC system.
If you are suffering from time skew using a multi-CEC system, say YES.
Otherwise it is safe to say NO.
CONFIG_X86_UP_IOAPIC
An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an
SMP-capable replacement for PC-style interrupt controllers. Most
......
......@@ -52,7 +52,8 @@ endif
HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
libs-y += arch/i386/lib/
core-y += arch/i386/kernel/ arch/i386/mm/ \
core-y += arch/i386/kernel/ \
arch/i386/mm/ \
arch/i386/$(MACHINE)/
drivers-$(CONFIG_MATH_EMULATION) += arch/i386/math-emu/
drivers-$(CONFIG_PCI) += arch/i386/pci/
......
......@@ -12,6 +12,7 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
bootflag.o
obj-y += cpu/
obj-y += timers/
obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
obj-$(CONFIG_MCA) += mca.o
obj-$(CONFIG_X86_MSR) += msr.o
......
This diff is collapsed.
#
# Makefile for x86 timers
#
obj-y := timer.o
obj-y += timer_tsc.o
obj-y += timer_pit.o
obj-$(CONFIG_X86_CYCLONE) += timer_cyclone.o
include $(TOPDIR)/Rules.make
#include <linux/kernel.h>
#include <asm/timer.h>
/* list of externed timers */
extern struct timer_opts timer_pit;
extern struct timer_opts timer_tsc;
/* list of timers, ordered by preference, NULL terminated */
static struct timer_opts* timers[] = {
&timer_tsc,
#ifndef CONFIG_X86_TSC
&timer_pit,
#endif
NULL,
};
/* iterates through the list of timers, returning the first
* one that initializes successfully.
*/
struct timer_opts* select_timer(void)
{
int i = 0;
/* find most preferred working timer */
while (timers[i]) {
if (timers[i]->init)
if (timers[i]->init() == 0)
return timers[i];
++i;
}
panic("select_timer: Cannot find a suitable timer\n");
return NULL;
}
/* Cyclone-timer:
* This code implements timer_ops for the cyclone counter found
* on IBM x440, x360, and other Summit based systems.
*
* Copyright (C) 2002 IBM, John Stultz (johnstul@us.ibm.com)
*/
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/timex.h>
#include <asm/timer.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/fixmap.h>
extern spinlock_t i8253_lock;
/* Number of usecs that the last interrupt was delayed */
static int delay_at_last_interrupt;
#define CYCLONE_CBAR_ADDR 0xFEB00CD0
#define CYCLONE_PMCC_OFFSET 0x51A0
#define CYCLONE_MPMC_OFFSET 0x51D0
#define CYCLONE_MPCS_OFFSET 0x51A8
#define CYCLONE_TIMER_FREQ 100000000
int use_cyclone = 0;
static u32* volatile cyclone_timer; /* Cyclone MPMC0 register */
static u32 last_cyclone_timer;
static void mark_offset_cyclone(void)
{
int count;
spin_lock(&i8253_lock);
/* quickly read the cyclone timer */
if(cyclone_timer)
last_cyclone_timer = cyclone_timer[0];
/* calculate delay_at_last_interrupt */
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
spin_unlock(&i8253_lock);
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
}
static unsigned long get_offset_cyclone(void)
{
u32 offset;
if(!cyclone_timer)
return delay_at_last_interrupt;
/* Read the cyclone timer */
offset = cyclone_timer[0];
/* .. relative to previous jiffy */
offset = offset - last_cyclone_timer;
/* convert cyclone ticks to microseconds */
/* XXX slow, can we speed this up? */
offset = offset/(CYCLONE_TIMER_FREQ/1000000);
/* our adjusted time offset in microseconds */
return delay_at_last_interrupt + offset;
}
static int init_cyclone(void)
{
u32* reg;
u32 base; /* saved cyclone base address */
u32 pageaddr; /* page that contains cyclone_timer register */
u32 offset; /* offset from pageaddr to cyclone_timer register */
int i;
/*make sure we're on a summit box*/
/*XXX need to use proper summit hooks! such as xapic -john*/
if(!use_cyclone) return 0;
printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
/* find base address */
pageaddr = (CYCLONE_CBAR_ADDR)&PAGE_MASK;
offset = (CYCLONE_CBAR_ADDR)&(~PAGE_MASK);
set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
if(!reg){
printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
return 0;
}
base = *reg;
if(!base){
printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
return 0;
}
/* setup PMCC */
pageaddr = (base + CYCLONE_PMCC_OFFSET)&PAGE_MASK;
offset = (base + CYCLONE_PMCC_OFFSET)&(~PAGE_MASK);
set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
if(!reg){
printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
return 0;
}
reg[0] = 0x00000001;
/* setup MPCS */
pageaddr = (base + CYCLONE_MPCS_OFFSET)&PAGE_MASK;
offset = (base + CYCLONE_MPCS_OFFSET)&(~PAGE_MASK);
set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
if(!reg){
printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
return 0;
}
reg[0] = 0x00000001;
/* map in cyclone_timer */
pageaddr = (base + CYCLONE_MPMC_OFFSET)&PAGE_MASK;
offset = (base + CYCLONE_MPMC_OFFSET)&(~PAGE_MASK);
set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
cyclone_timer = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
if(!cyclone_timer){
printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
return 0;
}
/*quick test to make sure its ticking*/
for(i=0; i<3; i++){
u32 old = cyclone_timer[0];
int stall = 100;
while(stall--) barrier();
if(cyclone_timer[0] == old){
printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
cyclone_timer = 0;
return 0;
}
}
/* Everything looks good! */
return 1;
}
#if 0 /* XXX future work */
static void delay_cyclone(unsigned long loops)
{
unsigned long bclock, now;
if(!cyclone_timer)
return;
bclock = cyclone_timer[0];
do {
rep_nop();
now = cyclone_timer[0];
} while ((now-bclock) < loops);
}
#endif
/************************************************************/
/* cyclone timer_opts struct */
struct timer_opts timer_cyclone = {
init: init_cyclone,
mark_offset: mark_offset_cyclone,
get_offset: get_offset_cyclone
};
/*
* This code largely moved from arch/i386/kernel/time.c.
* See comments there for proper credits.
*/
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/device.h>
#include <asm/timer.h>
#include <asm/io.h>
extern spinlock_t i8259A_lock;
extern spinlock_t i8253_lock;
#include "do_timer.h"
static int init_pit(void)
{
return 0;
}
static void mark_offset_pit(void)
{
/* nothing needed */
}
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
*
* However, the pc-audio speaker driver changes the divisor so that
* it gets interrupted rather more often - it loads 64 into the
* counter rather than 11932! This has an adverse impact on
* do_gettimeoffset() -- it stops working! What is also not
* good is that the interval that our timer function gets called
* is no longer 10.0002 ms, but 9.9767 ms. To get around this
* would require using a different timing source. Maybe someone
* could use the RTC - I know that this can interrupt at frequencies
* ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
* it so that at startup, the timer code in sched.c would select
* using either the RTC or the 8253 timer. The decision would be
* based on whether there was any other device around that needed
* to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
* and then do some jiggery to have a version of do_timer that
* advanced the clock by 1/1024 s. Every time that reached over 1/100
* of a second, then do all the old code. If the time was kept correct
* then do_gettimeoffset could just return 0 - there is no low order
* divider that can be accessed.
*
* Ideally, you would be able to use the RTC for the speaker driver,
* but it appears that the speaker driver really needs interrupt more
* often than every 120 us or so.
*
* Anyway, this needs more thought.... pjsg (1993-08-28)
*
* If you are really that interested, you should be reading
* comp.protocols.time.ntp!
*/
static unsigned long get_offset_pit(void)
{
int count;
static int count_p = LATCH; /* for the first call after boot */
static unsigned long jiffies_p = 0;
/*
* cache volatile jiffies temporarily; we have IRQs turned off.
*/
unsigned long jiffies_t;
/* gets recalled with irq locally disabled */
spin_lock(&i8253_lock);
/* timer count may underflow right here */
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
/*
* We do this guaranteed double memory access instead of a _p
* postfix in the previous port access. Wheee, hackady hack
*/
jiffies_t = jiffies;
count |= inb_p(0x40) << 8;
/* VIA686a test code... reset the latch if count > max + 1 */
if (count > LATCH) {
outb_p(0x34, 0x43);
outb_p(LATCH & 0xff, 0x40);
outb(LATCH >> 8, 0x40);
count = LATCH - 1;
}
spin_unlock(&i8253_lock);
/*
* avoiding timer inconsistencies (they are rare, but they happen)...
* there are two kinds of problems that must be avoided here:
* 1. the timer counter underflows
* 2. hardware problem with the timer, not giving us continuous time,
* the counter does small "jumps" upwards on some Pentium systems,
* (see c't 95/10 page 335 for Neptun bug.)
*/
if( jiffies_t == jiffies_p ) {
if( count > count_p ) {
/* the nutcase */
count = do_timer_overflow(count);
}
} else
jiffies_p = jiffies_t;
count_p = count;
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
return count;
}
/* tsc timer_opts struct */
struct timer_opts timer_pit = {
.init = init_pit,
.mark_offset = mark_offset_pit,
.get_offset = get_offset_pit,
};
/*
* This code largely moved from arch/i386/kernel/time.c.
* See comments there for proper credits.
*/
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/timex.h>
#include <linux/errno.h>
#include <asm/timer.h>
#include <asm/io.h>
extern int x86_udelay_tsc;
extern spinlock_t i8253_lock;
static int use_tsc;
/* Number of usecs that the last interrupt was delayed */
static int delay_at_last_interrupt;
static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
/* Cached *multiplier* to convert TSC counts to microseconds.
* (see the equation below).
* Equal to 2^32 * (1 / (clocks per usec) ).
* Initialized in time_init.
*/
unsigned long fast_gettimeoffset_quotient;
static unsigned long get_offset_tsc(void)
{
register unsigned long eax, edx;
/* Read the Time Stamp Counter */
rdtsc(eax,edx);
/* .. relative to previous jiffy (32 bits is enough) */
eax -= last_tsc_low; /* tsc_low delta */
/*
* Time offset = (tsc_low delta) * fast_gettimeoffset_quotient
* = (tsc_low delta) * (usecs_per_clock)
* = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
*
* Using a mull instead of a divl saves up to 31 clock cycles
* in the critical path.
*/
__asm__("mull %2"
:"=a" (eax), "=d" (edx)
:"rm" (fast_gettimeoffset_quotient),
"0" (eax));
/* our adjusted time offset in microseconds */
return delay_at_last_interrupt + edx;
}
static void mark_offset_tsc(void)
{
int count;
/*
* It is important that these two operations happen almost at
* the same time. We do the RDTSC stuff first, since it's
* faster. To avoid any inconsistencies, we need interrupts
* disabled locally.
*/
/*
* Interrupts are just disabled locally since the timer irq
* has the SA_INTERRUPT flag set. -arca
*/
/* read Pentium cycle counter */
rdtscl(last_tsc_low);
spin_lock(&i8253_lock);
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
spin_unlock(&i8253_lock);
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
}
/* ------ Calibrate the TSC -------
* Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
* Too much 64-bit arithmetic here to do this cleanly in C, and for
* accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
* output busy loop as low as possible. We avoid reading the CTC registers
* directly because of the awkward 8-bit access mechanism of the 82C54
* device.
*/
#define CALIBRATE_LATCH (5 * LATCH)
#define CALIBRATE_TIME (5 * 1000020/HZ)
static unsigned long __init calibrate_tsc(void)
{
/* Set the Gate high, disable speaker */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
/*
* Now let's take care of CTC channel 2
*
* Set the Gate high, program CTC channel 2 for mode 0,
* (interrupt on terminal count mode), binary count,
* load 5 * LATCH count, (LSB and MSB) to begin countdown.
*/
outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
{
unsigned long startlow, starthigh;
unsigned long endlow, endhigh;
unsigned long count;
rdtsc(startlow,starthigh);
count = 0;
do {
count++;
} while ((inb(0x61) & 0x20) == 0);
rdtsc(endlow,endhigh);
last_tsc_low = endlow;
/* Error: ECTCNEVERSET */
if (count <= 1)
goto bad_ctc;
/* 64-bit subtract - gcc just messes up with long longs */
__asm__("subl %2,%0\n\t"
"sbbl %3,%1"
:"=a" (endlow), "=d" (endhigh)
:"g" (startlow), "g" (starthigh),
"0" (endlow), "1" (endhigh));
/* Error: ECPUTOOFAST */
if (endhigh)
goto bad_ctc;
/* Error: ECPUTOOSLOW */
if (endlow <= CALIBRATE_TIME)
goto bad_ctc;
__asm__("divl %2"
:"=a" (endlow), "=d" (endhigh)
:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
return endlow;
}
/*
* The CTC wasn't reliable: we got a hit on the very first read,
* or the CPU was so fast/slow that the quotient wouldn't fit in
* 32 bits..
*/
bad_ctc:
return 0;
}
#ifdef CONFIG_CPU_FREQ
static int
time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freq = data;
unsigned int i;
if (!cpu_has_tsc)
return 0;
switch (val) {
case CPUFREQ_PRECHANGE:
if ((freq->old < freq->new) &&
((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) {
cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new);
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old);
}
for (i=0; i<NR_CPUS; i++)
if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i))
cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new);
break;
case CPUFREQ_POSTCHANGE:
if ((freq->new < freq->old) &&
((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) {
cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new);
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old);
}
for (i=0; i<NR_CPUS; i++)
if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i))
cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new);
break;
}
return 0;
}
static struct notifier_block time_cpufreq_notifier_block = {
notifier_call: time_cpufreq_notifier
};
#endif
static int init_tsc(void)
{
/*
* If we have APM enabled or the CPU clock speed is variable
* (CPU stops clock on HLT or slows clock to save power)
* then the TSC timestamps may diverge by up to 1 jiffy from
* 'real time' but nothing will break.
* The most frequent case is that the CPU is "woken" from a halt
* state by the timer interrupt itself, so we get 0 error. In the
* rare cases where a driver would "wake" the CPU and request a
* timestamp, the maximum error is < 1 jiffy. But timestamps are
* still perfectly ordered.
* Note that the TSC counter will be reset if APM suspends
* to disk; this won't break the kernel, though, 'cuz we're
* smart. See arch/i386/kernel/apm.c.
*/
/*
* Firstly we have to do a CPU check for chips with
* a potentially buggy TSC. At this point we haven't run
* the ident/bugs checks so we must run this hook as it
* may turn off the TSC flag.
*
* NOTE: this doesnt yet handle SMP 486 machines where only
* some CPU's have a TSC. Thats never worked and nobody has
* moaned if you have the only one in the world - you fix it!
*/
dodgy_tsc();
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
if (tsc_quotient) {
fast_gettimeoffset_quotient = tsc_quotient;
use_tsc = 1;
/*
* We could be more selective here I suspect
* and just enable this for the next intel chips ?
*/
x86_udelay_tsc = 1;
/* report CPU clock rate in Hz.
* The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
* clock/second. Our precision is about 100 ppm.
*/
{ unsigned long eax=0, edx=1000;
__asm__("divl %2"
:"=a" (cpu_khz), "=d" (edx)
:"r" (tsc_quotient),
"0" (eax), "1" (edx));
printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
}
#ifdef CONFIG_CPU_FREQ
cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
#endif
return 0;
}
}
return -ENODEV;
}
/************************************************************/
/* tsc timer_opts struct */
struct timer_opts timer_tsc = {
.init = init_tsc,
.mark_offset = mark_offset_tsc,
.get_offset = get_offset_tsc,
};
......@@ -689,21 +689,28 @@ static int cdrom_read_mech_status(struct cdrom_device_info *cdi,
static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot)
{
struct cdrom_changer_info info;
struct cdrom_changer_info *info;
int ret;
cdinfo(CD_CHANGER, "entering cdrom_slot_status()\n");
if (cdi->sanyo_slot)
return CDS_NO_INFO;
if ((ret = cdrom_read_mech_status(cdi, &info)))
return ret;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if ((ret = cdrom_read_mech_status(cdi, info)))
goto out_free;
if (info.slots[slot].disc_present)
return CDS_DISC_OK;
if (info->slots[slot].disc_present)
ret = CDS_DISC_OK;
else
return CDS_NO_DISC;
ret = CDS_NO_DISC;
out_free:
kfree(info);
return ret;
}
/* Return the number of slots for an ATAPI/SCSI cdrom,
......@@ -713,15 +720,20 @@ int cdrom_number_of_slots(struct cdrom_device_info *cdi)
{
int status;
int nslots = 1;
struct cdrom_changer_info info;
struct cdrom_changer_info *info;
cdinfo(CD_CHANGER, "entering cdrom_number_of_slots()\n");
/* cdrom_read_mech_status requires a valid value for capacity: */
cdi->capacity = 0;
if ((status = cdrom_read_mech_status(cdi, &info)) == 0)
nslots = info.hdr.nslots;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if ((status = cdrom_read_mech_status(cdi, info)) == 0)
nslots = info->hdr.nslots;
kfree(info);
return nslots;
}
......@@ -755,7 +767,7 @@ static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot)
static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
{
struct cdrom_changer_info info;
struct cdrom_changer_info *info;
int curslot;
int ret;
......@@ -771,10 +783,17 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
return cdrom_load_unload(cdi, -1);
}
if ((ret = cdrom_read_mech_status(cdi, &info)))
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if ((ret = cdrom_read_mech_status(cdi, info))) {
kfree(info);
return ret;
}
curslot = info.hdr.curslot;
curslot = info->hdr.curslot;
kfree(info);
if (cdi->use_count > 1 || keeplocked) {
if (slot == CDSL_CURRENT) {
......@@ -1502,7 +1521,8 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
}
case CDROM_MEDIA_CHANGED: {
struct cdrom_changer_info info;
struct cdrom_changer_info *info;
int changed;
cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
if (!CDROM_CAN(CDC_MEDIA_CHANGED))
......@@ -1515,10 +1535,18 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
if ((unsigned int)arg >= cdi->capacity)
return -EINVAL;
if ((ret = cdrom_read_mech_status(cdi, &info)))
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if ((ret = cdrom_read_mech_status(cdi, info))) {
kfree(info);
return ret;
}
return info.slots[arg].change;
changed = info->slots[arg].change;
kfree(info);
return changed;
}
case CDROM_SET_OPTIONS: {
......
......@@ -137,7 +137,7 @@ include $(TOPDIR)/Rules.make
$(obj)/53c7,8xx.o: $(obj)/53c8xx_d.h $(obj)/53c8xx_u.h
$(obj)/53c7xx.o: $(obj)/53c7xx_d.h $(obj)/53c7xx_u.h
$(obj)/sim710.o: $(obj)/sim710_d.h
$(obj)/53c700.o $(MODVERDIR)/53c700.ver: $(obj)/53c700_d.h
$(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h
# If you want to play with the firmware, uncomment
# GENERATE_FIRMWARE := 1
......
EXTRA_CFLAGS += -I$(TOPDIR)/drivers/scsi
# Adaptec aacraid
obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
......
......@@ -902,10 +902,12 @@ static void tscam(struct Scsi_Host *host)
0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
};
/* I can't believe we need this before we've even done anything. Remove it
* and see if anyone bitches.
for (i = 0; i < 0x10; i++) {
udelay(0xffff);
}
*/
tmport = dev->ioport + 1;
outb(0x08, tmport++);
......@@ -993,8 +995,7 @@ static void tscam(struct Scsi_Host *host)
inb(0x80); /* 2 deskew delay(45ns*2=90ns) */
val &= 0x007f; /* no bsy */
outw(val, tmport);
udelay(0xffff); /* recommanded SCAM selection response time */
udelay(0xffff);
mdelay(128);
val &= 0x00fb; /* after 1ms no msg */
outw(val, tmport);
wait_nomsg:
......@@ -2420,9 +2421,9 @@ static int atp870u_detect(Scsi_Host_Template * tpnt)
k = (inb(tmport) & 0xf3) | 0x10;
outb(k, tmport);
outb((k & 0xdf), tmport);
udelay(0x8000);
mdelay(32);
outb(k, tmport);
udelay(0x8000);
mdelay(32);
tmport = base_io;
outb((host_id | 0x08), tmport);
tmport += 0x18;
......@@ -2539,9 +2540,9 @@ static int atp870u_detect(Scsi_Host_Template * tpnt)
outb(k, tmport);
tmport += 0x03;
outb(0x20, tmport);
udelay(0x8000);
mdelay(32);
outb(0, tmport);
udelay(0x8000);
mdelay(32);
tmport = base_io + 0x5b;
inb(tmport);
tmport -= 0x04;
......@@ -2581,7 +2582,7 @@ static int atp870u_detect(Scsi_Host_Template * tpnt)
shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */
}
shpnt->irq = irq;
restore_flags(flags);
spin_unlock_irqrestore(shpnt->host_lock, flags);
if (dev_id[h] == 0x8081) {
request_region(base_io, 0x60, "atp870u"); /* Register the IO ports that we use */
} else {
......
......@@ -34,11 +34,6 @@
#include "zisofs.h"
/*
* We have no support for "multi volume" CDs, but more and more disks carry
* wrong information within the volume descriptors.
*/
#define IGNORE_WRONG_MULTI_VOLUME_SPECS
#define BEQUIET
#ifdef LEAK_CHECK
......@@ -556,19 +551,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
if (!parse_options((char *) data, &opt))
goto out_freesbi;
#if 0
printk("map = %c\n", opt.map);
printk("rock = %c\n", opt.rock);
printk("joliet = %c\n", opt.joliet);
printk("check = %c\n", opt.check);
printk("cruft = %c\n", opt.cruft);
printk("unhide = %c\n", opt.unhide);
printk("blocksize = %d\n", opt.blocksize);
printk("gid = %d\n", opt.gid);
printk("uid = %d\n", opt.uid);
printk("iocharset = %s\n", opt.iocharset);
#endif
/*
* First of all, get the hardware blocksize for this device.
* If we don't know what it is, or the hardware blocksize is
......@@ -673,19 +655,11 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
if(sbi->s_high_sierra){
rootp = (struct iso_directory_record *) h_pri->root_directory_record;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
if (isonum_723 (h_pri->volume_set_size) != 1)
goto out_no_support;
#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
sbi->s_nzones = isonum_733 (h_pri->volume_space_size);
sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size);
sbi->s_max_size = isonum_733(h_pri->volume_space_size);
} else {
rootp = (struct iso_directory_record *) pri->root_directory_record;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
if (isonum_723 (pri->volume_set_size) != 1)
goto out_no_support;
#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
sbi->s_nzones = isonum_733 (pri->volume_space_size);
sbi->s_log_zone_size = isonum_723 (pri->logical_block_size);
sbi->s_max_size = isonum_733(pri->volume_space_size);
......@@ -898,11 +872,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
orig_zonesize, opt.blocksize);
goto out_freebh;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
out_no_support:
printk(KERN_WARNING "Multi-volume disks not supported.\n");
goto out_freebh;
#endif
out_unknown_format:
if (!silent)
printk(KERN_WARNING "Unable to identify CD-ROM format.\n");
......@@ -1335,28 +1304,7 @@ static void isofs_read_inode(struct inode * inode)
/* get the volume sequence number */
volume_seq_no = isonum_723 (de->volume_sequence_number) ;
/*
* Disable checking if we see any volume number other than 0 or 1.
* We could use the cruft option, but that has multiple purposes, one
* of which is limiting the file size to 16Mb. Thus we silently allow
* volume numbers of 0 to go through without complaining.
*/
if (sbi->s_cruft == 'n' &&
(volume_seq_no != 0) && (volume_seq_no != 1)) {
printk(KERN_WARNING "Warning: defective CD-ROM "
"(volume sequence number %d). "
"Enabling \"cruft\" mount option.\n", volume_seq_no);
sbi->s_cruft = 'y';
}
/* Install the inode operations vector */
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
if (sbi->s_cruft != 'y' &&
(volume_seq_no != 0) && (volume_seq_no != 1)) {
printk(KERN_WARNING "Multi-volume CD somehow got mounted.\n");
} else
#endif /*IGNORE_WRONG_MULTI_VOLUME_SPECS */
{
if (S_ISREG(inode->i_mode)) {
inode->i_fop = &generic_ro_fops;
switch ( ei->i_file_format ) {
......@@ -1379,7 +1327,7 @@ static void isofs_read_inode(struct inode * inode)
/* XXX - parse_rock_ridge_inode() had already set i_rdev. */
init_special_inode(inode, inode->i_mode,
kdev_t_to_nr(inode->i_rdev));
}
out:
if (tmpde)
kfree(tmpde);
......
......@@ -107,7 +107,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index);
again:
error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, page,
error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->entry->cookie, page,
NFS_SERVER(inode)->dtsize, desc->plus);
if (error < 0) {
/* We requested READDIRPLUS, but the server doesn't grok it */
......@@ -341,7 +341,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
status = -ENOMEM;
goto out;
}
desc->error = NFS_PROTO(inode)->readdir(inode, cred, desc->target,
desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->target,
page,
NFS_SERVER(inode)->dtsize,
desc->plus);
......@@ -1022,16 +1022,23 @@ nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
struct nfs_fattr sym_attr;
struct nfs_fh sym_fh;
struct qstr qsymname;
unsigned int maxlen;
int error;
dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
dir->i_ino, dentry->d_name.name, symname);
error = -ENAMETOOLONG;
maxlen = (NFS_PROTO(dir)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN;
if (strlen(symname) > maxlen)
switch (NFS_PROTO(dir)->version) {
case 2:
if (strlen(symname) > NFS2_MAXPATHLEN)
goto out;
break;
case 3:
if (strlen(symname) > NFS3_MAXPATHLEN)
goto out;
default:
break;
}
#ifdef NFS_PARANOIA
if (dentry->d_inode)
......
......@@ -171,7 +171,7 @@ nfs_flushd(struct rpc_task *task)
nfs_pagein_list(&head, server->rpages);
continue;
}
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (nfs_scan_lru_commit_timeout(server, &head)) {
spin_unlock(&nfs_wreq_lock);
nfs_commit_list(&head, FLUSH_AGING);
......
......@@ -716,12 +716,14 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
inode->i_mtime = nfs_time_to_secs(new_mtime);
NFS_MTIME_UPDATE(inode) = fattr->timestamp;
NFS_CACHE_ISIZE(inode) = new_size;
if (fattr->valid & NFS_ATTR_FATTR_V4)
NFS_CHANGE_ATTR(inode) = fattr->change_attr;
inode->i_size = new_isize;
inode->i_mode = fattr->mode;
inode->i_nlink = fattr->nlink;
inode->i_uid = fattr->uid;
inode->i_gid = fattr->gid;
if (fattr->valid & NFS_ATTR_FATTR_V3) {
if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) {
/*
* report the blocks in 512byte units
*/
......@@ -781,7 +783,7 @@ printk("nfs_setattr: revalidate failed, error=%d\n", error);
if (error)
goto out;
error = NFS_PROTO(inode)->setattr(inode, &fattr, attr);
error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
if (error)
goto out;
/*
......@@ -1067,12 +1069,25 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
invalid = 1;
}
if ((fattr->valid & NFS_ATTR_FATTR_V4)
&& NFS_CHANGE_ATTR(inode) != fattr->change_attr) {
#ifdef NFS_DEBUG_VERBOSE
printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n",
inode->i_sb->s_id, inode->i_ino);
#endif
invalid = 1;
}
/* Check Weak Cache Consistency data.
* If size and mtime match the pre-operation values, we can
* assume that any attribute changes were caused by our NFS
* operation, so there's no need to invalidate the caches.
*/
if ((fattr->valid & NFS_ATTR_WCC)
if ((fattr->valid & NFS_ATTR_PRE_CHANGE)
&& NFS_CHANGE_ATTR(inode) == fattr->pre_change_attr) {
invalid = 0;
}
else if ((fattr->valid & NFS_ATTR_WCC)
&& NFS_CACHE_ISIZE(inode) == fattr->pre_size
&& NFS_CACHE_MTIME(inode) == fattr->pre_mtime) {
invalid = 0;
......@@ -1110,12 +1125,15 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
}
}
if (fattr->valid & NFS_ATTR_FATTR_V4)
NFS_CHANGE_ATTR(inode) = fattr->change_attr;
inode->i_mode = fattr->mode;
inode->i_nlink = fattr->nlink;
inode->i_uid = fattr->uid;
inode->i_gid = fattr->gid;
if (fattr->valid & NFS_ATTR_FATTR_V3) {
if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) {
/*
* report the blocks in 512byte units
*/
......
......@@ -107,7 +107,7 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
fattr->du.nfs2.blocksize = ntohl(*p++);
fattr->rdev = ntohl(*p++);
fattr->du.nfs2.blocks = ntohl(*p++);
fattr->fsid = ntohl(*p++);
fattr->fsid_u.nfs3 = ntohl(*p++);
fattr->fileid = ntohl(*p++);
p = xdr_decode_time(p, &fattr->atime);
p = xdr_decode_time(p, &fattr->mtime);
......
......@@ -14,6 +14,7 @@
#include <linux/nfs.h>
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/smp_lock.h>
#define NFSDBG_FACILITY NFSDBG_PROC
......@@ -86,9 +87,10 @@ nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
}
static int
nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
struct iattr *sattr)
{
struct inode *inode = dentry->d_inode;
struct nfs3_sattrargs arg = {
.fh = NFS_FH(inode),
.sattr = sattr,
......@@ -543,9 +545,10 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
* readdirplus.
*/
static int
nfs3_proc_readdir(struct inode *dir, struct rpc_cred *cred,
nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
u64 cookie, struct page *page, unsigned int count, int plus)
{
struct inode *dir = dentry->d_inode;
struct nfs_fattr dir_attr;
u32 *verf = NFS_COOKIEVERF(dir);
struct nfs3_readdirargs arg = {
......@@ -644,6 +647,51 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
static void
nfs3_read_done(struct rpc_task *task)
{
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
if (nfs_async_handle_jukebox(task))
return;
nfs_readpage_result(task, data->u.v3.res.count, data->u.v3.res.eof);
}
static void
nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count)
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
struct nfs_page *req;
int flags;
struct rpc_message msg;
req = nfs_list_entry(data->pages.next);
data->u.v3.args.fh = NFS_FH(inode);
data->u.v3.args.offset = req_offset(req) + req->wb_offset;
data->u.v3.args.pgbase = req->wb_offset;
data->u.v3.args.pages = data->pagevec;
data->u.v3.args.count = count;
data->u.v3.res.fattr = &data->fattr;
data->u.v3.res.count = count;
data->u.v3.res.eof = 0;
/* N.B. Do we need to test? Never called for swapfile inode */
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs3_read_done, flags);
task->tk_calldata = data;
/* Release requests */
task->tk_release = nfs_readdata_release;
msg.rpc_proc = NFS3PROC_READ;
msg.rpc_argp = &data->u.v3.args;
msg.rpc_resp = &data->u.v3.res;
msg.rpc_cred = data->cred;
rpc_call_setup(&data->task, &msg, 0);
}
struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */
.getroot = nfs3_proc_get_root,
......@@ -667,4 +715,5 @@ struct nfs_rpc_ops nfs_v3_clientops = {
.mknod = nfs3_proc_mknod,
.statfs = nfs3_proc_statfs,
.decode_dirent = nfs3_decode_dirent,
.read_setup = nfs3_proc_read_setup,
};
......@@ -173,7 +173,7 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
/* Turn remote device info into Linux-specific dev_t */
fattr->rdev = ntohl(*p++) << MINORBITS;
fattr->rdev |= ntohl(*p++) & MINORMASK;
p = xdr_decode_hyper(p, &fattr->fsid);
p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3);
p = xdr_decode_hyper(p, &fattr->fileid);
p = xdr_decode_time3(p, &fattr->atime);
p = xdr_decode_time3(p, &fattr->mtime);
......
......@@ -14,6 +14,7 @@
#include <linux/file.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfs3.h>
#include <linux/nfs4.h>
#include <linux/nfs_page.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_flushd.h>
......@@ -506,7 +507,7 @@ nfs_try_to_free_pages(struct nfs_server *server)
continue;
}
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
/* Let's try to free up some completed NFSv3 unstable writes */
nfs_scan_lru_commit(server, &head);
if (!list_empty(&head)) {
......
......@@ -41,6 +41,7 @@
#include <linux/nfs.h>
#include <linux/nfs2.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/smp_lock.h>
#define NFSDBG_FACILITY NFSDBG_PROC
......@@ -78,9 +79,10 @@ nfs_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
}
static int
nfs_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
struct iattr *sattr)
{
struct inode *inode = dentry->d_inode;
struct nfs_sattrargs arg = {
.fh = NFS_FH(inode),
.sattr = sattr
......@@ -425,9 +427,10 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name)
* from nfs_readdir by calling the decode_entry function directly.
*/
static int
nfs_proc_readdir(struct inode *dir, struct rpc_cred *cred,
nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
u64 cookie, struct page *page, unsigned int count, int plus)
{
struct inode *dir = dentry->d_inode;
struct nfs_readdirargs arg = {
.fh = NFS_FH(dir),
.cookie = cookie,
......@@ -467,6 +470,48 @@ nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
static void
nfs_read_done(struct rpc_task *task)
{
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
nfs_readpage_result(task, data->u.v3.res.count, data->u.v3.res.eof);
}
static void
nfs_proc_read_setup(struct nfs_read_data *data, unsigned int count)
{
struct rpc_task *task = &data->task;
struct inode *inode = data->inode;
struct nfs_page *req;
int flags;
struct rpc_message msg;
req = nfs_list_entry(data->pages.next);
data->u.v3.args.fh = NFS_FH(inode);
data->u.v3.args.offset = req_offset(req) + req->wb_offset;
data->u.v3.args.pgbase = req->wb_offset;
data->u.v3.args.pages = data->pagevec;
data->u.v3.args.count = count;
data->u.v3.res.fattr = &data->fattr;
data->u.v3.res.count = count;
data->u.v3.res.eof = 0;
/* N.B. Do we need to test? Never called for swapfile inode */
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
/* Finalize the task. */
rpc_init_task(task, NFS_CLIENT(inode), nfs_read_done, flags);
task->tk_calldata = data;
/* Release requests */
task->tk_release = nfs_readdata_release;
msg.rpc_proc = NFSPROC_READ;
msg.rpc_argp = &data->u.v3.args;
msg.rpc_resp = &data->u.v3.res;
msg.rpc_cred = data->cred;
rpc_call_setup(&data->task, &msg, 0);
}
struct nfs_rpc_ops nfs_v2_clientops = {
.version = 2, /* protocol version */
.getroot = nfs_proc_get_root,
......@@ -491,4 +536,5 @@ struct nfs_rpc_ops nfs_v2_clientops = {
.mknod = nfs_proc_mknod,
.statfs = nfs_proc_statfs,
.decode_dirent = nfs_decode_dirent,
.read_setup = nfs_proc_read_setup,
};
......@@ -34,27 +34,6 @@
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
struct nfs_read_data {
struct rpc_task task;
struct inode *inode;
struct rpc_cred *cred;
struct nfs_readargs args; /* XDR argument struct */
struct nfs_readres res; /* ... and result struct */
struct nfs_fattr fattr; /* fattr storage */
struct list_head pages; /* Coalesced read requests */
struct page *pagevec[NFS_READ_MAXIOV];
};
/*
* Local function declarations
*/
static void nfs_readpage_result(struct rpc_task *task);
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
#endif
static kmem_cache_t *nfs_rdata_cachep;
static __inline__ struct nfs_read_data *nfs_readdata_alloc(void)
......@@ -64,7 +43,6 @@ static __inline__ struct nfs_read_data *nfs_readdata_alloc(void)
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
p->args.pages = p->pagevec;
}
return p;
}
......@@ -74,7 +52,7 @@ static __inline__ void nfs_readdata_free(struct nfs_read_data *p)
kmem_cache_free(nfs_rdata_cachep, p);
}
static void nfs_readdata_release(struct rpc_task *task)
void nfs_readdata_release(struct rpc_task *task)
{
struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
nfs_readdata_free(data);
......@@ -190,29 +168,32 @@ nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
static void
nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data)
{
struct inode *inode;
struct nfs_page *req;
struct page **pages;
unsigned int count;
pages = data->args.pages;
pages = data->pagevec;
count = 0;
while (!list_empty(head)) {
struct nfs_page *req = nfs_list_entry(head->next);
req = nfs_list_entry(head->next);
nfs_list_remove_request(req);
nfs_list_add_request(req, &data->pages);
*pages++ = req->wb_page;
count += req->wb_bytes;
}
req = nfs_list_entry(data->pages.next);
data->inode = req->wb_inode;
data->inode = inode = req->wb_inode;
data->cred = req->wb_cred;
data->args.fh = NFS_FH(req->wb_inode);
data->args.offset = req_offset(req) + req->wb_offset;
data->args.pgbase = req->wb_offset;
data->args.count = count;
data->res.fattr = &data->fattr;
data->res.count = count;
data->res.eof = 0;
NFS_PROTO(inode)->read_setup(data, count);
dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu.\n",
data->task.tk_pid,
inode->i_sb->s_id,
(long long)NFS_FILEID(inode),
count,
(unsigned long long)req_offset(req) + req->wb_offset);
}
static void
......@@ -236,50 +217,20 @@ nfs_async_read_error(struct list_head *head)
static int
nfs_pagein_one(struct list_head *head, struct inode *inode)
{
struct rpc_task *task;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
struct nfs_read_data *data;
struct rpc_message msg;
int flags;
sigset_t oldset;
data = nfs_readdata_alloc();
if (!data)
goto out_bad;
task = &data->task;
/* N.B. Do we need to test? Never called for swapfile inode */
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
nfs_read_rpcsetup(head, data);
/* Finalize the task. */
rpc_init_task(task, clnt, nfs_readpage_result, flags);
task->tk_calldata = data;
/* Release requests */
task->tk_release = nfs_readdata_release;
#ifdef CONFIG_NFS_V3
msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ? NFS3PROC_READ : NFSPROC_READ;
#else
msg.rpc_proc = NFSPROC_READ;
#endif
msg.rpc_argp = &data->args;
msg.rpc_resp = &data->res;
msg.rpc_cred = data->cred;
/* Start the async call */
dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu.\n",
task->tk_pid,
inode->i_sb->s_id,
(long long)NFS_FILEID(inode),
(unsigned int)data->args.count,
(unsigned long long)data->args.offset);
rpc_clnt_sigmask(clnt, &oldset);
rpc_call_setup(task, &msg, 0);
lock_kernel();
rpc_execute(task);
rpc_execute(&data->task);
unlock_kernel();
rpc_clnt_sigunmask(clnt, &oldset);
return 0;
......@@ -399,19 +350,15 @@ int nfs_pagein_inode(struct inode *inode, unsigned long idx_start,
* This is the callback from RPC telling us whether a reply was
* received or some error occurred (timeout or socket shutdown).
*/
static void
nfs_readpage_result(struct rpc_task *task)
void
nfs_readpage_result(struct rpc_task *task, unsigned int count, int eof)
{
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
struct inode *inode = data->inode;
unsigned int count = data->res.count;
dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
task->tk_pid, task->tk_status);
if (nfs_async_handle_jukebox(task))
return;
nfs_refresh_inode(inode, &data->fattr);
while (!list_empty(&data->pages)) {
struct nfs_page *req = nfs_list_entry(data->pages.next);
......@@ -424,7 +371,7 @@ nfs_readpage_result(struct rpc_task *task)
memset(p + count, 0, PAGE_CACHE_SIZE - count);
kunmap(page);
count = 0;
if (data->res.eof)
if (eof)
SetPageUptodate(page);
else
SetPageError(page);
......
......@@ -88,7 +88,7 @@ static struct nfs_page * nfs_update_request(struct file*, struct inode *,
unsigned int, unsigned int);
static void nfs_strategy(struct inode *inode);
static void nfs_writeback_done(struct rpc_task *);
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
static void nfs_commit_done(struct rpc_task *);
#endif
......@@ -414,7 +414,7 @@ nfs_dirty_request(struct nfs_page *req)
return !list_empty(&req->wb_list) && req->wb_list_head == &nfsi->dirty;
}
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
/*
* Add a request to the inode's commit list.
*/
......@@ -552,7 +552,7 @@ nfs_scan_dirty(struct inode *inode, struct list_head *dst, struct file *file, un
return res;
}
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
/**
* nfs_scan_lru_commit_timeout - Scan LRU list for timed out commit requests
* @server: NFS superblock data
......@@ -747,7 +747,7 @@ nfs_strategy(struct inode *inode)
dirty = NFS_I(inode)->ndirty;
wpages = NFS_SERVER(inode)->wpages;
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (NFS_PROTO(inode)->version == 2) {
if (dirty >= NFS_STRATEGY_PAGES * wpages)
nfs_flush_file(inode, NULL, 0, 0, 0);
......@@ -1032,7 +1032,7 @@ nfs_writeback_done(struct rpc_task *task)
* an error. */
task->tk_status = -EIO;
}
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (resp->verf->committed < argp->stable && task->tk_status >= 0) {
/* We tried a write call, but the server did not
* commit data to stable storage even though we
......@@ -1082,7 +1082,7 @@ nfs_writeback_done(struct rpc_task *task)
goto next;
}
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (argp->stable != NFS_UNSTABLE || resp->verf->committed == NFS_FILE_SYNC) {
nfs_inode_remove_request(req);
dprintk(" OK\n");
......@@ -1101,7 +1101,7 @@ nfs_writeback_done(struct rpc_task *task)
}
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
/*
* Set up the argument/result storage required for the RPC call.
*/
......@@ -1265,7 +1265,7 @@ int nfs_flush_file(struct inode *inode, struct file *file, unsigned long idx_sta
return res;
}
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
int nfs_commit_file(struct inode *inode, struct file *file, unsigned long idx_start,
unsigned int npages, int how)
{
......@@ -1302,7 +1302,7 @@ int nfs_sync_file(struct inode *inode, struct file *file, unsigned long idx_star
error = nfs_wait_on_requests(inode, file, idx_start, npages);
if (error == 0)
error = nfs_flush_file(inode, file, idx_start, npages, how);
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (error == 0)
error = nfs_commit_file(inode, file, idx_start, npages, how);
#endif
......
......@@ -165,6 +165,24 @@ proc_file_lseek(struct file * file, loff_t offset, int orig)
return -EINVAL;
}
static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
{
struct inode *inode = dentry->d_inode;
int error = inode_setattr(inode, iattr);
if (!error) {
struct proc_dir_entry *de = PDE(inode);
de->uid = inode->i_uid;
de->gid = inode->i_gid;
de->mode = inode->i_mode;
}
return error;
}
static struct inode_operations proc_file_inode_operations = {
.setattr = proc_notify_change,
};
/*
* This function parses a name such as "tty/driver/serial", and
* returns the struct proc_dir_entry for "/proc/tty/driver", and
......@@ -368,6 +386,7 @@ static struct file_operations proc_dir_operations = {
*/
static struct inode_operations proc_dir_inode_operations = {
.lookup = proc_lookup,
.setattr = proc_notify_change,
};
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
......@@ -393,6 +412,8 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
} else if (S_ISREG(dp->mode)) {
if (dp->proc_fops == NULL)
dp->proc_fops = &proc_file_operations;
if (dp->proc_iops == NULL)
dp->proc_iops = &proc_file_inode_operations;
}
return 0;
}
......
......@@ -65,6 +65,9 @@ enum fixed_addresses {
#ifdef CONFIG_X86_F00F_BUG
FIX_F00F_IDT, /* Virtual mapping for IDT */
#endif
#ifdef CONFIG_X86_CYCLONE
FIX_CYCLONE_TIMER, /*cyclone timer register*/
#endif
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
......
#ifndef _ASMi386_TIMER_H
#define _ASMi386_TIMER_H
/**
* struct timer_ops - used to define a timer source
*
* @init: Probes and initializes the timer. Returns 0 on success, anything
* else on failure.
* @mark_offset: called by the timer interrupt
* @get_offset: called by gettimeofday(). Returns the number of ms since the
* last timer intruupt.
*/
struct timer_opts{
int (*init)(void);
void (*mark_offset)(void);
unsigned long (*get_offset)(void);
};
#define TICK_SIZE (tick_nsec / 1000)
extern struct timer_opts* select_timer(void);
#endif
/*
* include/linux/nfs4.h
*
* NFSv4 protocol definitions.
*
* Copyright (c) 2002 The Regents of the University of Michigan.
* All rights reserved.
*
* Kendrick Smith <kmsmith@umich.edu>
* Andy Adamson <andros@umich.edu>
*/
#ifndef _LINUX_NFS4_H
#define _LINUX_NFS4_H
#define NFS4_VERIFIER_SIZE 8
#define NFS4_FHSIZE 128
#define NFS4_MAXNAMLEN NAME_MAX
#define NFS4_ACCESS_READ 0x0001
#define NFS4_ACCESS_LOOKUP 0x0002
#define NFS4_ACCESS_MODIFY 0x0004
#define NFS4_ACCESS_EXTEND 0x0008
#define NFS4_ACCESS_DELETE 0x0010
#define NFS4_ACCESS_EXECUTE 0x0020
#define NFS4_FH_PERISTENT 0x0000
#define NFS4_FH_NOEXPIRE_WITH_OPEN 0x0001
#define NFS4_FH_VOLATILE_ANY 0x0002
#define NFS4_FH_VOL_MIGRATION 0x0004
#define NFS4_FH_VOL_RENAME 0x0008
#define NFS4_OPEN_RESULT_CONFIRM 0x0002
#define NFS4_SHARE_ACCESS_READ 0x0001
#define NFS4_SHARE_ACCESS_WRITE 0x0002
#define NFS4_SHARE_ACCESS_BOTH 0x0003
#define NFS4_SET_TO_SERVER_TIME 0
#define NFS4_SET_TO_CLIENT_TIME 1
#define NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE 0
#define NFS4_ACE_ACCESS_DENIED_ACE_TYPE 1
#define NFS4_ACE_SYSTEM_AUDIT_ACE_TYPE 2
#define NFS4_ACE_SYSTEM_ALARM_ACE_TYPE 3
typedef char nfs4_verifier[NFS4_VERIFIER_SIZE];
typedef char nfs4_stateid[16];
enum nfs_opnum4 {
OP_ACCESS = 3,
OP_CLOSE = 4,
OP_COMMIT = 5,
OP_CREATE = 6,
OP_DELEGPURGE = 7,
OP_DELEGRETURN = 8,
OP_GETATTR = 9,
OP_GETFH = 10,
OP_LINK = 11,
OP_LOCK = 12,
OP_LOCKT = 13,
OP_LOCKU = 14,
OP_LOOKUP = 15,
OP_LOOKUPP = 16,
OP_NVERIFY = 17,
OP_OPEN = 18,
OP_OPENATTR = 19,
OP_OPEN_CONFIRM = 20,
OP_OPEN_DOWNGRADE = 21,
OP_PUTFH = 22,
OP_PUTPUBFH = 23,
OP_PUTROOTFH = 24,
OP_READ = 25,
OP_READDIR = 26,
OP_READLINK = 27,
OP_REMOVE = 28,
OP_RENAME = 29,
OP_RENEW = 30,
OP_RESTOREFH = 31,
OP_SAVEFH = 32,
OP_SECINFO = 33,
OP_SETATTR = 34,
OP_SETCLIENTID = 35,
OP_SETCLIENTID_CONFIRM = 36,
OP_VERIFY = 37,
OP_WRITE = 38,
};
/*
* Note: NF4BAD is not actually part of the protocol; it is just used
* internally by nfsd.
*/
enum nfs_ftype4 {
NF4BAD = 0,
NF4REG = 1, /* Regular File */
NF4DIR = 2, /* Directory */
NF4BLK = 3, /* Special File - block device */
NF4CHR = 4, /* Special File - character device */
NF4LNK = 5, /* Symbolic Link */
NF4SOCK = 6, /* Special File - socket */
NF4FIFO = 7, /* Special File - fifo */
NF4ATTRDIR = 8, /* Attribute Directory */
NF4NAMEDATTR = 9 /* Named Attribute */
};
enum open_claim_type4 {
NFS4_OPEN_CLAIM_NULL = 0,
NFS4_OPEN_CLAIM_PREVIOUS = 1,
NFS4_OPEN_CLAIM_DELEGATE_CUR = 2,
NFS4_OPEN_CLAIM_DELEGATE_PREV = 3
};
enum opentype4 {
NFS4_OPEN_NOCREATE = 0,
NFS4_OPEN_CREATE = 1
};
enum createmode4 {
NFS4_CREATE_UNCHECKED = 0,
NFS4_CREATE_GUARDED = 1,
NFS4_CREATE_EXCLUSIVE = 2
};
enum limit_by4 {
NFS4_LIMIT_SIZE = 1,
NFS4_LIMIT_BLOCKS = 2
};
enum open_delegation_type4 {
NFS4_OPEN_DELEGATE_NONE = 0,
NFS4_OPEN_DELEGATE_READ = 1,
NFS4_OPEN_DELEGATE_WRITE = 2
};
/* Mandatory Attributes */
#define FATTR4_WORD0_SUPPORTED_ATTRS (1)
#define FATTR4_WORD0_TYPE (1 << 1)
#define FATTR4_WORD0_FH_EXPIRE_TYPE (1 << 2)
#define FATTR4_WORD0_CHANGE (1 << 3)
#define FATTR4_WORD0_SIZE (1 << 4)
#define FATTR4_WORD0_LINK_SUPPORT (1 << 5)
#define FATTR4_WORD0_SYMLINK_SUPPORT (1 << 6)
#define FATTR4_WORD0_NAMED_ATTR (1 << 7)
#define FATTR4_WORD0_FSID (1 << 8)
#define FATTR4_WORD0_UNIQUE_HANDLES (1 << 9)
#define FATTR4_WORD0_LEASE_TIME (1 << 10)
#define FATTR4_WORD0_RDATTR_ERROR (1 << 11)
/* Recommended Attributes */
#define FATTR4_WORD0_ACL (1 << 12)
#define FATTR4_WORD0_ACLSUPPORT (1 << 13)
#define FATTR4_WORD0_ARCHIVE (1 << 14)
#define FATTR4_WORD0_CANSETTIME (1 << 15)
#define FATTR4_WORD0_CASE_INSENSITIVE (1 << 16)
#define FATTR4_WORD0_CASE_PRESERVING (1 << 17)
#define FATTR4_WORD0_CHOWN_RESTRICTED (1 << 18)
#define FATTR4_WORD0_FILEHANDLE (1 << 19)
#define FATTR4_WORD0_FILEID (1 << 20)
#define FATTR4_WORD0_FILES_AVAIL (1 << 21)
#define FATTR4_WORD0_FILES_FREE (1 << 22)
#define FATTR4_WORD0_FILES_TOTAL (1 << 23)
#define FATTR4_WORD0_FS_LOCATIONS (1 << 24)
#define FATTR4_WORD0_HIDDEN (1 << 25)
#define FATTR4_WORD0_HOMOGENEOUS (1 << 26)
#define FATTR4_WORD0_MAXFILESIZE (1 << 27)
#define FATTR4_WORD0_MAXLINK (1 << 28)
#define FATTR4_WORD0_MAXNAME (1 << 29)
#define FATTR4_WORD0_MAXREAD (1 << 30)
#define FATTR4_WORD0_MAXWRITE (1 << 31)
#define FATTR4_WORD1_MIMETYPE (1)
#define FATTR4_WORD1_MODE (1 << 1)
#define FATTR4_WORD1_NO_TRUNC (1 << 2)
#define FATTR4_WORD1_NUMLINKS (1 << 3)
#define FATTR4_WORD1_OWNER (1 << 4)
#define FATTR4_WORD1_OWNER_GROUP (1 << 5)
#define FATTR4_WORD1_QUOTA_HARD (1 << 6)
#define FATTR4_WORD1_QUOTA_SOFT (1 << 7)
#define FATTR4_WORD1_QUOTA_USED (1 << 8)
#define FATTR4_WORD1_RAWDEV (1 << 9)
#define FATTR4_WORD1_SPACE_AVAIL (1 << 10)
#define FATTR4_WORD1_SPACE_FREE (1 << 11)
#define FATTR4_WORD1_SPACE_TOTAL (1 << 12)
#define FATTR4_WORD1_SPACE_USED (1 << 13)
#define FATTR4_WORD1_SYSTEM (1 << 14)
#define FATTR4_WORD1_TIME_ACCESS (1 << 15)
#define FATTR4_WORD1_TIME_ACCESS_SET (1 << 16)
#define FATTR4_WORD1_TIME_BACKUP (1 << 17)
#define FATTR4_WORD1_TIME_CREATE (1 << 18)
#define FATTR4_WORD1_TIME_DELTA (1 << 19)
#define FATTR4_WORD1_TIME_METADATA (1 << 20)
#define FATTR4_WORD1_TIME_MODIFY (1 << 21)
#define FATTR4_WORD1_TIME_MODIFY_SET (1 << 22)
#define NFSPROC4_NULL 0
#define NFSPROC4_COMPOUND 1
#define NFS4_MINOR_VERSION 0
#define NFS4_DEBUG 1
#endif
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
......@@ -25,6 +25,7 @@
#include <linux/nfs.h>
#include <linux/nfs2.h>
#include <linux/nfs3.h>
#include <linux/nfs4.h>
#include <linux/nfs_page.h>
#include <linux/nfs_xdr.h>
......@@ -143,6 +144,7 @@ struct nfs_inode {
__u64 read_cache_isize;
unsigned long attrtimeo;
unsigned long attrtimeo_timestamp;
__u64 change_attr; /* v4 only */
/*
* Timestamp that dates the change made to read_cache_mtime.
......@@ -207,6 +209,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode)
#define NFS_CACHE_CTIME(inode) (NFS_I(inode)->read_cache_ctime)
#define NFS_CACHE_MTIME(inode) (NFS_I(inode)->read_cache_mtime)
#define NFS_CACHE_ISIZE(inode) (NFS_I(inode)->read_cache_isize)
#define NFS_CHANGE_ATTR(inode) (NFS_I(inode)->change_attr)
#define NFS_NEXTSCAN(inode) (NFS_I(inode)->nextscan)
#define NFS_CACHEINV(inode) \
do { \
......@@ -329,7 +332,7 @@ extern int nfs_flush_file(struct inode *, struct file *, unsigned long, unsigne
extern int nfs_flush_list(struct list_head *, int, int);
extern int nfs_scan_lru_dirty(struct nfs_server *, struct list_head *);
extern int nfs_scan_lru_dirty_timeout(struct nfs_server *, struct list_head *);
#ifdef CONFIG_NFS_V3
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern int nfs_commit_file(struct inode *, struct file *, unsigned long, unsigned int, int);
extern int nfs_commit_list(struct list_head *, int);
extern int nfs_scan_lru_commit(struct nfs_server *, struct list_head *);
......@@ -376,6 +379,11 @@ nfs_wb_file(struct inode *inode, struct file *file)
return (error < 0) ? error : 0;
}
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
#endif
/*
* linux/fs/nfs/read.c
*/
......@@ -384,6 +392,8 @@ extern int nfs_pagein_inode(struct inode *, unsigned long, unsigned int);
extern int nfs_pagein_list(struct list_head *, int);
extern int nfs_scan_lru_read(struct nfs_server *, struct list_head *);
extern int nfs_scan_lru_read_timeout(struct nfs_server *, struct list_head *);
extern void nfs_readpage_result(struct rpc_task *, unsigned int count, int eof);
extern void nfs_readdata_release(struct rpc_task *);
/*
* linux/fs/mount_clnt.c
......
......@@ -24,17 +24,27 @@ struct nfs_fattr {
} nfs3;
} du;
__u32 rdev;
__u64 fsid;
union {
__u64 nfs3; /* also nfs2 */
struct {
__u64 major;
__u64 minor;
} nfs4;
} fsid_u;
__u64 fileid;
__u64 atime;
__u64 mtime;
__u64 ctime;
__u64 change_attr; /* NFSv4 change attribute */
__u64 pre_change_attr;/* pre-op NFSv4 change attribute */
unsigned long timestamp;
};
#define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */
#define NFS_ATTR_FATTR 0x0002 /* post-op attributes */
#define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */
#define NFS_ATTR_FATTR_V4 0x0008
#define NFS_ATTR_PRE_CHANGE 0x0010
/*
* Info on the file system
......@@ -298,6 +308,24 @@ struct nfs3_readdirres {
int plus;
};
struct nfs_read_data {
struct rpc_task task;
struct inode *inode;
struct rpc_cred *cred;
struct nfs_fattr fattr; /* fattr storage */
struct list_head pages; /* Coalesced read requests */
struct page *pagevec[NFS_READ_MAXIOV];
union {
struct {
struct nfs_readargs args;
struct nfs_readres res;
} v3; /* also v2 */
#ifdef CONFIG_NFS_V4
/* NFSv4 data will come here... */
#endif
} u;
};
/*
* RPC procedure vector for NFSv2/NFSv3 demuxing
*/
......@@ -307,7 +335,7 @@ struct nfs_rpc_ops {
int (*getroot) (struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *);
int (*getattr) (struct inode *, struct nfs_fattr *);
int (*setattr) (struct inode *, struct nfs_fattr *,
int (*setattr) (struct dentry *, struct nfs_fattr *,
struct iattr *);
int (*lookup) (struct inode *, struct qstr *,
struct nfs_fh *, struct nfs_fattr *);
......@@ -338,13 +366,14 @@ struct nfs_rpc_ops {
int (*mkdir) (struct inode *, struct qstr *, struct iattr *,
struct nfs_fh *, struct nfs_fattr *);
int (*rmdir) (struct inode *, struct qstr *);
int (*readdir) (struct inode *, struct rpc_cred *,
int (*readdir) (struct dentry *, struct rpc_cred *,
u64, struct page *, unsigned int, int);
int (*mknod) (struct inode *, struct qstr *, struct iattr *,
dev_t, struct nfs_fh *, struct nfs_fattr *);
int (*statfs) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsinfo *);
u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus);
void (*read_setup) (struct nfs_read_data *, unsigned int count);
};
/*
......
......@@ -12,6 +12,7 @@
#include <linux/nfs.h>
#include <linux/nfs2.h>
#include <linux/nfs3.h>
#include <linux/nfs4.h>
/*
* Maximum protocol version supported by knfsd
......
......@@ -623,6 +623,7 @@
#define PCI_VENDOR_ID_MOTOROLA_OOPS 0x1507
#define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001
#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002
#define PCI_DEVICE_ID_MOTOROLA_MPC107 0x0004
#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801
#define PCI_DEVICE_ID_MOTOROLA_FALCON 0x4802
#define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803
......
......@@ -146,6 +146,7 @@ struct rpc_xprt {
unsigned long sockstate; /* Socket state */
unsigned char shutdown : 1, /* being shut down */
nocong : 1, /* no congestion control */
resvport : 1, /* use a reserved port */
stream : 1; /* TCP */
/*
......
......@@ -17,4 +17,4 @@ $(obj)/version.o: $(objtree)/include/linux/compile.h
$(objtree)/include/linux/compile.h: FORCE
@echo -n ' Generating $@'
@$(srctree)/scripts/mkcompile_h $@ "$(ARCH)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
@sh $(srctree)/scripts/mkcompile_h $@ "$(ARCH)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
......@@ -88,8 +88,8 @@ extern int sysctl_ieee_emulation_warnings;
extern int sysctl_userprocess_debug;
#endif
#ifdef CONFIG_PPC32
extern unsigned long zero_paged_on, powersave_nap;
#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
extern unsigned long powersave_nap;
int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp);
#endif
......@@ -190,9 +190,7 @@ static ctl_table kern_table[] = {
{KERN_SPARC_STOP_A, "stop-a", &stop_a_enabled, sizeof (int),
0644, NULL, &proc_dointvec},
#endif
#ifdef CONFIG_PPC32
{KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, sizeof(int),
0644, NULL, &proc_dointvec},
#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
{KERN_PPC_POWERSAVE_NAP, "powersave-nap", &powersave_nap, sizeof(int),
0644, NULL, &proc_dointvec},
{KERN_PPC_L2CR, "l2cr", NULL, 0,
......
......@@ -89,7 +89,7 @@ static void xprt_disconnect(struct rpc_xprt *);
static void xprt_conn_status(struct rpc_task *task);
static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap,
struct rpc_timeout *to);
static struct socket *xprt_create_socket(int, struct rpc_timeout *);
static struct socket *xprt_create_socket(int, struct rpc_timeout *, int);
static void xprt_bind_socket(struct rpc_xprt *, struct socket *);
static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
......@@ -442,7 +442,7 @@ xprt_connect(struct rpc_task *task)
* Start by resetting any existing state.
*/
xprt_close(xprt);
if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout))) {
if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout, xprt->resvport))) {
/* couldn't create socket or bind to reserved port;
* this is likely a permanent error, so cause an abort */
task->tk_status = -EIO;
......@@ -1490,7 +1490,7 @@ xprt_sock_setbufsize(struct rpc_xprt *xprt)
* and connect stream sockets.
*/
static struct socket *
xprt_create_socket(int proto, struct rpc_timeout *to)
xprt_create_socket(int proto, struct rpc_timeout *to, int resvport)
{
struct socket *sock;
int type, err;
......@@ -1506,7 +1506,7 @@ xprt_create_socket(int proto, struct rpc_timeout *to)
}
/* If the caller has the capability, bind to a reserved port */
if (capable(CAP_NET_BIND_SERVICE) && xprt_bindresvport(sock) < 0) {
if (resvport && xprt_bindresvport(sock) < 0) {
printk("RPC: can't bind to reserved port.\n");
goto failed;
}
......@@ -1528,29 +1528,25 @@ xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
xprt = xprt_setup(proto, sap, to);
if (!xprt)
goto out;
goto out_bad;
xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
if (!xprt->stream) {
struct socket *sock = xprt_create_socket(proto, to);
if (sock)
struct socket *sock;
sock = xprt_create_socket(proto, to, xprt->resvport);
if (!sock)
goto out_bad;
xprt_bind_socket(xprt, sock);
else {
rpc_free(xprt);
xprt = NULL;
}
} else
/*
* Don't allow a TCP service user unless they have
* enough capability to bind a reserved port.
*/
if (!capable(CAP_NET_BIND_SERVICE)) {
rpc_free(xprt);
xprt = NULL;
}
out:
dprintk("RPC: xprt_create_proto created xprt %p\n", xprt);
return xprt;
out_bad:
dprintk("RPC: xprt_create_proto failed\n");
if (xprt)
rpc_free(xprt);
return NULL;
}
/*
......
......@@ -61,7 +61,7 @@
*
* It is invoked as
*
* fixdep <depfile> <target> <topdir> <cmdline>
* fixdep <depfile> <target> <cmdline>
*
* and will read the dependency file <depfile>
*
......@@ -111,7 +111,6 @@
#define INT_NFIG ntohl(0x4e464947)
#define INT_FIG_ ntohl(0x4649475f)
char *topdir;
char *target;
char *depfile;
char *cmdline;
......@@ -119,7 +118,7 @@ char *cmdline;
void usage(void)
{
fprintf(stderr, "Usage: fixdep <depfile> <target> <topdir> <cmdline>\n");
fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
exit(1);
}
......@@ -364,13 +363,12 @@ int main(int argc, char *argv[])
{
traps();
if (argc != 5)
if (argc != 4)
usage();
depfile = argv[1];
target = argv[2];
topdir = argv[3];
cmdline = argv[4];
cmdline = argv[3];
print_cmdline();
print_deps();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment