From 2a2f78fda49f3d902123daeb5b2a3ca04659122b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 23 Sep 2009 14:36:37 -0400 Subject: [PATCH] --- yaml --- r: 165548 b: refs/heads/master c: 8a6e5deb8a8caa810fef2c525f5dbea2cfe04a47 h: refs/heads/master v: v3 --- [refs] | 2 +- .../feature-removal-schedule.txt | 8 + trunk/Documentation/filesystems/9p.txt | 40 +- trunk/Documentation/hwmon/coretemp | 4 +- trunk/Documentation/hwmon/fscher | 169 +++++ trunk/MAINTAINERS | 7 - trunk/arch/arm/mach-ixp4xx/common.c | 16 +- .../arm/mach-ixp4xx/include/mach/system.h | 6 +- trunk/drivers/char/tpm/tpm.c | 5 +- trunk/drivers/hwmon/Kconfig | 34 +- trunk/drivers/hwmon/Makefile | 2 + trunk/drivers/hwmon/adm1031.c | 40 -- trunk/drivers/hwmon/coretemp.c | 57 +- trunk/drivers/hwmon/fscher.c | 680 ++++++++++++++++++ trunk/drivers/hwmon/fscpos.c | 654 +++++++++++++++++ trunk/drivers/hwmon/ltc4215.c | 2 +- trunk/drivers/hwmon/ltc4245.c | 3 +- trunk/drivers/serial/serial_core.c | 4 +- trunk/fs/9p/Kconfig | 9 - trunk/fs/9p/Makefile | 3 +- trunk/fs/9p/cache.c | 474 ------------ trunk/fs/9p/cache.h | 176 ----- trunk/fs/9p/v9fs.c | 196 +---- trunk/fs/9p/v9fs.h | 13 +- trunk/fs/9p/v9fs_vfs.h | 6 - trunk/fs/9p/vfs_addr.c | 88 +-- trunk/fs/9p/vfs_file.c | 25 +- trunk/fs/9p/vfs_inode.c | 61 +- trunk/fs/9p/vfs_super.c | 16 +- trunk/fs/nfs/client.c | 12 +- trunk/fs/nfs/super.c | 17 +- trunk/include/linux/cred.h | 18 +- trunk/include/linux/serial_core.h | 4 +- trunk/include/net/9p/9p.h | 3 - trunk/kernel/cred.c | 19 - trunk/security/keys/gc.c | 4 +- trunk/security/selinux/avc.c | 19 +- 37 files changed, 1686 insertions(+), 1210 deletions(-) create mode 100644 trunk/Documentation/hwmon/fscher create mode 100644 trunk/drivers/hwmon/fscher.c create mode 100644 trunk/drivers/hwmon/fscpos.c delete mode 100644 trunk/fs/9p/cache.c delete mode 100644 trunk/fs/9p/cache.h diff --git a/[refs] b/[refs] index 0c84abd3f329..a242007eaa8e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a7ddbf891b8236b51fb3c9574555eb7d7d13aca6 +refs/heads/master: 8a6e5deb8a8caa810fef2c525f5dbea2cfe04a47 diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 89a47b5aff07..fa75220f8d34 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -354,6 +354,14 @@ Who: Krzysztof Piotr Oledzki --------------------------- +What: fscher and fscpos drivers +When: June 2009 +Why: Deprecated by the new fschmd driver. +Who: Hans de Goede + Jean Delvare + +--------------------------- + What: sysfs ui for changing p4-clockmod parameters When: September 2009 Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and diff --git a/trunk/Documentation/filesystems/9p.txt b/trunk/Documentation/filesystems/9p.txt index 57e0b80a5274..6208f55c44c3 100644 --- a/trunk/Documentation/filesystems/9p.txt +++ b/trunk/Documentation/filesystems/9p.txt @@ -18,11 +18,11 @@ the 9p client is available in the form of a USENIX paper: Other applications are described in the following papers: * XCPU & Clustering - http://xcpu.org/papers/xcpu-talk.pdf + http://www.xcpu.org/xcpu-talk.pdf * KVMFS: control file system for KVM - http://xcpu.org/papers/kvmfs.pdf - * CellFS: A New Programming Model for the Cell BE - http://xcpu.org/papers/cellfs-talk.pdf + http://www.xcpu.org/kvmfs.pdf + * CellFS: A New ProgrammingModel for the Cell BE + http://www.xcpu.org/cellfs-talk.pdf * PROSE I/O: Using 9p to enable Application Partitions http://plan9.escet.urjc.es/iwp9/cready/PROSE_iwp9_2006.pdf @@ -48,7 +48,6 @@ OPTIONS (see rfdno and wfdno) virtio - connect to the next virtio channel available (from lguest or KVM with trans_virtio module) - rdma - connect to a specified RDMA channel uname=name user name to attempt mount as on the remote server. The server may override or ignore this value. Certain user @@ -60,22 +59,16 @@ OPTIONS cache=mode specifies a caching policy. By default, no caches are used. loose = no attempts are made at consistency, intended for exclusive, read-only mounts - fscache = use FS-Cache for a persistent, read-only - cache backend. debug=n specifies debug level. The debug level is a bitmask. - 0x01 = display verbose error messages - 0x02 = developer debug (DEBUG_CURRENT) - 0x04 = display 9p trace - 0x08 = display VFS trace - 0x10 = display Marshalling debug - 0x20 = display RPC debug - 0x40 = display transport debug - 0x80 = display allocation debug - 0x100 = display protocol message debug - 0x200 = display Fid debug - 0x400 = display packet debug - 0x800 = display fscache tracing debug + 0x01 = display verbose error messages + 0x02 = developer debug (DEBUG_CURRENT) + 0x04 = display 9p trace + 0x08 = display VFS trace + 0x10 = display Marshalling debug + 0x20 = display RPC debug + 0x40 = display transport debug + 0x80 = display allocation debug rfdno=n the file descriptor for reading with trans=fd @@ -107,10 +100,6 @@ OPTIONS any = v9fs does single attach and performs all operations as one user - cachetag cache tag to use the specified persistent cache. - cache tags for existing cache sessions can be listed at - /sys/fs/9p/caches. (applies only to cache=fscache) - RESOURCES ========= @@ -129,7 +118,7 @@ and export. A Linux version of the 9p server is now maintained under the npfs project on sourceforge (http://sourceforge.net/projects/npfs). The currently maintained version is the single-threaded version of the server (named spfs) -available from the same SVN repository. +available from the same CVS repository. There are user and developer mailing lists available through the v9fs project on sourceforge (http://sourceforge.net/projects/v9fs). @@ -137,8 +126,7 @@ on sourceforge (http://sourceforge.net/projects/v9fs). A stand-alone version of the module (which should build for any 2.6 kernel) is available via (http://github.com/ericvh/9p-sac/tree/master) -News and other information is maintained on SWiK (http://swik.net/v9fs) -and the Wiki (http://sf.net/apps/mediawiki/v9fs/index.php). +News and other information is maintained on SWiK (http://swik.net/v9fs). Bug reports may be issued through the kernel.org bugzilla (http://bugzilla.kernel.org) diff --git a/trunk/Documentation/hwmon/coretemp b/trunk/Documentation/hwmon/coretemp index 92267b62db59..dbbe6c7025b0 100644 --- a/trunk/Documentation/hwmon/coretemp +++ b/trunk/Documentation/hwmon/coretemp @@ -4,9 +4,7 @@ Kernel driver coretemp Supported chips: * All Intel Core family Prefix: 'coretemp' - CPUID: family 0x6, models 0xe (Pentium M DC), 0xf (Core 2 DC 65nm), - 0x16 (Core 2 SC 65nm), 0x17 (Penryn 45nm), - 0x1a (Nehalem), 0x1c (Atom), 0x1e (Lynnfield) + CPUID: family 0x6, models 0xe, 0xf, 0x16, 0x17 Datasheet: Intel 64 and IA-32 Architectures Software Developer's Manual Volume 3A: System Programming Guide http://softwarecommunity.intel.com/Wiki/Mobility/720.htm diff --git a/trunk/Documentation/hwmon/fscher b/trunk/Documentation/hwmon/fscher new file mode 100644 index 000000000000..64031659aff3 --- /dev/null +++ b/trunk/Documentation/hwmon/fscher @@ -0,0 +1,169 @@ +Kernel driver fscher +==================== + +Supported chips: + * Fujitsu-Siemens Hermes chip + Prefix: 'fscher' + Addresses scanned: I2C 0x73 + +Authors: + Reinhard Nissl based on work + from Hermann Jung , + Frodo Looijaard , + Philip Edelbrock + +Description +----------- + +This driver implements support for the Fujitsu-Siemens Hermes chip. It is +described in the 'Register Set Specification BMC Hermes based Systemboard' +from Fujitsu-Siemens. + +The Hermes chip implements a hardware-based system management, e.g. for +controlling fan speed and core voltage. There is also a watchdog counter on +the chip which can trigger an alarm and even shut the system down. + +The chip provides three temperature values (CPU, motherboard and +auxiliary), three voltage values (+12V, +5V and battery) and three fans +(power supply, CPU and auxiliary). + +Temperatures are measured in degrees Celsius. The resolution is 1 degree. + +Fan rotation speeds are reported in RPM (rotations per minute). The value +can be divided by a programmable divider (1, 2 or 4) which is stored on +the chip. + +Voltage sensors (also known as "in" sensors) report their values in volts. + +All values are reported as final values from the driver. There is no need +for further calculations. + + +Detailed description +-------------------- + +Below you'll find a single line description of all the bit values. With +this information, you're able to decode e. g. alarms, wdog, etc. To make +use of the watchdog, you'll need to set the watchdog time and enable the +watchdog. After that it is necessary to restart the watchdog time within +the specified period of time, or a system reset will occur. + +* revision + READING & 0xff = 0x??: HERMES revision identification + +* alarms + READING & 0x80 = 0x80: CPU throttling active + READING & 0x80 = 0x00: CPU running at full speed + + READING & 0x10 = 0x10: software event (see control:1) + READING & 0x10 = 0x00: no software event + + READING & 0x08 = 0x08: watchdog event (see wdog:2) + READING & 0x08 = 0x00: no watchdog event + + READING & 0x02 = 0x02: thermal event (see temp*:1) + READING & 0x02 = 0x00: no thermal event + + READING & 0x01 = 0x01: fan event (see fan*:1) + READING & 0x01 = 0x00: no fan event + + READING & 0x13 ! 0x00: ALERT LED is flashing + +* control + READING & 0x01 = 0x01: software event + READING & 0x01 = 0x00: no software event + + WRITING & 0x01 = 0x01: set software event + WRITING & 0x01 = 0x00: clear software event + +* watchdog_control + READING & 0x80 = 0x80: power off on watchdog event while thermal event + READING & 0x80 = 0x00: watchdog power off disabled (just system reset enabled) + + READING & 0x40 = 0x40: watchdog timebase 60 seconds (see also wdog:1) + READING & 0x40 = 0x00: watchdog timebase 2 seconds + + READING & 0x10 = 0x10: watchdog enabled + READING & 0x10 = 0x00: watchdog disabled + + WRITING & 0x80 = 0x80: enable "power off on watchdog event while thermal event" + WRITING & 0x80 = 0x00: disable "power off on watchdog event while thermal event" + + WRITING & 0x40 = 0x40: set watchdog timebase to 60 seconds + WRITING & 0x40 = 0x00: set watchdog timebase to 2 seconds + + WRITING & 0x20 = 0x20: disable watchdog + + WRITING & 0x10 = 0x10: enable watchdog / restart watchdog time + +* watchdog_state + READING & 0x02 = 0x02: watchdog system reset occurred + READING & 0x02 = 0x00: no watchdog system reset occurred + + WRITING & 0x02 = 0x02: clear watchdog event + +* watchdog_preset + READING & 0xff = 0x??: configured watch dog time in units (see wdog:3 0x40) + + WRITING & 0xff = 0x??: configure watch dog time in units + +* in* (0: +5V, 1: +12V, 2: onboard 3V battery) + READING: actual voltage value + +* temp*_status (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor) + READING & 0x02 = 0x02: thermal event (overtemperature) + READING & 0x02 = 0x00: no thermal event + + READING & 0x01 = 0x01: sensor is working + READING & 0x01 = 0x00: sensor is faulty + + WRITING & 0x02 = 0x02: clear thermal event + +* temp*_input (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor) + READING: actual temperature value + +* fan*_status (1: power supply fan, 2: CPU fan, 3: auxiliary fan) + READING & 0x04 = 0x04: fan event (fan fault) + READING & 0x04 = 0x00: no fan event + + WRITING & 0x04 = 0x04: clear fan event + +* fan*_div (1: power supply fan, 2: CPU fan, 3: auxiliary fan) + Divisors 2,4 and 8 are supported, both for reading and writing + +* fan*_pwm (1: power supply fan, 2: CPU fan, 3: auxiliary fan) + READING & 0xff = 0x00: fan may be switched off + READING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V) + READING & 0xff = 0xff: fan must run at maximum speed (supply: 12V) + READING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V) + + WRITING & 0xff = 0x00: fan may be switched off + WRITING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V) + WRITING & 0xff = 0xff: fan must run at maximum speed (supply: 12V) + WRITING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V) + +* fan*_input (1: power supply fan, 2: CPU fan, 3: auxiliary fan) + READING: actual RPM value + + +Limitations +----------- + +* Measuring fan speed +It seems that the chip counts "ripples" (typical fans produce 2 ripples per +rotation while VERAX fans produce 18) in a 9-bit register. This register is +read out every second, then the ripple prescaler (2, 4 or 8) is applied and +the result is stored in the 8 bit output register. Due to the limitation of +the counting register to 9 bits, it is impossible to measure a VERAX fan +properly (even with a prescaler of 8). At its maximum speed of 3500 RPM the +fan produces 1080 ripples per second which causes the counting register to +overflow twice, leading to only 186 RPM. + +* Measuring input voltages +in2 ("battery") reports the voltage of the onboard lithium battery and not ++3.3V from the power supply. + +* Undocumented features +Fujitsu-Siemens Computers has not documented all features of the chip so +far. Their software, System Guard, shows that there are a still some +features which cannot be controlled by this implementation. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 7c1c0b05b298..8f6297881077 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -686,13 +686,6 @@ M: Lennert Buytenhek L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -ARM/INTEL IXP4XX ARM ARCHITECTURE -M: Imre Kaloz -M: Krzysztof Halasa -L: linux-arm-kernel@lists.infradead.org -S: Maintained -F: arch/arm/mach-ixp4xx/ - ARM/INTEL XSC3 (MANZANO) ARM CORE M: Lennert Buytenhek M: Dan Williams diff --git a/trunk/arch/arm/mach-ixp4xx/common.c b/trunk/arch/arm/mach-ixp4xx/common.c index cfd52fb341cb..5083f03e9b5e 100644 --- a/trunk/arch/arm/mach-ixp4xx/common.c +++ b/trunk/arch/arm/mach-ixp4xx/common.c @@ -41,8 +41,8 @@ #include #include -static void __init ixp4xx_clocksource_init(void); -static void __init ixp4xx_clockevent_init(void); +static int __init ixp4xx_clocksource_init(void); +static int __init ixp4xx_clockevent_init(void); static struct clock_event_device clockevent_ixp4xx; /************************************************************************* @@ -267,7 +267,7 @@ void __init ixp4xx_init_irq(void) static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) { - struct clock_event_device *evt = dev_id; + struct clock_event_device *evt = &clockevent_ixp4xx; /* Clear Pending Interrupt by writing '1' to it */ *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; @@ -281,7 +281,6 @@ static struct irqaction ixp4xx_timer_irq = { .name = "timer1", .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, .handler = ixp4xx_timer_interrupt, - .dev_id = &clockevent_ixp4xx, }; void __init ixp4xx_timer_init(void) @@ -402,7 +401,7 @@ void __init ixp4xx_sys_init(void) /* * clocksource */ -static cycle_t ixp4xx_get_cycles(struct clocksource *cs) +cycle_t ixp4xx_get_cycles(struct clocksource *cs) { return *IXP4XX_OSTS; } @@ -418,12 +417,14 @@ static struct clocksource clocksource_ixp4xx = { unsigned long ixp4xx_timer_freq = FREQ; EXPORT_SYMBOL(ixp4xx_timer_freq); -static void __init ixp4xx_clocksource_init(void) +static int __init ixp4xx_clocksource_init(void) { clocksource_ixp4xx.mult = clocksource_hz2mult(ixp4xx_timer_freq, clocksource_ixp4xx.shift); clocksource_register(&clocksource_ixp4xx); + + return 0; } /* @@ -479,7 +480,7 @@ static struct clock_event_device clockevent_ixp4xx = { .set_next_event = ixp4xx_set_next_event, }; -static void __init ixp4xx_clockevent_init(void) +static int __init ixp4xx_clockevent_init(void) { clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC, clockevent_ixp4xx.shift); @@ -490,4 +491,5 @@ static void __init ixp4xx_clockevent_init(void) clockevent_ixp4xx.cpumask = cpumask_of(0); clockevents_register_device(&clockevent_ixp4xx); + return 0; } diff --git a/trunk/arch/arm/mach-ixp4xx/include/mach/system.h b/trunk/arch/arm/mach-ixp4xx/include/mach/system.h index 54c0af7fa2d4..d2aa26f5acd7 100644 --- a/trunk/arch/arm/mach-ixp4xx/include/mach/system.h +++ b/trunk/arch/arm/mach-ixp4xx/include/mach/system.h @@ -13,11 +13,9 @@ static inline void arch_idle(void) { - /* ixp4xx does not implement the XScale PWRMODE register, - * so it must not call cpu_do_idle() here. - */ #if 0 - cpu_do_idle(); + if (!hlt_counter) + cpu_do_idle(0); #endif } diff --git a/trunk/drivers/char/tpm/tpm.c b/trunk/drivers/char/tpm/tpm.c index 45d58002b06c..32b957efa420 100644 --- a/trunk/drivers/char/tpm/tpm.c +++ b/trunk/drivers/char/tpm/tpm.c @@ -742,7 +742,7 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read); * the module usage count. */ #define TPM_ORD_PCR_EXTEND cpu_to_be32(20) -#define EXTEND_PCR_RESULT_SIZE 34 +#define EXTEND_PCR_SIZE 34 static struct tpm_input_header pcrextend_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(34), @@ -760,9 +760,10 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) return -ENODEV; cmd.header.in = pcrextend_header; + BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); - rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, + rc = transmit_cmd(chip, &cmd, cmd.header.in.length, "attempting extend a PCR value"); module_put(chip->dev->driver->owner); diff --git a/trunk/drivers/hwmon/Kconfig b/trunk/drivers/hwmon/Kconfig index 6857560144bd..ed7711d11ae8 100644 --- a/trunk/drivers/hwmon/Kconfig +++ b/trunk/drivers/hwmon/Kconfig @@ -325,6 +325,34 @@ config SENSORS_F75375S This driver can also be built as a module. If so, the module will be called f75375s. +config SENSORS_FSCHER + tristate "FSC Hermes (DEPRECATED)" + depends on X86 && I2C + help + This driver is DEPRECATED please use the new merged fschmd + ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver + instead. + + If you say yes here you get support for Fujitsu Siemens + Computers Hermes sensor chips. + + This driver can also be built as a module. If so, the module + will be called fscher. + +config SENSORS_FSCPOS + tristate "FSC Poseidon (DEPRECATED)" + depends on X86 && I2C + help + This driver is DEPRECATED please use the new merged fschmd + ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver + instead. + + If you say yes here you get support for Fujitsu Siemens + Computers Poseidon sensor chips. + + This driver can also be built as a module. If so, the module + will be called fscpos. + config SENSORS_FSCHMD tristate "Fujitsu Siemens Computers sensor chips" depends on X86 && I2C @@ -373,12 +401,12 @@ config SENSORS_GL520SM will be called gl520sm. config SENSORS_CORETEMP - tristate "Intel Core/Core2/Atom temperature sensor" + tristate "Intel Core (2) Duo/Solo temperature sensor" depends on X86 && EXPERIMENTAL help If you say yes here you get support for the temperature - sensor inside your CPU. Most of the family 6 CPUs - are supported. Check documentation/driver for details. + sensor inside your CPU. Supported all are all known variants + of Intel Core family. config SENSORS_IBMAEM tristate "IBM Active Energy Manager temperature/power sensors and control" diff --git a/trunk/drivers/hwmon/Makefile b/trunk/drivers/hwmon/Makefile index 9f46cb019cc6..bcf73a9bb619 100644 --- a/trunk/drivers/hwmon/Makefile +++ b/trunk/drivers/hwmon/Makefile @@ -42,7 +42,9 @@ obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o +obj-$(CONFIG_SENSORS_FSCHER) += fscher.o obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o +obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_G760A) += g760a.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o diff --git a/trunk/drivers/hwmon/adm1031.c b/trunk/drivers/hwmon/adm1031.c index 56905955352c..789441830cd8 100644 --- a/trunk/drivers/hwmon/adm1031.c +++ b/trunk/drivers/hwmon/adm1031.c @@ -37,7 +37,6 @@ #define ADM1031_REG_PWM (0x22) #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) -#define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) @@ -94,7 +93,6 @@ struct adm1031_data { u8 auto_temp_min[3]; u8 auto_temp_off[3]; u8 auto_temp_max[3]; - s8 temp_offset[3]; s8 temp_min[3]; s8 temp_max[3]; s8 temp_crit[3]; @@ -147,10 +145,6 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) -#define TEMP_OFFSET_TO_REG(val) (TEMP_TO_REG(val) & 0x8f) -#define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \ - (val) | 0x70 : (val)) - #define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) : 0) static int FAN_TO_REG(int reg, int div) @@ -591,14 +585,6 @@ static ssize_t show_temp(struct device *dev, (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); } -static ssize_t show_temp_offset(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", - TEMP_OFFSET_FROM_REG(data->temp_offset[nr])); -} static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, char *buf) { @@ -620,24 +606,6 @@ static ssize_t show_temp_crit(struct device *dev, struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); } -static ssize_t set_temp_offset(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - int val; - - val = simple_strtol(buf, NULL, 10); - val = SENSORS_LIMIT(val, -15000, 15000); - mutex_lock(&data->update_lock); - data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val); - adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr), - data->temp_offset[nr]); - mutex_unlock(&data->update_lock); - return count; -} static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -693,8 +661,6 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, #define temp_reg(offset) \ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ - show_temp_offset, set_temp_offset, offset - 1); \ static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ show_temp_min, set_temp_min, offset - 1); \ static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ @@ -748,7 +714,6 @@ static struct attribute *adm1031_attributes[] = { &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_offset.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, @@ -756,7 +721,6 @@ static struct attribute *adm1031_attributes[] = { &sensor_dev_attr_temp1_crit.dev_attr.attr, &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, @@ -793,7 +757,6 @@ static struct attribute *adm1031_attributes_opt[] = { &sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, @@ -974,9 +937,6 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) } data->temp[chan] = newh; - data->temp_offset[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_OFFSET(chan)); data->temp_min[chan] = adm1031_read_value(client, ADM1031_REG_TEMP_MIN(chan)); diff --git a/trunk/drivers/hwmon/coretemp.c b/trunk/drivers/hwmon/coretemp.c index caef39cda8c8..972cf4ba963c 100644 --- a/trunk/drivers/hwmon/coretemp.c +++ b/trunk/drivers/hwmon/coretemp.c @@ -157,26 +157,17 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * /* The 100C is default for both mobile and non mobile CPUs */ int tjmax = 100000; - int tjmax_ee = 85000; - int usemsr_ee = 1; + int ismobile = 1; int err; u32 eax, edx; /* Early chips have no MSR for TjMax */ if ((c->x86_model == 0xf) && (c->x86_mask < 4)) { - usemsr_ee = 0; + ismobile = 0; } - /* Atoms seems to have TjMax at 90C */ - - if (c->x86_model == 0x1c) { - usemsr_ee = 0; - tjmax = 90000; - } - - if ((c->x86_model > 0xe) && (usemsr_ee)) { - u8 platform_id; + if ((c->x86_model > 0xe) && (ismobile)) { /* Now we can detect the mobile CPU using Intel provided table http://softwarecommunity.intel.com/Wiki/Mobility/720.htm @@ -188,29 +179,13 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * dev_warn(dev, "Unable to access MSR 0x17, assuming desktop" " CPU\n"); - usemsr_ee = 0; - } else if (c->x86_model < 0x17 && !(eax & 0x10000000)) { - /* Trust bit 28 up to Penryn, I could not find any - documentation on that; if you happen to know - someone at Intel please ask */ - usemsr_ee = 0; - } else { - /* Platform ID bits 52:50 (EDX starts at bit 32) */ - platform_id = (edx >> 18) & 0x7; - - /* Mobile Penryn CPU seems to be platform ID 7 or 5 - (guesswork) */ - if ((c->x86_model == 0x17) && - ((platform_id == 5) || (platform_id == 7))) { - /* If MSR EE bit is set, set it to 90 degrees C, - otherwise 105 degrees C */ - tjmax_ee = 90000; - tjmax = 105000; - } + ismobile = 0; + } else if (!(eax & 0x10000000)) { + ismobile = 0; } } - if (usemsr_ee) { + if (ismobile || c->x86_model == 0x1c) { err = rdmsr_safe_on_cpu(id, 0xee, &eax, &edx); if (err) { @@ -218,11 +193,9 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * "Unable to access MSR 0xEE, for Tjmax, left" " at default"); } else if (eax & 0x40000000) { - tjmax = tjmax_ee; + tjmax = 85000; } - /* if we dont use msr EE it means we are desktop CPU (with exeception - of Atom) */ - } else if (tjmax == 100000) { + } else { dev_warn(dev, "Using relative temperature scale!\n"); } @@ -275,9 +248,9 @@ static int __devinit coretemp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); /* read the still undocumented IA32_TEMPERATURE_TARGET it exists - on older CPUs but not in this register, Atoms don't have it either */ + on older CPUs but not in this register */ - if ((c->x86_model > 0xe) && (c->x86_model != 0x1c)) { + if (c->x86_model > 0xe) { err = rdmsr_safe_on_cpu(data->id, 0x1a2, &eax, &edx); if (err) { dev_warn(&pdev->dev, "Unable to read" @@ -440,15 +413,11 @@ static int __init coretemp_init(void) for_each_online_cpu(i) { struct cpuinfo_x86 *c = &cpu_data(i); - /* check if family 6, models 0xe (Pentium M DC), - 0xf (Core 2 DC 65nm), 0x16 (Core 2 SC 65nm), - 0x17 (Penryn 45nm), 0x1a (Nehalem), 0x1c (Atom), - 0x1e (Lynnfield) */ + /* check if family 6, models 0xe, 0xf, 0x16, 0x17, 0x1A */ if ((c->cpuid_level < 0) || (c->x86 != 0x6) || !((c->x86_model == 0xe) || (c->x86_model == 0xf) || (c->x86_model == 0x16) || (c->x86_model == 0x17) || - (c->x86_model == 0x1a) || (c->x86_model == 0x1c) || - (c->x86_model == 0x1e))) { + (c->x86_model == 0x1A) || (c->x86_model == 0x1c))) { /* supported CPU not found, but report the unknown family 6 CPU */ diff --git a/trunk/drivers/hwmon/fscher.c b/trunk/drivers/hwmon/fscher.c new file mode 100644 index 000000000000..12c70e402cb2 --- /dev/null +++ b/trunk/drivers/hwmon/fscher.c @@ -0,0 +1,680 @@ +/* + * fscher.c - Part of lm_sensors, Linux kernel modules for hardware + * monitoring + * Copyright (C) 2003, 2004 Reinhard Nissl + * + * 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. + */ + +/* + * fujitsu siemens hermes chip, + * module based on fscpos.c + * Copyright (C) 2000 Hermann Jung + * Copyright (C) 1998, 1999 Frodo Looijaard + * and Philip Edelbrock + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Addresses to scan + */ + +static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; + +/* + * Insmod parameters + */ + +I2C_CLIENT_INSMOD_1(fscher); + +/* + * The FSCHER registers + */ + +/* chip identification */ +#define FSCHER_REG_IDENT_0 0x00 +#define FSCHER_REG_IDENT_1 0x01 +#define FSCHER_REG_IDENT_2 0x02 +#define FSCHER_REG_REVISION 0x03 + +/* global control and status */ +#define FSCHER_REG_EVENT_STATE 0x04 +#define FSCHER_REG_CONTROL 0x05 + +/* watchdog */ +#define FSCHER_REG_WDOG_PRESET 0x28 +#define FSCHER_REG_WDOG_STATE 0x23 +#define FSCHER_REG_WDOG_CONTROL 0x21 + +/* fan 0 */ +#define FSCHER_REG_FAN0_MIN 0x55 +#define FSCHER_REG_FAN0_ACT 0x0e +#define FSCHER_REG_FAN0_STATE 0x0d +#define FSCHER_REG_FAN0_RIPPLE 0x0f + +/* fan 1 */ +#define FSCHER_REG_FAN1_MIN 0x65 +#define FSCHER_REG_FAN1_ACT 0x6b +#define FSCHER_REG_FAN1_STATE 0x62 +#define FSCHER_REG_FAN1_RIPPLE 0x6f + +/* fan 2 */ +#define FSCHER_REG_FAN2_MIN 0xb5 +#define FSCHER_REG_FAN2_ACT 0xbb +#define FSCHER_REG_FAN2_STATE 0xb2 +#define FSCHER_REG_FAN2_RIPPLE 0xbf + +/* voltage supervision */ +#define FSCHER_REG_VOLT_12 0x45 +#define FSCHER_REG_VOLT_5 0x42 +#define FSCHER_REG_VOLT_BATT 0x48 + +/* temperature 0 */ +#define FSCHER_REG_TEMP0_ACT 0x64 +#define FSCHER_REG_TEMP0_STATE 0x71 + +/* temperature 1 */ +#define FSCHER_REG_TEMP1_ACT 0x32 +#define FSCHER_REG_TEMP1_STATE 0x81 + +/* temperature 2 */ +#define FSCHER_REG_TEMP2_ACT 0x35 +#define FSCHER_REG_TEMP2_STATE 0x91 + +/* + * Functions declaration + */ + +static int fscher_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int fscher_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int fscher_remove(struct i2c_client *client); +static struct fscher_data *fscher_update_device(struct device *dev); +static void fscher_init_client(struct i2c_client *client); + +static int fscher_read_value(struct i2c_client *client, u8 reg); +static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value); + +/* + * Driver data (common to all clients) + */ + +static const struct i2c_device_id fscher_id[] = { + { "fscher", fscher }, + { } +}; + +static struct i2c_driver fscher_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "fscher", + }, + .probe = fscher_probe, + .remove = fscher_remove, + .id_table = fscher_id, + .detect = fscher_detect, + .address_data = &addr_data, +}; + +/* + * Client data (each client gets its own) + */ + +struct fscher_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + + /* register values */ + u8 revision; /* revision of chip */ + u8 global_event; /* global event status */ + u8 global_control; /* global control register */ + u8 watchdog[3]; /* watchdog */ + u8 volt[3]; /* 12, 5, battery voltage */ + u8 temp_act[3]; /* temperature */ + u8 temp_status[3]; /* status of sensor */ + u8 fan_act[3]; /* fans revolutions per second */ + u8 fan_status[3]; /* fan status */ + u8 fan_min[3]; /* fan min value for rps */ + u8 fan_ripple[3]; /* divider for rps */ +}; + +/* + * Sysfs stuff + */ + +#define sysfs_r(kind, sub, offset, reg) \ +static ssize_t show_##kind##sub (struct fscher_data *, char *, int); \ +static ssize_t show_##kind##offset##sub (struct device *, struct device_attribute *attr, char *); \ +static ssize_t show_##kind##offset##sub (struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct fscher_data *data = fscher_update_device(dev); \ + return show_##kind##sub(data, buf, (offset)); \ +} + +#define sysfs_w(kind, sub, offset, reg) \ +static ssize_t set_##kind##sub (struct i2c_client *, struct fscher_data *, const char *, size_t, int, int); \ +static ssize_t set_##kind##offset##sub (struct device *, struct device_attribute *attr, const char *, size_t); \ +static ssize_t set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct fscher_data *data = i2c_get_clientdata(client); \ + return set_##kind##sub(client, data, buf, count, (offset), reg); \ +} + +#define sysfs_rw_n(kind, sub, offset, reg) \ +sysfs_r(kind, sub, offset, reg) \ +sysfs_w(kind, sub, offset, reg) \ +static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, show_##kind##offset##sub, set_##kind##offset##sub); + +#define sysfs_rw(kind, sub, reg) \ +sysfs_r(kind, sub, 0, reg) \ +sysfs_w(kind, sub, 0, reg) \ +static DEVICE_ATTR(kind##sub, S_IRUGO | S_IWUSR, show_##kind##0##sub, set_##kind##0##sub); + +#define sysfs_ro_n(kind, sub, offset, reg) \ +sysfs_r(kind, sub, offset, reg) \ +static DEVICE_ATTR(kind##offset##sub, S_IRUGO, show_##kind##offset##sub, NULL); + +#define sysfs_ro(kind, sub, reg) \ +sysfs_r(kind, sub, 0, reg) \ +static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL); + +#define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \ +sysfs_rw_n(pwm, , offset, reg_min) \ +sysfs_rw_n(fan, _status, offset, reg_status) \ +sysfs_rw_n(fan, _div , offset, reg_ripple) \ +sysfs_ro_n(fan, _input , offset, reg_act) + +#define sysfs_temp(offset, reg_status, reg_act) \ +sysfs_rw_n(temp, _status, offset, reg_status) \ +sysfs_ro_n(temp, _input , offset, reg_act) + +#define sysfs_in(offset, reg_act) \ +sysfs_ro_n(in, _input, offset, reg_act) + +#define sysfs_revision(reg_revision) \ +sysfs_ro(revision, , reg_revision) + +#define sysfs_alarms(reg_events) \ +sysfs_ro(alarms, , reg_events) + +#define sysfs_control(reg_control) \ +sysfs_rw(control, , reg_control) + +#define sysfs_watchdog(reg_control, reg_status, reg_preset) \ +sysfs_rw(watchdog, _control, reg_control) \ +sysfs_rw(watchdog, _status , reg_status) \ +sysfs_rw(watchdog, _preset , reg_preset) + +sysfs_fan(1, FSCHER_REG_FAN0_STATE, FSCHER_REG_FAN0_MIN, + FSCHER_REG_FAN0_RIPPLE, FSCHER_REG_FAN0_ACT) +sysfs_fan(2, FSCHER_REG_FAN1_STATE, FSCHER_REG_FAN1_MIN, + FSCHER_REG_FAN1_RIPPLE, FSCHER_REG_FAN1_ACT) +sysfs_fan(3, FSCHER_REG_FAN2_STATE, FSCHER_REG_FAN2_MIN, + FSCHER_REG_FAN2_RIPPLE, FSCHER_REG_FAN2_ACT) + +sysfs_temp(1, FSCHER_REG_TEMP0_STATE, FSCHER_REG_TEMP0_ACT) +sysfs_temp(2, FSCHER_REG_TEMP1_STATE, FSCHER_REG_TEMP1_ACT) +sysfs_temp(3, FSCHER_REG_TEMP2_STATE, FSCHER_REG_TEMP2_ACT) + +sysfs_in(0, FSCHER_REG_VOLT_12) +sysfs_in(1, FSCHER_REG_VOLT_5) +sysfs_in(2, FSCHER_REG_VOLT_BATT) + +sysfs_revision(FSCHER_REG_REVISION) +sysfs_alarms(FSCHER_REG_EVENTS) +sysfs_control(FSCHER_REG_CONTROL) +sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET) + +static struct attribute *fscher_attributes[] = { + &dev_attr_revision.attr, + &dev_attr_alarms.attr, + &dev_attr_control.attr, + + &dev_attr_watchdog_status.attr, + &dev_attr_watchdog_control.attr, + &dev_attr_watchdog_preset.attr, + + &dev_attr_in0_input.attr, + &dev_attr_in1_input.attr, + &dev_attr_in2_input.attr, + + &dev_attr_fan1_status.attr, + &dev_attr_fan1_div.attr, + &dev_attr_fan1_input.attr, + &dev_attr_pwm1.attr, + &dev_attr_fan2_status.attr, + &dev_attr_fan2_div.attr, + &dev_attr_fan2_input.attr, + &dev_attr_pwm2.attr, + &dev_attr_fan3_status.attr, + &dev_attr_fan3_div.attr, + &dev_attr_fan3_input.attr, + &dev_attr_pwm3.attr, + + &dev_attr_temp1_status.attr, + &dev_attr_temp1_input.attr, + &dev_attr_temp2_status.attr, + &dev_attr_temp2_input.attr, + &dev_attr_temp3_status.attr, + &dev_attr_temp3_input.attr, + NULL +}; + +static const struct attribute_group fscher_group = { + .attrs = fscher_attributes, +}; + +/* + * Real code + */ + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int fscher_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + /* Do the remaining detection unless force or force_fscher parameter */ + if (kind < 0) { + if ((i2c_smbus_read_byte_data(new_client, + FSCHER_REG_IDENT_0) != 0x48) /* 'H' */ + || (i2c_smbus_read_byte_data(new_client, + FSCHER_REG_IDENT_1) != 0x45) /* 'E' */ + || (i2c_smbus_read_byte_data(new_client, + FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */ + return -ENODEV; + } + + strlcpy(info->type, "fscher", I2C_NAME_SIZE); + + return 0; +} + +static int fscher_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct fscher_data *data; + int err; + + data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(new_client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + fscher_init_client(new_client); + + /* Register sysfs hooks */ + if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group))) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove_files; + } + + return 0; + +exit_remove_files: + sysfs_remove_group(&new_client->dev.kobj, &fscher_group); +exit_free: + kfree(data); +exit: + return err; +} + +static int fscher_remove(struct i2c_client *client) +{ + struct fscher_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &fscher_group); + + kfree(data); + return 0; +} + +static int fscher_read_value(struct i2c_client *client, u8 reg) +{ + dev_dbg(&client->dev, "read reg 0x%02x\n", reg); + + return i2c_smbus_read_byte_data(client, reg); +} + +static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + dev_dbg(&client->dev, "write reg 0x%02x, val 0x%02x\n", + reg, value); + + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* Called when we have found a new FSC Hermes. */ +static void fscher_init_client(struct i2c_client *client) +{ + struct fscher_data *data = i2c_get_clientdata(client); + + /* Read revision from chip */ + data->revision = fscher_read_value(client, FSCHER_REG_REVISION); +} + +static struct fscher_data *fscher_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct fscher_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + + dev_dbg(&client->dev, "Starting fscher update\n"); + + data->temp_act[0] = fscher_read_value(client, FSCHER_REG_TEMP0_ACT); + data->temp_act[1] = fscher_read_value(client, FSCHER_REG_TEMP1_ACT); + data->temp_act[2] = fscher_read_value(client, FSCHER_REG_TEMP2_ACT); + data->temp_status[0] = fscher_read_value(client, FSCHER_REG_TEMP0_STATE); + data->temp_status[1] = fscher_read_value(client, FSCHER_REG_TEMP1_STATE); + data->temp_status[2] = fscher_read_value(client, FSCHER_REG_TEMP2_STATE); + + data->volt[0] = fscher_read_value(client, FSCHER_REG_VOLT_12); + data->volt[1] = fscher_read_value(client, FSCHER_REG_VOLT_5); + data->volt[2] = fscher_read_value(client, FSCHER_REG_VOLT_BATT); + + data->fan_act[0] = fscher_read_value(client, FSCHER_REG_FAN0_ACT); + data->fan_act[1] = fscher_read_value(client, FSCHER_REG_FAN1_ACT); + data->fan_act[2] = fscher_read_value(client, FSCHER_REG_FAN2_ACT); + data->fan_status[0] = fscher_read_value(client, FSCHER_REG_FAN0_STATE); + data->fan_status[1] = fscher_read_value(client, FSCHER_REG_FAN1_STATE); + data->fan_status[2] = fscher_read_value(client, FSCHER_REG_FAN2_STATE); + data->fan_min[0] = fscher_read_value(client, FSCHER_REG_FAN0_MIN); + data->fan_min[1] = fscher_read_value(client, FSCHER_REG_FAN1_MIN); + data->fan_min[2] = fscher_read_value(client, FSCHER_REG_FAN2_MIN); + data->fan_ripple[0] = fscher_read_value(client, FSCHER_REG_FAN0_RIPPLE); + data->fan_ripple[1] = fscher_read_value(client, FSCHER_REG_FAN1_RIPPLE); + data->fan_ripple[2] = fscher_read_value(client, FSCHER_REG_FAN2_RIPPLE); + + data->watchdog[0] = fscher_read_value(client, FSCHER_REG_WDOG_PRESET); + data->watchdog[1] = fscher_read_value(client, FSCHER_REG_WDOG_STATE); + data->watchdog[2] = fscher_read_value(client, FSCHER_REG_WDOG_CONTROL); + + data->global_event = fscher_read_value(client, FSCHER_REG_EVENT_STATE); + data->global_control = fscher_read_value(client, + FSCHER_REG_CONTROL); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + + + +#define FAN_INDEX_FROM_NUM(nr) ((nr) - 1) + +static ssize_t set_fan_status(struct i2c_client *client, struct fscher_data *data, + const char *buf, size_t count, int nr, int reg) +{ + /* bits 0..1, 3..7 reserved => mask with 0x04 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04; + + mutex_lock(&data->update_lock); + data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v; + fscher_write_value(client, reg, v); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_fan_status(struct fscher_data *data, char *buf, int nr) +{ + /* bits 0..1, 3..7 reserved => mask with 0x04 */ + return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04); +} + +static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data, + const char *buf, size_t count, int nr, int reg) +{ + unsigned long v = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; + fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_pwm(struct fscher_data *data, char *buf, int nr) +{ + return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]); +} + +static ssize_t set_fan_div(struct i2c_client *client, struct fscher_data *data, + const char *buf, size_t count, int nr, int reg) +{ + /* supported values: 2, 4, 8 */ + unsigned long v = simple_strtoul(buf, NULL, 10); + + switch (v) { + case 2: v = 1; break; + case 4: v = 2; break; + case 8: v = 3; break; + default: + dev_err(&client->dev, "fan_div value %ld not " + "supported. Choose one of 2, 4 or 8!\n", v); + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + /* bits 2..7 reserved => mask with 0x03 */ + data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03; + data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v; + + fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_fan_div(struct fscher_data *data, char *buf, int nr) +{ + /* bits 2..7 reserved => mask with 0x03 */ + return sprintf(buf, "%u\n", 1 << (data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] & 0x03)); +} + +#define RPM_FROM_REG(val) (val*60) + +static ssize_t show_fan_input (struct fscher_data *data, char *buf, int nr) +{ + return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[FAN_INDEX_FROM_NUM(nr)])); +} + + + +#define TEMP_INDEX_FROM_NUM(nr) ((nr) - 1) + +static ssize_t set_temp_status(struct i2c_client *client, struct fscher_data *data, + const char *buf, size_t count, int nr, int reg) +{ + /* bits 2..7 reserved, 0 read only => mask with 0x02 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; + + mutex_lock(&data->update_lock); + data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v; + fscher_write_value(client, reg, v); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_temp_status(struct fscher_data *data, char *buf, int nr) +{ + /* bits 2..7 reserved => mask with 0x03 */ + return sprintf(buf, "%u\n", data->temp_status[TEMP_INDEX_FROM_NUM(nr)] & 0x03); +} + +#define TEMP_FROM_REG(val) (((val) - 128) * 1000) + +static ssize_t show_temp_input(struct fscher_data *data, char *buf, int nr) +{ + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[TEMP_INDEX_FROM_NUM(nr)])); +} + +/* + * The final conversion is specified in sensors.conf, as it depends on + * mainboard specific values. We export the registers contents as + * pseudo-hundredths-of-Volts (range 0V - 2.55V). Not that it makes much + * sense per se, but it minimizes the conversions count and keeps the + * values within a usual range. + */ +#define VOLT_FROM_REG(val) ((val) * 10) + +static ssize_t show_in_input(struct fscher_data *data, char *buf, int nr) +{ + return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[nr])); +} + + + +static ssize_t show_revision(struct fscher_data *data, char *buf, int nr) +{ + return sprintf(buf, "%u\n", data->revision); +} + + + +static ssize_t show_alarms(struct fscher_data *data, char *buf, int nr) +{ + /* bits 2, 5..6 reserved => mask with 0x9b */ + return sprintf(buf, "%u\n", data->global_event & 0x9b); +} + + + +static ssize_t set_control(struct i2c_client *client, struct fscher_data *data, + const char *buf, size_t count, int nr, int reg) +{ + /* bits 1..7 reserved => mask with 0x01 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; + + mutex_lock(&data->update_lock); + data->global_control = v; + fscher_write_value(client, reg, v); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_control(struct fscher_data *data, char *buf, int nr) +{ + /* bits 1..7 reserved => mask with 0x01 */ + return sprintf(buf, "%u\n", data->global_control & 0x01); +} + + + +static ssize_t set_watchdog_control(struct i2c_client *client, struct + fscher_data *data, const char *buf, size_t count, + int nr, int reg) +{ + /* bits 0..3 reserved => mask with 0xf0 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; + + mutex_lock(&data->update_lock); + data->watchdog[2] &= ~0xf0; + data->watchdog[2] |= v; + fscher_write_value(client, reg, data->watchdog[2]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_watchdog_control(struct fscher_data *data, char *buf, int nr) +{ + /* bits 0..3 reserved, bit 5 write only => mask with 0xd0 */ + return sprintf(buf, "%u\n", data->watchdog[2] & 0xd0); +} + +static ssize_t set_watchdog_status(struct i2c_client *client, struct fscher_data *data, + const char *buf, size_t count, int nr, int reg) +{ + /* bits 0, 2..7 reserved => mask with 0x02 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; + + mutex_lock(&data->update_lock); + data->watchdog[1] &= ~v; + fscher_write_value(client, reg, v); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_watchdog_status(struct fscher_data *data, char *buf, int nr) +{ + /* bits 0, 2..7 reserved => mask with 0x02 */ + return sprintf(buf, "%u\n", data->watchdog[1] & 0x02); +} + +static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data *data, + const char *buf, size_t count, int nr, int reg) +{ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; + + mutex_lock(&data->update_lock); + data->watchdog[0] = v; + fscher_write_value(client, reg, data->watchdog[0]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_watchdog_preset(struct fscher_data *data, char *buf, int nr) +{ + return sprintf(buf, "%u\n", data->watchdog[0]); +} + +static int __init sensors_fscher_init(void) +{ + return i2c_add_driver(&fscher_driver); +} + +static void __exit sensors_fscher_exit(void) +{ + i2c_del_driver(&fscher_driver); +} + +MODULE_AUTHOR("Reinhard Nissl "); +MODULE_DESCRIPTION("FSC Hermes driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_fscher_init); +module_exit(sensors_fscher_exit); diff --git a/trunk/drivers/hwmon/fscpos.c b/trunk/drivers/hwmon/fscpos.c new file mode 100644 index 000000000000..8a7bcf500b4e --- /dev/null +++ b/trunk/drivers/hwmon/fscpos.c @@ -0,0 +1,654 @@ +/* + fscpos.c - Kernel module for hardware monitoring with FSC Poseidon chips + Copyright (C) 2004, 2005 Stefan Ott + + 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. +*/ + +/* + fujitsu siemens poseidon chip, + module based on the old fscpos module by Hermann Jung and + the fscher module by Reinhard Nissl + + original module based on lm80.c + Copyright (C) 1998, 1999 Frodo Looijaard + and Philip Edelbrock + + Thanks to Jean Delvare for reviewing my code and suggesting a lot of + improvements. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Addresses to scan + */ +static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; + +/* + * Insmod parameters + */ +I2C_CLIENT_INSMOD_1(fscpos); + +/* + * The FSCPOS registers + */ + +/* chip identification */ +#define FSCPOS_REG_IDENT_0 0x00 +#define FSCPOS_REG_IDENT_1 0x01 +#define FSCPOS_REG_IDENT_2 0x02 +#define FSCPOS_REG_REVISION 0x03 + +/* global control and status */ +#define FSCPOS_REG_EVENT_STATE 0x04 +#define FSCPOS_REG_CONTROL 0x05 + +/* watchdog */ +#define FSCPOS_REG_WDOG_PRESET 0x28 +#define FSCPOS_REG_WDOG_STATE 0x23 +#define FSCPOS_REG_WDOG_CONTROL 0x21 + +/* voltages */ +#define FSCPOS_REG_VOLT_12 0x45 +#define FSCPOS_REG_VOLT_5 0x42 +#define FSCPOS_REG_VOLT_BATT 0x48 + +/* fans - the chip does not support minimum speed for fan2 */ +static u8 FSCPOS_REG_PWM[] = { 0x55, 0x65 }; +static u8 FSCPOS_REG_FAN_ACT[] = { 0x0e, 0x6b, 0xab }; +static u8 FSCPOS_REG_FAN_STATE[] = { 0x0d, 0x62, 0xa2 }; +static u8 FSCPOS_REG_FAN_RIPPLE[] = { 0x0f, 0x6f, 0xaf }; + +/* temperatures */ +static u8 FSCPOS_REG_TEMP_ACT[] = { 0x64, 0x32, 0x35 }; +static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 }; + +/* + * Functions declaration + */ +static int fscpos_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int fscpos_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int fscpos_remove(struct i2c_client *client); + +static int fscpos_read_value(struct i2c_client *client, u8 reg); +static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); +static struct fscpos_data *fscpos_update_device(struct device *dev); +static void fscpos_init_client(struct i2c_client *client); + +static void reset_fan_alarm(struct i2c_client *client, int nr); + +/* + * Driver data (common to all clients) + */ +static const struct i2c_device_id fscpos_id[] = { + { "fscpos", fscpos }, + { } +}; + +static struct i2c_driver fscpos_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "fscpos", + }, + .probe = fscpos_probe, + .remove = fscpos_remove, + .id_table = fscpos_id, + .detect = fscpos_detect, + .address_data = &addr_data, +}; + +/* + * Client data (each client gets its own) + */ +struct fscpos_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* 0 until following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + /* register values */ + u8 revision; /* revision of chip */ + u8 global_event; /* global event status */ + u8 global_control; /* global control register */ + u8 wdog_control; /* watchdog control */ + u8 wdog_state; /* watchdog status */ + u8 wdog_preset; /* watchdog preset */ + u8 volt[3]; /* 12, 5, battery current */ + u8 temp_act[3]; /* temperature */ + u8 temp_status[3]; /* status of sensor */ + u8 fan_act[3]; /* fans revolutions per second */ + u8 fan_status[3]; /* fan status */ + u8 pwm[2]; /* fan min value for rps */ + u8 fan_ripple[3]; /* divider for rps */ +}; + +/* Temperature */ +#define TEMP_FROM_REG(val) (((val) - 128) * 1000) + +static ssize_t show_temp_input(struct fscpos_data *data, char *buf, int nr) +{ + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[nr - 1])); +} + +static ssize_t show_temp_status(struct fscpos_data *data, char *buf, int nr) +{ + /* bits 2..7 reserved => mask with 0x03 */ + return sprintf(buf, "%u\n", data->temp_status[nr - 1] & 0x03); +} + +static ssize_t show_temp_reset(struct fscpos_data *data, char *buf, int nr) +{ + return sprintf(buf, "1\n"); +} + +static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data + *data, const char *buf, size_t count, int nr, int reg) +{ + unsigned long v = simple_strtoul(buf, NULL, 10); + if (v != 1) { + dev_err(&client->dev, "temp_reset value %ld not supported. " + "Use 1 to reset the alarm!\n", v); + return -EINVAL; + } + + dev_info(&client->dev, "You used the temp_reset feature which has not " + "been proplerly tested. Please report your " + "experience to the module author.\n"); + + /* Supported value: 2 (clears the status) */ + fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr - 1], 2); + return count; +} + +/* Fans */ +#define RPM_FROM_REG(val) ((val) * 60) + +static ssize_t show_fan_status(struct fscpos_data *data, char *buf, int nr) +{ + /* bits 0..1, 3..7 reserved => mask with 0x04 */ + return sprintf(buf, "%u\n", data->fan_status[nr - 1] & 0x04); +} + +static ssize_t show_fan_input(struct fscpos_data *data, char *buf, int nr) +{ + return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[nr - 1])); +} + +static ssize_t show_fan_ripple(struct fscpos_data *data, char *buf, int nr) +{ + /* bits 2..7 reserved => mask with 0x03 */ + return sprintf(buf, "%u\n", data->fan_ripple[nr - 1] & 0x03); +} + +static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data + *data, const char *buf, size_t count, int nr, int reg) +{ + /* supported values: 2, 4, 8 */ + unsigned long v = simple_strtoul(buf, NULL, 10); + + switch (v) { + case 2: v = 1; break; + case 4: v = 2; break; + case 8: v = 3; break; + default: + dev_err(&client->dev, "fan_ripple value %ld not supported. " + "Must be one of 2, 4 or 8!\n", v); + return -EINVAL; + } + + mutex_lock(&data->update_lock); + /* bits 2..7 reserved => mask with 0x03 */ + data->fan_ripple[nr - 1] &= ~0x03; + data->fan_ripple[nr - 1] |= v; + + fscpos_write_value(client, reg, data->fan_ripple[nr - 1]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_pwm(struct fscpos_data *data, char *buf, int nr) +{ + return sprintf(buf, "%u\n", data->pwm[nr - 1]); +} + +static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data, + const char *buf, size_t count, int nr, int reg) +{ + unsigned long v = simple_strtoul(buf, NULL, 10); + + /* Range: 0..255 */ + if (v < 0) v = 0; + if (v > 255) v = 255; + + mutex_lock(&data->update_lock); + data->pwm[nr - 1] = v; + fscpos_write_value(client, reg, data->pwm[nr - 1]); + mutex_unlock(&data->update_lock); + return count; +} + +static void reset_fan_alarm(struct i2c_client *client, int nr) +{ + fscpos_write_value(client, FSCPOS_REG_FAN_STATE[nr], 4); +} + +/* Volts */ +#define VOLT_FROM_REG(val, mult) ((val) * (mult) / 255) + +static ssize_t show_volt_12(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct fscpos_data *data = fscpos_update_device(dev); + return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200)); +} + +static ssize_t show_volt_5(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct fscpos_data *data = fscpos_update_device(dev); + return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600)); +} + +static ssize_t show_volt_batt(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct fscpos_data *data = fscpos_update_device(dev); + return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300)); +} + +/* Watchdog */ +static ssize_t show_wdog_control(struct fscpos_data *data, char *buf) +{ + /* bits 0..3 reserved, bit 6 write only => mask with 0xb0 */ + return sprintf(buf, "%u\n", data->wdog_control & 0xb0); +} + +static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data + *data, const char *buf, size_t count, int reg) +{ + /* bits 0..3 reserved => mask with 0xf0 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; + + mutex_lock(&data->update_lock); + data->wdog_control &= ~0xf0; + data->wdog_control |= v; + fscpos_write_value(client, reg, data->wdog_control); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_wdog_state(struct fscpos_data *data, char *buf) +{ + /* bits 0, 2..7 reserved => mask with 0x02 */ + return sprintf(buf, "%u\n", data->wdog_state & 0x02); +} + +static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data + *data, const char *buf, size_t count, int reg) +{ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; + + /* Valid values: 2 (clear) */ + if (v != 2) { + dev_err(&client->dev, "wdog_state value %ld not supported. " + "Must be 2 to clear the state!\n", v); + return -EINVAL; + } + + mutex_lock(&data->update_lock); + data->wdog_state &= ~v; + fscpos_write_value(client, reg, v); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_wdog_preset(struct fscpos_data *data, char *buf) +{ + return sprintf(buf, "%u\n", data->wdog_preset); +} + +static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data + *data, const char *buf, size_t count, int reg) +{ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; + + mutex_lock(&data->update_lock); + data->wdog_preset = v; + fscpos_write_value(client, reg, data->wdog_preset); + mutex_unlock(&data->update_lock); + return count; +} + +/* Event */ +static ssize_t show_event(struct device *dev, struct device_attribute *attr, char *buf) +{ + /* bits 5..7 reserved => mask with 0x1f */ + struct fscpos_data *data = fscpos_update_device(dev); + return sprintf(buf, "%u\n", data->global_event & 0x9b); +} + +/* + * Sysfs stuff + */ +#define create_getter(kind, sub) \ + static ssize_t sysfs_show_##kind##sub(struct device *dev, struct device_attribute *attr, char *buf) \ + { \ + struct fscpos_data *data = fscpos_update_device(dev); \ + return show_##kind##sub(data, buf); \ + } + +#define create_getter_n(kind, offset, sub) \ + static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, struct device_attribute *attr, char\ + *buf) \ + { \ + struct fscpos_data *data = fscpos_update_device(dev); \ + return show_##kind##sub(data, buf, offset); \ + } + +#define create_setter(kind, sub, reg) \ + static ssize_t sysfs_set_##kind##sub (struct device *dev, struct device_attribute *attr, const char \ + *buf, size_t count) \ + { \ + struct i2c_client *client = to_i2c_client(dev); \ + struct fscpos_data *data = i2c_get_clientdata(client); \ + return set_##kind##sub(client, data, buf, count, reg); \ + } + +#define create_setter_n(kind, offset, sub, reg) \ + static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ + { \ + struct i2c_client *client = to_i2c_client(dev); \ + struct fscpos_data *data = i2c_get_clientdata(client); \ + return set_##kind##sub(client, data, buf, count, offset, reg);\ + } + +#define create_sysfs_device_ro(kind, sub, offset) \ + static DEVICE_ATTR(kind##offset##sub, S_IRUGO, \ + sysfs_show_##kind##offset##sub, NULL); + +#define create_sysfs_device_rw(kind, sub, offset) \ + static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, \ + sysfs_show_##kind##offset##sub, sysfs_set_##kind##offset##sub); + +#define sysfs_ro_n(kind, sub, offset) \ + create_getter_n(kind, offset, sub); \ + create_sysfs_device_ro(kind, sub, offset); + +#define sysfs_rw_n(kind, sub, offset, reg) \ + create_getter_n(kind, offset, sub); \ + create_setter_n(kind, offset, sub, reg); \ + create_sysfs_device_rw(kind, sub, offset); + +#define sysfs_rw(kind, sub, reg) \ + create_getter(kind, sub); \ + create_setter(kind, sub, reg); \ + create_sysfs_device_rw(kind, sub,); + +#define sysfs_fan_with_min(offset, reg_status, reg_ripple, reg_min) \ + sysfs_fan(offset, reg_status, reg_ripple); \ + sysfs_rw_n(pwm,, offset, reg_min); + +#define sysfs_fan(offset, reg_status, reg_ripple) \ + sysfs_ro_n(fan, _input, offset); \ + sysfs_ro_n(fan, _status, offset); \ + sysfs_rw_n(fan, _ripple, offset, reg_ripple); + +#define sysfs_temp(offset, reg_status) \ + sysfs_ro_n(temp, _input, offset); \ + sysfs_ro_n(temp, _status, offset); \ + sysfs_rw_n(temp, _reset, offset, reg_status); + +#define sysfs_watchdog(reg_wdog_preset, reg_wdog_state, reg_wdog_control) \ + sysfs_rw(wdog, _control, reg_wdog_control); \ + sysfs_rw(wdog, _preset, reg_wdog_preset); \ + sysfs_rw(wdog, _state, reg_wdog_state); + +sysfs_fan_with_min(1, FSCPOS_REG_FAN_STATE[0], FSCPOS_REG_FAN_RIPPLE[0], + FSCPOS_REG_PWM[0]); +sysfs_fan_with_min(2, FSCPOS_REG_FAN_STATE[1], FSCPOS_REG_FAN_RIPPLE[1], + FSCPOS_REG_PWM[1]); +sysfs_fan(3, FSCPOS_REG_FAN_STATE[2], FSCPOS_REG_FAN_RIPPLE[2]); + +sysfs_temp(1, FSCPOS_REG_TEMP_STATE[0]); +sysfs_temp(2, FSCPOS_REG_TEMP_STATE[1]); +sysfs_temp(3, FSCPOS_REG_TEMP_STATE[2]); + +sysfs_watchdog(FSCPOS_REG_WDOG_PRESET, FSCPOS_REG_WDOG_STATE, + FSCPOS_REG_WDOG_CONTROL); + +static DEVICE_ATTR(event, S_IRUGO, show_event, NULL); +static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL); +static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL); +static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL); + +static struct attribute *fscpos_attributes[] = { + &dev_attr_event.attr, + &dev_attr_in0_input.attr, + &dev_attr_in1_input.attr, + &dev_attr_in2_input.attr, + + &dev_attr_wdog_control.attr, + &dev_attr_wdog_preset.attr, + &dev_attr_wdog_state.attr, + + &dev_attr_temp1_input.attr, + &dev_attr_temp1_status.attr, + &dev_attr_temp1_reset.attr, + &dev_attr_temp2_input.attr, + &dev_attr_temp2_status.attr, + &dev_attr_temp2_reset.attr, + &dev_attr_temp3_input.attr, + &dev_attr_temp3_status.attr, + &dev_attr_temp3_reset.attr, + + &dev_attr_fan1_input.attr, + &dev_attr_fan1_status.attr, + &dev_attr_fan1_ripple.attr, + &dev_attr_pwm1.attr, + &dev_attr_fan2_input.attr, + &dev_attr_fan2_status.attr, + &dev_attr_fan2_ripple.attr, + &dev_attr_pwm2.attr, + &dev_attr_fan3_input.attr, + &dev_attr_fan3_status.attr, + &dev_attr_fan3_ripple.attr, + NULL +}; + +static const struct attribute_group fscpos_group = { + .attrs = fscpos_attributes, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int fscpos_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + /* Do the remaining detection unless force or force_fscpos parameter */ + if (kind < 0) { + if ((fscpos_read_value(new_client, FSCPOS_REG_IDENT_0) + != 0x50) /* 'P' */ + || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1) + != 0x45) /* 'E' */ + || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2) + != 0x47))/* 'G' */ + return -ENODEV; + } + + strlcpy(info->type, "fscpos", I2C_NAME_SIZE); + + return 0; +} + +static int fscpos_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct fscpos_data *data; + int err; + + data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(new_client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + /* Inizialize the fscpos chip */ + fscpos_init_client(new_client); + + /* Announce that the chip was found */ + dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision); + + /* Register sysfs hooks */ + if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group))) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove_files; + } + + return 0; + +exit_remove_files: + sysfs_remove_group(&new_client->dev.kobj, &fscpos_group); +exit_free: + kfree(data); +exit: + return err; +} + +static int fscpos_remove(struct i2c_client *client) +{ + struct fscpos_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &fscpos_group); + + kfree(data); + return 0; +} + +static int fscpos_read_value(struct i2c_client *client, u8 reg) +{ + dev_dbg(&client->dev, "Read reg 0x%02x\n", reg); + return i2c_smbus_read_byte_data(client, reg); +} + +static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + dev_dbg(&client->dev, "Write reg 0x%02x, val 0x%02x\n", reg, value); + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* Called when we have found a new FSCPOS chip */ +static void fscpos_init_client(struct i2c_client *client) +{ + struct fscpos_data *data = i2c_get_clientdata(client); + + /* read revision from chip */ + data->revision = fscpos_read_value(client, FSCPOS_REG_REVISION); +} + +static struct fscpos_data *fscpos_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct fscpos_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting fscpos update\n"); + + for (i = 0; i < 3; i++) { + data->temp_act[i] = fscpos_read_value(client, + FSCPOS_REG_TEMP_ACT[i]); + data->temp_status[i] = fscpos_read_value(client, + FSCPOS_REG_TEMP_STATE[i]); + data->fan_act[i] = fscpos_read_value(client, + FSCPOS_REG_FAN_ACT[i]); + data->fan_status[i] = fscpos_read_value(client, + FSCPOS_REG_FAN_STATE[i]); + data->fan_ripple[i] = fscpos_read_value(client, + FSCPOS_REG_FAN_RIPPLE[i]); + if (i < 2) { + /* fan2_min is not supported by the chip */ + data->pwm[i] = fscpos_read_value(client, + FSCPOS_REG_PWM[i]); + } + /* reset fan status if speed is back to > 0 */ + if (data->fan_status[i] != 0 && data->fan_act[i] > 0) { + reset_fan_alarm(client, i); + } + } + + data->volt[0] = fscpos_read_value(client, FSCPOS_REG_VOLT_12); + data->volt[1] = fscpos_read_value(client, FSCPOS_REG_VOLT_5); + data->volt[2] = fscpos_read_value(client, FSCPOS_REG_VOLT_BATT); + + data->wdog_preset = fscpos_read_value(client, + FSCPOS_REG_WDOG_PRESET); + data->wdog_state = fscpos_read_value(client, + FSCPOS_REG_WDOG_STATE); + data->wdog_control = fscpos_read_value(client, + FSCPOS_REG_WDOG_CONTROL); + + data->global_event = fscpos_read_value(client, + FSCPOS_REG_EVENT_STATE); + + data->last_updated = jiffies; + data->valid = 1; + } + mutex_unlock(&data->update_lock); + return data; +} + +static int __init sm_fscpos_init(void) +{ + return i2c_add_driver(&fscpos_driver); +} + +static void __exit sm_fscpos_exit(void) +{ + i2c_del_driver(&fscpos_driver); +} + +MODULE_AUTHOR("Stefan Ott based on work from Hermann Jung " + ", Frodo Looijaard " + " and Philip Edelbrock "); +MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver"); +MODULE_LICENSE("GPL"); + +module_init(sm_fscpos_init); +module_exit(sm_fscpos_exit); diff --git a/trunk/drivers/hwmon/ltc4215.c b/trunk/drivers/hwmon/ltc4215.c index 6c9a04136e0a..9386e2a39211 100644 --- a/trunk/drivers/hwmon/ltc4215.c +++ b/trunk/drivers/hwmon/ltc4215.c @@ -259,7 +259,7 @@ static int ltc4215_probe(struct i2c_client *client, mutex_init(&data->update_lock); /* Initialize the LTC4215 chip */ - i2c_smbus_write_byte_data(client, LTC4215_FAULT, 0x00); + /* TODO */ /* Register sysfs hooks */ ret = sysfs_create_group(&client->dev.kobj, <c4215_group); diff --git a/trunk/drivers/hwmon/ltc4245.c b/trunk/drivers/hwmon/ltc4245.c index e38964333612..034b2c515848 100644 --- a/trunk/drivers/hwmon/ltc4245.c +++ b/trunk/drivers/hwmon/ltc4245.c @@ -382,8 +382,7 @@ static int ltc4245_probe(struct i2c_client *client, mutex_init(&data->update_lock); /* Initialize the LTC4245 chip */ - i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00); - i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00); + /* TODO */ /* Register sysfs hooks */ ret = sysfs_create_group(&client->dev.kobj, <c4245_group); diff --git a/trunk/drivers/serial/serial_core.c b/trunk/drivers/serial/serial_core.c index 1689bda1d13b..2514d00c0f6f 100644 --- a/trunk/drivers/serial/serial_core.c +++ b/trunk/drivers/serial/serial_core.c @@ -2426,7 +2426,7 @@ struct tty_driver *uart_console_device(struct console *co, int *index) /** * uart_add_one_port - attach a driver-defined port structure * @drv: pointer to the uart low level driver structure for this port - * @uport: uart port structure to use for this port. + * @port: uart port structure to use for this port. * * This allows the driver to register its own uart_port structure * with the core driver. The main purpose is to allow the low @@ -2499,7 +2499,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) /** * uart_remove_one_port - detach a driver defined port structure * @drv: pointer to the uart low level driver structure for this port - * @uport: uart port structure for this port + * @port: uart port structure for this port * * This unhooks (and hangs up) the specified port structure from the * core driver. No further calls will be made to the low-level code diff --git a/trunk/fs/9p/Kconfig b/trunk/fs/9p/Kconfig index 795233702a4e..74e0723e90bc 100644 --- a/trunk/fs/9p/Kconfig +++ b/trunk/fs/9p/Kconfig @@ -8,12 +8,3 @@ config 9P_FS See for more information. If unsure, say N. - -config 9P_FSCACHE - bool "Enable 9P client caching support (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on 9P_FS=m && FSCACHE || 9P_FS=y && FSCACHE=y - help - Choose Y here to enable persistent, read-only local - caching support for 9p clients using FS-Cache - diff --git a/trunk/fs/9p/Makefile b/trunk/fs/9p/Makefile index 1a940ec7af61..bc7f0d1551e6 100644 --- a/trunk/fs/9p/Makefile +++ b/trunk/fs/9p/Makefile @@ -8,6 +8,5 @@ obj-$(CONFIG_9P_FS) := 9p.o vfs_dir.o \ vfs_dentry.o \ v9fs.o \ - fid.o + fid.o \ -9p-$(CONFIG_9P_FSCACHE) += cache.o diff --git a/trunk/fs/9p/cache.c b/trunk/fs/9p/cache.c deleted file mode 100644 index 51c94e26a346..000000000000 --- a/trunk/fs/9p/cache.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * V9FS cache definitions. - * - * Copyright (C) 2009 by Abhishek Kulkarni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * 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: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "cache.h" - -#define CACHETAG_LEN 11 - -struct kmem_cache *vcookie_cache; - -struct fscache_netfs v9fs_cache_netfs = { - .name = "9p", - .version = 0, -}; - -static void init_once(void *foo) -{ - struct v9fs_cookie *vcookie = (struct v9fs_cookie *) foo; - vcookie->fscache = NULL; - vcookie->qid = NULL; - inode_init_once(&vcookie->inode); -} - -/** - * v9fs_init_vcookiecache - initialize a cache for vcookies to maintain - * vcookie to inode mapping - * - * Returns 0 on success. - */ - -static int v9fs_init_vcookiecache(void) -{ - vcookie_cache = kmem_cache_create("vcookie_cache", - sizeof(struct v9fs_cookie), - 0, (SLAB_RECLAIM_ACCOUNT| - SLAB_MEM_SPREAD), - init_once); - if (!vcookie_cache) - return -ENOMEM; - - return 0; -} - -/** - * v9fs_destroy_vcookiecache - destroy the cache of vcookies - * - */ - -static void v9fs_destroy_vcookiecache(void) -{ - kmem_cache_destroy(vcookie_cache); -} - -int __v9fs_cache_register(void) -{ - int ret; - ret = v9fs_init_vcookiecache(); - if (ret < 0) - return ret; - - return fscache_register_netfs(&v9fs_cache_netfs); -} - -void __v9fs_cache_unregister(void) -{ - v9fs_destroy_vcookiecache(); - fscache_unregister_netfs(&v9fs_cache_netfs); -} - -/** - * v9fs_random_cachetag - Generate a random tag to be associated - * with a new cache session. - * - * The value of jiffies is used for a fairly randomly cache tag. - */ - -static -int v9fs_random_cachetag(struct v9fs_session_info *v9ses) -{ - v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL); - if (!v9ses->cachetag) - return -ENOMEM; - - return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies); -} - -static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data, - void *buffer, uint16_t bufmax) -{ - struct v9fs_session_info *v9ses; - uint16_t klen = 0; - - v9ses = (struct v9fs_session_info *)cookie_netfs_data; - P9_DPRINTK(P9_DEBUG_FSC, "session %p buf %p size %u", v9ses, - buffer, bufmax); - - if (v9ses->cachetag) - klen = strlen(v9ses->cachetag); - - if (klen > bufmax) - return 0; - - memcpy(buffer, v9ses->cachetag, klen); - P9_DPRINTK(P9_DEBUG_FSC, "cache session tag %s", v9ses->cachetag); - return klen; -} - -const struct fscache_cookie_def v9fs_cache_session_index_def = { - .name = "9P.session", - .type = FSCACHE_COOKIE_TYPE_INDEX, - .get_key = v9fs_cache_session_get_key, -}; - -void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses) -{ - /* If no cache session tag was specified, we generate a random one. */ - if (!v9ses->cachetag) - v9fs_random_cachetag(v9ses); - - v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index, - &v9fs_cache_session_index_def, - v9ses); - P9_DPRINTK(P9_DEBUG_FSC, "session %p get cookie %p", v9ses, - v9ses->fscache); -} - -void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses) -{ - P9_DPRINTK(P9_DEBUG_FSC, "session %p put cookie %p", v9ses, - v9ses->fscache); - fscache_relinquish_cookie(v9ses->fscache, 0); - v9ses->fscache = NULL; -} - - -static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data, - void *buffer, uint16_t bufmax) -{ - const struct v9fs_cookie *vcookie = cookie_netfs_data; - memcpy(buffer, &vcookie->qid->path, sizeof(vcookie->qid->path)); - - P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &vcookie->inode, - vcookie->qid->path); - return sizeof(vcookie->qid->path); -} - -static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, - uint64_t *size) -{ - const struct v9fs_cookie *vcookie = cookie_netfs_data; - *size = i_size_read(&vcookie->inode); - - P9_DPRINTK(P9_DEBUG_FSC, "inode %p get attr %llu", &vcookie->inode, - *size); -} - -static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data, - void *buffer, uint16_t buflen) -{ - const struct v9fs_cookie *vcookie = cookie_netfs_data; - memcpy(buffer, &vcookie->qid->version, sizeof(vcookie->qid->version)); - - P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &vcookie->inode, - vcookie->qid->version); - return sizeof(vcookie->qid->version); -} - -static enum -fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data, - const void *buffer, - uint16_t buflen) -{ - const struct v9fs_cookie *vcookie = cookie_netfs_data; - - if (buflen != sizeof(vcookie->qid->version)) - return FSCACHE_CHECKAUX_OBSOLETE; - - if (memcmp(buffer, &vcookie->qid->version, - sizeof(vcookie->qid->version))) - return FSCACHE_CHECKAUX_OBSOLETE; - - return FSCACHE_CHECKAUX_OKAY; -} - -static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data) -{ - struct v9fs_cookie *vcookie = cookie_netfs_data; - struct pagevec pvec; - pgoff_t first; - int loop, nr_pages; - - pagevec_init(&pvec, 0); - first = 0; - - for (;;) { - nr_pages = pagevec_lookup(&pvec, vcookie->inode.i_mapping, - first, - PAGEVEC_SIZE - pagevec_count(&pvec)); - if (!nr_pages) - break; - - for (loop = 0; loop < nr_pages; loop++) - ClearPageFsCache(pvec.pages[loop]); - - first = pvec.pages[nr_pages - 1]->index + 1; - - pvec.nr = nr_pages; - pagevec_release(&pvec); - cond_resched(); - } -} - -const struct fscache_cookie_def v9fs_cache_inode_index_def = { - .name = "9p.inode", - .type = FSCACHE_COOKIE_TYPE_DATAFILE, - .get_key = v9fs_cache_inode_get_key, - .get_attr = v9fs_cache_inode_get_attr, - .get_aux = v9fs_cache_inode_get_aux, - .check_aux = v9fs_cache_inode_check_aux, - .now_uncached = v9fs_cache_inode_now_uncached, -}; - -void v9fs_cache_inode_get_cookie(struct inode *inode) -{ - struct v9fs_cookie *vcookie; - struct v9fs_session_info *v9ses; - - if (!S_ISREG(inode->i_mode)) - return; - - vcookie = v9fs_inode2cookie(inode); - if (vcookie->fscache) - return; - - v9ses = v9fs_inode2v9ses(inode); - vcookie->fscache = fscache_acquire_cookie(v9ses->fscache, - &v9fs_cache_inode_index_def, - vcookie); - - P9_DPRINTK(P9_DEBUG_FSC, "inode %p get cookie %p", inode, - vcookie->fscache); -} - -void v9fs_cache_inode_put_cookie(struct inode *inode) -{ - struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - - if (!vcookie->fscache) - return; - P9_DPRINTK(P9_DEBUG_FSC, "inode %p put cookie %p", inode, - vcookie->fscache); - - fscache_relinquish_cookie(vcookie->fscache, 0); - vcookie->fscache = NULL; -} - -void v9fs_cache_inode_flush_cookie(struct inode *inode) -{ - struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - - if (!vcookie->fscache) - return; - P9_DPRINTK(P9_DEBUG_FSC, "inode %p flush cookie %p", inode, - vcookie->fscache); - - fscache_relinquish_cookie(vcookie->fscache, 1); - vcookie->fscache = NULL; -} - -void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp) -{ - struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - struct p9_fid *fid; - - if (!vcookie->fscache) - return; - - spin_lock(&vcookie->lock); - fid = filp->private_data; - if ((filp->f_flags & O_ACCMODE) != O_RDONLY) - v9fs_cache_inode_flush_cookie(inode); - else - v9fs_cache_inode_get_cookie(inode); - - spin_unlock(&vcookie->lock); -} - -void v9fs_cache_inode_reset_cookie(struct inode *inode) -{ - struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - struct v9fs_session_info *v9ses; - struct fscache_cookie *old; - - if (!vcookie->fscache) - return; - - old = vcookie->fscache; - - spin_lock(&vcookie->lock); - fscache_relinquish_cookie(vcookie->fscache, 1); - - v9ses = v9fs_inode2v9ses(inode); - vcookie->fscache = fscache_acquire_cookie(v9ses->fscache, - &v9fs_cache_inode_index_def, - vcookie); - - P9_DPRINTK(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p", - inode, old, vcookie->fscache); - - spin_unlock(&vcookie->lock); -} - -int __v9fs_fscache_release_page(struct page *page, gfp_t gfp) -{ - struct inode *inode = page->mapping->host; - struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - - BUG_ON(!vcookie->fscache); - - if (PageFsCache(page)) { - if (fscache_check_page_write(vcookie->fscache, page)) { - if (!(gfp & __GFP_WAIT)) - return 0; - fscache_wait_on_page_write(vcookie->fscache, page); - } - - fscache_uncache_page(vcookie->fscache, page); - ClearPageFsCache(page); - } - - return 1; -} - -void __v9fs_fscache_invalidate_page(struct page *page) -{ - struct inode *inode = page->mapping->host; - struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - - BUG_ON(!vcookie->fscache); - - if (PageFsCache(page)) { - fscache_wait_on_page_write(vcookie->fscache, page); - BUG_ON(!PageLocked(page)); - fscache_uncache_page(vcookie->fscache, page); - ClearPageFsCache(page); - } -} - -static void v9fs_vfs_readpage_complete(struct page *page, void *data, - int error) -{ - if (!error) - SetPageUptodate(page); - - unlock_page(page); -} - -/** - * __v9fs_readpage_from_fscache - read a page from cache - * - * Returns 0 if the pages are in cache and a BIO is submitted, - * 1 if the pages are not in cache and -error otherwise. - */ - -int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page) -{ - int ret; - const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - - P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page); - if (!vcookie->fscache) - return -ENOBUFS; - - ret = fscache_read_or_alloc_page(vcookie->fscache, - page, - v9fs_vfs_readpage_complete, - NULL, - GFP_KERNEL); - switch (ret) { - case -ENOBUFS: - case -ENODATA: - P9_DPRINTK(P9_DEBUG_FSC, "page/inode not in cache %d", ret); - return 1; - case 0: - P9_DPRINTK(P9_DEBUG_FSC, "BIO submitted"); - return ret; - default: - P9_DPRINTK(P9_DEBUG_FSC, "ret %d", ret); - return ret; - } -} - -/** - * __v9fs_readpages_from_fscache - read multiple pages from cache - * - * Returns 0 if the pages are in cache and a BIO is submitted, - * 1 if the pages are not in cache and -error otherwise. - */ - -int __v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - int ret; - const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - - P9_DPRINTK(P9_DEBUG_FSC, "inode %p pages %u", inode, *nr_pages); - if (!vcookie->fscache) - return -ENOBUFS; - - ret = fscache_read_or_alloc_pages(vcookie->fscache, - mapping, pages, nr_pages, - v9fs_vfs_readpage_complete, - NULL, - mapping_gfp_mask(mapping)); - switch (ret) { - case -ENOBUFS: - case -ENODATA: - P9_DPRINTK(P9_DEBUG_FSC, "pages/inodes not in cache %d", ret); - return 1; - case 0: - BUG_ON(!list_empty(pages)); - BUG_ON(*nr_pages != 0); - P9_DPRINTK(P9_DEBUG_FSC, "BIO submitted"); - return ret; - default: - P9_DPRINTK(P9_DEBUG_FSC, "ret %d", ret); - return ret; - } -} - -/** - * __v9fs_readpage_to_fscache - write a page to the cache - * - */ - -void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page) -{ - int ret; - const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - - P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page); - ret = fscache_write_page(vcookie->fscache, page, GFP_KERNEL); - P9_DPRINTK(P9_DEBUG_FSC, "ret = %d", ret); - if (ret != 0) - v9fs_uncache_page(inode, page); -} diff --git a/trunk/fs/9p/cache.h b/trunk/fs/9p/cache.h deleted file mode 100644 index a94192bfaee8..000000000000 --- a/trunk/fs/9p/cache.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * V9FS cache definitions. - * - * Copyright (C) 2009 by Abhishek Kulkarni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * 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: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#ifndef _9P_CACHE_H -#ifdef CONFIG_9P_FSCACHE -#include -#include - -extern struct kmem_cache *vcookie_cache; - -struct v9fs_cookie { - spinlock_t lock; - struct inode inode; - struct fscache_cookie *fscache; - struct p9_qid *qid; -}; - -static inline struct v9fs_cookie *v9fs_inode2cookie(const struct inode *inode) -{ - return container_of(inode, struct v9fs_cookie, inode); -} - -extern struct fscache_netfs v9fs_cache_netfs; -extern const struct fscache_cookie_def v9fs_cache_session_index_def; -extern const struct fscache_cookie_def v9fs_cache_inode_index_def; - -extern void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses); -extern void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses); - -extern void v9fs_cache_inode_get_cookie(struct inode *inode); -extern void v9fs_cache_inode_put_cookie(struct inode *inode); -extern void v9fs_cache_inode_flush_cookie(struct inode *inode); -extern void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp); -extern void v9fs_cache_inode_reset_cookie(struct inode *inode); - -extern int __v9fs_cache_register(void); -extern void __v9fs_cache_unregister(void); - -extern int __v9fs_fscache_release_page(struct page *page, gfp_t gfp); -extern void __v9fs_fscache_invalidate_page(struct page *page); -extern int __v9fs_readpage_from_fscache(struct inode *inode, - struct page *page); -extern int __v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages); -extern void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page); - - -/** - * v9fs_cache_register - Register v9fs file system with the cache - */ -static inline int v9fs_cache_register(void) -{ - return __v9fs_cache_register(); -} - -/** - * v9fs_cache_unregister - Unregister v9fs from the cache - */ -static inline void v9fs_cache_unregister(void) -{ - __v9fs_cache_unregister(); -} - -static inline int v9fs_fscache_release_page(struct page *page, - gfp_t gfp) -{ - return __v9fs_fscache_release_page(page, gfp); -} - -static inline void v9fs_fscache_invalidate_page(struct page *page) -{ - __v9fs_fscache_invalidate_page(page); -} - -static inline int v9fs_readpage_from_fscache(struct inode *inode, - struct page *page) -{ - return __v9fs_readpage_from_fscache(inode, page); -} - -static inline int v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - return __v9fs_readpages_from_fscache(inode, mapping, pages, - nr_pages); -} - -static inline void v9fs_readpage_to_fscache(struct inode *inode, - struct page *page) -{ - if (PageFsCache(page)) - __v9fs_readpage_to_fscache(inode, page); -} - -static inline void v9fs_uncache_page(struct inode *inode, struct page *page) -{ - struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - fscache_uncache_page(vcookie->fscache, page); - BUG_ON(PageFsCache(page)); -} - -static inline void v9fs_vcookie_set_qid(struct inode *inode, - struct p9_qid *qid) -{ - struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); - spin_lock(&vcookie->lock); - vcookie->qid = qid; - spin_unlock(&vcookie->lock); -} - -#else /* CONFIG_9P_FSCACHE */ - -static inline int v9fs_cache_register(void) -{ - return 1; -} - -static inline void v9fs_cache_unregister(void) {} - -static inline int v9fs_fscache_release_page(struct page *page, - gfp_t gfp) { - return 1; -} - -static inline void v9fs_fscache_invalidate_page(struct page *page) {} - -static inline int v9fs_readpage_from_fscache(struct inode *inode, - struct page *page) -{ - return -ENOBUFS; -} - -static inline int v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - return -ENOBUFS; -} - -static inline void v9fs_readpage_to_fscache(struct inode *inode, - struct page *page) -{} - -static inline void v9fs_uncache_page(struct inode *inode, struct page *page) -{} - -static inline void v9fs_vcookie_set_qid(struct inode *inode, - struct p9_qid *qid) -{} - -#endif /* CONFIG_9P_FSCACHE */ -#endif /* _9P_CACHE_H */ diff --git a/trunk/fs/9p/v9fs.c b/trunk/fs/9p/v9fs.c index cf62b05e296a..f7003cfac63d 100644 --- a/trunk/fs/9p/v9fs.c +++ b/trunk/fs/9p/v9fs.c @@ -34,25 +34,21 @@ #include #include "v9fs.h" #include "v9fs_vfs.h" -#include "cache.h" - -static DEFINE_SPINLOCK(v9fs_sessionlist_lock); -static LIST_HEAD(v9fs_sessionlist); /* - * Option Parsing (code inspired by NFS code) - * NOTE: each transport will parse its own options - */ + * Option Parsing (code inspired by NFS code) + * NOTE: each transport will parse its own options + */ enum { /* Options that take integer arguments */ Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid, /* String options */ - Opt_uname, Opt_remotename, Opt_trans, Opt_cache, Opt_cachetag, + Opt_uname, Opt_remotename, Opt_trans, /* Options that take no arguments */ Opt_nodevmap, /* Cache options */ - Opt_cache_loose, Opt_fscache, + Opt_cache_loose, /* Access options */ Opt_access, /* Error token */ @@ -67,10 +63,8 @@ static const match_table_t tokens = { {Opt_uname, "uname=%s"}, {Opt_remotename, "aname=%s"}, {Opt_nodevmap, "nodevmap"}, - {Opt_cache, "cache=%s"}, + {Opt_cache_loose, "cache=loose"}, {Opt_cache_loose, "loose"}, - {Opt_fscache, "fscache"}, - {Opt_cachetag, "cachetag=%s"}, {Opt_access, "access=%s"}, {Opt_err, NULL} }; @@ -95,16 +89,16 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) v9ses->afid = ~0; v9ses->debug = 0; v9ses->cache = 0; -#ifdef CONFIG_9P_FSCACHE - v9ses->cachetag = NULL; -#endif if (!opts) return 0; options = kstrdup(opts, GFP_KERNEL); - if (!options) - goto fail_option_alloc; + if (!options) { + P9_DPRINTK(P9_DEBUG_ERROR, + "failed to allocate copy of option string\n"); + return -ENOMEM; + } while ((p = strsep(&options, ",")) != NULL) { int token; @@ -149,33 +143,16 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) case Opt_cache_loose: v9ses->cache = CACHE_LOOSE; break; - case Opt_fscache: - v9ses->cache = CACHE_FSCACHE; - break; - case Opt_cachetag: -#ifdef CONFIG_9P_FSCACHE - v9ses->cachetag = match_strdup(&args[0]); -#endif - break; - case Opt_cache: - s = match_strdup(&args[0]); - if (!s) - goto fail_option_alloc; - - if (strcmp(s, "loose") == 0) - v9ses->cache = CACHE_LOOSE; - else if (strcmp(s, "fscache") == 0) - v9ses->cache = CACHE_FSCACHE; - else - v9ses->cache = CACHE_NONE; - kfree(s); - break; case Opt_access: s = match_strdup(&args[0]); - if (!s) - goto fail_option_alloc; - + if (!s) { + P9_DPRINTK(P9_DEBUG_ERROR, + "failed to allocate copy" + " of option argument\n"); + ret = -ENOMEM; + break; + } v9ses->flags &= ~V9FS_ACCESS_MASK; if (strcmp(s, "user") == 0) v9ses->flags |= V9FS_ACCESS_USER; @@ -196,11 +173,6 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) } kfree(options); return ret; - -fail_option_alloc: - P9_DPRINTK(P9_DEBUG_ERROR, - "failed to allocate copy of option argument\n"); - return -ENOMEM; } /** @@ -228,10 +200,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, return ERR_PTR(-ENOMEM); } - spin_lock(&v9fs_sessionlist_lock); - list_add(&v9ses->slist, &v9fs_sessionlist); - spin_unlock(&v9fs_sessionlist_lock); - v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER; strcpy(v9ses->uname, V9FS_DEFUSER); strcpy(v9ses->aname, V9FS_DEFANAME); @@ -281,11 +249,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, else fid->uid = ~0; -#ifdef CONFIG_9P_FSCACHE - /* register the session for caching */ - v9fs_cache_session_get_cookie(v9ses); -#endif - return fid; error: @@ -305,18 +268,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) v9ses->clnt = NULL; } -#ifdef CONFIG_9P_FSCACHE - if (v9ses->fscache) { - v9fs_cache_session_put_cookie(v9ses); - kfree(v9ses->cachetag); - } -#endif __putname(v9ses->uname); __putname(v9ses->aname); - - spin_lock(&v9fs_sessionlist_lock); - list_del(&v9ses->slist); - spin_unlock(&v9fs_sessionlist_lock); } /** @@ -333,132 +286,25 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses) { extern int v9fs_error_init(void); -static struct kobject *v9fs_kobj; - -#ifdef CONFIG_9P_FSCACHE /** - * caches_show - list caches associated with a session - * - * Returns the size of buffer written. - */ - -static ssize_t caches_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - ssize_t n = 0, count = 0, limit = PAGE_SIZE; - struct v9fs_session_info *v9ses; - - spin_lock(&v9fs_sessionlist_lock); - list_for_each_entry(v9ses, &v9fs_sessionlist, slist) { - if (v9ses->cachetag) { - n = snprintf(buf, limit, "%s\n", v9ses->cachetag); - if (n < 0) { - count = n; - break; - } - - count += n; - limit -= n; - } - } - - spin_unlock(&v9fs_sessionlist_lock); - return count; -} - -static struct kobj_attribute v9fs_attr_cache = __ATTR_RO(caches); -#endif /* CONFIG_9P_FSCACHE */ - -static struct attribute *v9fs_attrs[] = { -#ifdef CONFIG_9P_FSCACHE - &v9fs_attr_cache.attr, -#endif - NULL, -}; - -static struct attribute_group v9fs_attr_group = { - .attrs = v9fs_attrs, -}; - -/** - * v9fs_sysfs_init - Initialize the v9fs sysfs interface - * - */ - -static int v9fs_sysfs_init(void) -{ - v9fs_kobj = kobject_create_and_add("9p", fs_kobj); - if (!v9fs_kobj) - return -ENOMEM; - - if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) { - kobject_put(v9fs_kobj); - return -ENOMEM; - } - - return 0; -} - -/** - * v9fs_sysfs_cleanup - Unregister the v9fs sysfs interface - * - */ - -static void v9fs_sysfs_cleanup(void) -{ - sysfs_remove_group(v9fs_kobj, &v9fs_attr_group); - kobject_put(v9fs_kobj); -} - -/** - * init_v9fs - Initialize module + * v9fs_init - Initialize module * */ static int __init init_v9fs(void) { - int err; printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); /* TODO: Setup list of registered trasnport modules */ - err = register_filesystem(&v9fs_fs_type); - if (err < 0) { - printk(KERN_ERR "Failed to register filesystem\n"); - return err; - } - - err = v9fs_cache_register(); - if (err < 0) { - printk(KERN_ERR "Failed to register v9fs for caching\n"); - goto out_fs_unreg; - } - - err = v9fs_sysfs_init(); - if (err < 0) { - printk(KERN_ERR "Failed to register with sysfs\n"); - goto out_sysfs_cleanup; - } - - return 0; - -out_sysfs_cleanup: - v9fs_sysfs_cleanup(); - -out_fs_unreg: - unregister_filesystem(&v9fs_fs_type); - - return err; + return register_filesystem(&v9fs_fs_type); } /** - * exit_v9fs - shutdown module + * v9fs_init - shutdown module * */ static void __exit exit_v9fs(void) { - v9fs_sysfs_cleanup(); - v9fs_cache_unregister(); unregister_filesystem(&v9fs_fs_type); } diff --git a/trunk/fs/9p/v9fs.h b/trunk/fs/9p/v9fs.h index 019f4ccb70c1..38762bf102a9 100644 --- a/trunk/fs/9p/v9fs.h +++ b/trunk/fs/9p/v9fs.h @@ -51,7 +51,6 @@ enum p9_session_flags { enum p9_cache_modes { CACHE_NONE, CACHE_LOOSE, - CACHE_FSCACHE, }; /** @@ -61,8 +60,6 @@ enum p9_cache_modes { * @debug: debug level * @afid: authentication handle * @cache: cache mode of type &p9_cache_modes - * @cachetag: the tag of the cache associated with this session - * @fscache: session cookie associated with FS-Cache * @options: copy of options string given by user * @uname: string user name to mount hierarchy as * @aname: mount specifier for remote hierarchy @@ -71,7 +68,7 @@ enum p9_cache_modes { * @dfltgid: default numeric groupid to mount hierarchy as * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy * @clnt: reference to 9P network client instantiated for this session - * @slist: reference to list of registered 9p sessions + * @debugfs_dir: reference to debugfs_dir which can be used for add'l debug * * This structure holds state for each session instance established during * a sys_mount() . @@ -87,10 +84,6 @@ struct v9fs_session_info { unsigned short debug; unsigned int afid; unsigned int cache; -#ifdef CONFIG_9P_FSCACHE - char *cachetag; - struct fscache_cookie *fscache; -#endif char *uname; /* user name to mount as */ char *aname; /* name of remote hierarchy being mounted */ @@ -99,9 +92,11 @@ struct v9fs_session_info { unsigned int dfltgid; /* default gid for legacy support */ u32 uid; /* if ACCESS_SINGLE, the uid that has access */ struct p9_client *clnt; /* 9p client */ - struct list_head slist; /* list of sessions registered with v9fs */ + struct dentry *debugfs_dir; }; +extern struct dentry *v9fs_debugfs_root; + struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, char *); void v9fs_session_close(struct v9fs_session_info *v9ses); diff --git a/trunk/fs/9p/v9fs_vfs.h b/trunk/fs/9p/v9fs_vfs.h index 3a7560e35865..f0c7de78e205 100644 --- a/trunk/fs/9p/v9fs_vfs.h +++ b/trunk/fs/9p/v9fs_vfs.h @@ -44,13 +44,7 @@ extern const struct file_operations v9fs_dir_operations; extern const struct dentry_operations v9fs_dentry_operations; extern const struct dentry_operations v9fs_cached_dentry_operations; -#ifdef CONFIG_9P_FSCACHE -struct inode *v9fs_alloc_inode(struct super_block *sb); -void v9fs_destroy_inode(struct inode *inode); -#endif - struct inode *v9fs_get_inode(struct super_block *sb, int mode); -void v9fs_clear_inode(struct inode *inode); ino_t v9fs_qid2ino(struct p9_qid *qid); void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); int v9fs_dir_release(struct inode *inode, struct file *filp); diff --git a/trunk/fs/9p/vfs_addr.c b/trunk/fs/9p/vfs_addr.c index 90e38449f4b3..92828281a30b 100644 --- a/trunk/fs/9p/vfs_addr.c +++ b/trunk/fs/9p/vfs_addr.c @@ -38,7 +38,6 @@ #include "v9fs.h" #include "v9fs_vfs.h" -#include "cache.h" /** * v9fs_vfs_readpage - read an entire page in from 9P @@ -53,31 +52,18 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page) int retval; loff_t offset; char *buffer; - struct inode *inode; - inode = page->mapping->host; P9_DPRINTK(P9_DEBUG_VFS, "\n"); - - BUG_ON(!PageLocked(page)); - - retval = v9fs_readpage_from_fscache(inode, page); - if (retval == 0) - return retval; - buffer = kmap(page); offset = page_offset(page); retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset); - if (retval < 0) { - v9fs_uncache_page(inode, page); + if (retval < 0) goto done; - } memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); flush_dcache_page(page); SetPageUptodate(page); - - v9fs_readpage_to_fscache(inode, page); retval = 0; done: @@ -86,78 +72,6 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page) return retval; } -/** - * v9fs_vfs_readpages - read a set of pages from 9P - * - * @filp: file being read - * @mapping: the address space - * @pages: list of pages to read - * @nr_pages: count of pages to read - * - */ - -static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping, - struct list_head *pages, unsigned nr_pages) -{ - int ret = 0; - struct inode *inode; - - inode = mapping->host; - P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, filp); - - ret = v9fs_readpages_from_fscache(inode, mapping, pages, &nr_pages); - if (ret == 0) - return ret; - - ret = read_cache_pages(mapping, pages, (void *)v9fs_vfs_readpage, filp); - P9_DPRINTK(P9_DEBUG_VFS, " = %d\n", ret); - return ret; -} - -/** - * v9fs_release_page - release the private state associated with a page - * - * Returns 1 if the page can be released, false otherwise. - */ - -static int v9fs_release_page(struct page *page, gfp_t gfp) -{ - if (PagePrivate(page)) - return 0; - - return v9fs_fscache_release_page(page, gfp); -} - -/** - * v9fs_invalidate_page - Invalidate a page completely or partially - * - * @page: structure to page - * @offset: offset in the page - */ - -static void v9fs_invalidate_page(struct page *page, unsigned long offset) -{ - if (offset == 0) - v9fs_fscache_invalidate_page(page); -} - -/** - * v9fs_launder_page - Writeback a dirty page - * Since the writes go directly to the server, we simply return a 0 - * here to indicate success. - * - * Returns 0 on success. - */ - -static int v9fs_launder_page(struct page *page) -{ - return 0; -} - const struct address_space_operations v9fs_addr_operations = { .readpage = v9fs_vfs_readpage, - .readpages = v9fs_vfs_readpages, - .releasepage = v9fs_release_page, - .invalidatepage = v9fs_invalidate_page, - .launder_page = v9fs_launder_page, }; diff --git a/trunk/fs/9p/vfs_file.c b/trunk/fs/9p/vfs_file.c index 3902bf43a088..68bf2af6c389 100644 --- a/trunk/fs/9p/vfs_file.c +++ b/trunk/fs/9p/vfs_file.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -41,7 +40,6 @@ #include "v9fs.h" #include "v9fs_vfs.h" #include "fid.h" -#include "cache.h" static const struct file_operations v9fs_cached_file_operations; @@ -74,7 +72,7 @@ int v9fs_file_open(struct inode *inode, struct file *file) return err; } if (omode & P9_OTRUNC) { - i_size_write(inode, 0); + inode->i_size = 0; inode->i_blocks = 0; } if ((file->f_flags & O_APPEND) && (!v9fs_extended(v9ses))) @@ -87,10 +85,6 @@ int v9fs_file_open(struct inode *inode, struct file *file) /* enable cached file options */ if(file->f_op == &v9fs_file_operations) file->f_op = &v9fs_cached_file_operations; - -#ifdef CONFIG_9P_FSCACHE - v9fs_cache_inode_set_cookie(inode, file); -#endif } return 0; @@ -216,7 +210,6 @@ v9fs_file_write(struct file *filp, const char __user * data, struct p9_client *clnt; struct inode *inode = filp->f_path.dentry->d_inode; int origin = *offset; - unsigned long pg_start, pg_end; P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, (int)*offset); @@ -232,7 +225,7 @@ v9fs_file_write(struct file *filp, const char __user * data, if (count < rsize) rsize = count; - n = p9_client_write(fid, NULL, data+total, origin+total, + n = p9_client_write(fid, NULL, data+total, *offset+total, rsize); if (n <= 0) break; @@ -241,14 +234,14 @@ v9fs_file_write(struct file *filp, const char __user * data, } while (count > 0); if (total > 0) { - pg_start = origin >> PAGE_CACHE_SHIFT; - pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; - if (inode->i_mapping && inode->i_mapping->nrpages) - invalidate_inode_pages2_range(inode->i_mapping, - pg_start, pg_end); + invalidate_inode_pages2_range(inode->i_mapping, origin, + origin+total); *offset += total; - i_size_write(inode, i_size_read(inode) + total); - inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; + } + + if (*offset > inode->i_size) { + inode->i_size = *offset; + inode->i_blocks = (inode->i_size + 512 - 1) >> 9; } if (n < 0) diff --git a/trunk/fs/9p/vfs_inode.c b/trunk/fs/9p/vfs_inode.c index 5947628aefef..06a223d50a81 100644 --- a/trunk/fs/9p/vfs_inode.c +++ b/trunk/fs/9p/vfs_inode.c @@ -40,7 +40,6 @@ #include "v9fs.h" #include "v9fs_vfs.h" #include "fid.h" -#include "cache.h" static const struct inode_operations v9fs_dir_inode_operations; static const struct inode_operations v9fs_dir_inode_operations_ext; @@ -198,39 +197,6 @@ v9fs_blank_wstat(struct p9_wstat *wstat) wstat->extension = NULL; } -#ifdef CONFIG_9P_FSCACHE -/** - * v9fs_alloc_inode - helper function to allocate an inode - * This callback is executed before setting up the inode so that we - * can associate a vcookie with each inode. - * - */ - -struct inode *v9fs_alloc_inode(struct super_block *sb) -{ - struct v9fs_cookie *vcookie; - vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache, - GFP_KERNEL); - if (!vcookie) - return NULL; - - vcookie->fscache = NULL; - vcookie->qid = NULL; - spin_lock_init(&vcookie->lock); - return &vcookie->inode; -} - -/** - * v9fs_destroy_inode - destroy an inode - * - */ - -void v9fs_destroy_inode(struct inode *inode) -{ - kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode)); -} -#endif - /** * v9fs_get_inode - helper function to setup an inode * @sb: superblock @@ -360,21 +326,6 @@ v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) } */ - -/** - * v9fs_clear_inode - release an inode - * @inode: inode to release - * - */ -void v9fs_clear_inode(struct inode *inode) -{ - filemap_fdatawrite(inode->i_mapping); - -#ifdef CONFIG_9P_FSCACHE - v9fs_cache_inode_put_cookie(inode); -#endif -} - /** * v9fs_inode_from_fid - populate an inode by issuing a attribute request * @v9ses: session information @@ -405,14 +356,8 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, v9fs_stat2inode(st, ret, sb); ret->i_ino = v9fs_qid2ino(&st->qid); - -#ifdef CONFIG_9P_FSCACHE - v9fs_vcookie_set_qid(ret, &st->qid); - v9fs_cache_inode_get_cookie(ret); -#endif p9stat_free(st); kfree(st); - return ret; error: @@ -806,7 +751,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); err = -EPERM; v9ses = v9fs_inode2v9ses(dentry->d_inode); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) + if (v9ses->cache == CACHE_LOOSE) return simple_getattr(mnt, dentry, stat); fid = v9fs_fid_lookup(dentry); @@ -927,10 +872,10 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, } else inode->i_rdev = 0; - i_size_write(inode, stat->length); + inode->i_size = stat->length; /* not real number of blocks, but 512 byte ones ... */ - inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; + inode->i_blocks = (inode->i_size + 512 - 1) >> 9; } /** diff --git a/trunk/fs/9p/vfs_super.c b/trunk/fs/9p/vfs_super.c index 14a86448572c..8961f1a8f668 100644 --- a/trunk/fs/9p/vfs_super.c +++ b/trunk/fs/9p/vfs_super.c @@ -44,8 +44,20 @@ #include "v9fs_vfs.h" #include "fid.h" +static void v9fs_clear_inode(struct inode *); static const struct super_operations v9fs_super_ops; +/** + * v9fs_clear_inode - release an inode + * @inode: inode to release + * + */ + +static void v9fs_clear_inode(struct inode *inode) +{ + filemap_fdatawrite(inode->i_mapping); +} + /** * v9fs_set_super - set the superblock * @s: super block @@ -208,10 +220,6 @@ v9fs_umount_begin(struct super_block *sb) } static const struct super_operations v9fs_super_ops = { -#ifdef CONFIG_9P_FSCACHE - .alloc_inode = v9fs_alloc_inode, - .destroy_inode = v9fs_destroy_inode, -#endif .statfs = simple_statfs, .clear_inode = v9fs_clear_inode, .show_options = generic_show_options, diff --git a/trunk/fs/nfs/client.c b/trunk/fs/nfs/client.c index 152025358dad..73ddefba7aa3 100644 --- a/trunk/fs/nfs/client.c +++ b/trunk/fs/nfs/client.c @@ -648,8 +648,6 @@ static int nfs_start_lockd(struct nfs_server *server) .hostname = clp->cl_hostname, .address = (struct sockaddr *)&clp->cl_addr, .addrlen = clp->cl_addrlen, - .protocol = server->flags & NFS_MOUNT_TCP ? - IPPROTO_TCP : IPPROTO_UDP, .nfs_version = clp->rpc_ops->version, .noresvport = server->flags & NFS_MOUNT_NORESVPORT ? 1 : 0, @@ -660,6 +658,14 @@ static int nfs_start_lockd(struct nfs_server *server) if (server->flags & NFS_MOUNT_NONLM) return 0; + switch (clp->cl_proto) { + default: + nlm_init.protocol = IPPROTO_TCP; + break; + case XPRT_TRANSPORT_UDP: + nlm_init.protocol = IPPROTO_UDP; + } + host = nlmclnt_init(&nlm_init); if (IS_ERR(host)) return PTR_ERR(host); @@ -787,7 +793,7 @@ static int nfs_init_server(struct nfs_server *server, dprintk("--> nfs_init_server()\n"); #ifdef CONFIG_NFS_V3 - if (data->flags & NFS_MOUNT_VER3) + if (data->version == 3) cl_init.rpc_ops = &nfs_v3_clientops; #endif diff --git a/trunk/fs/nfs/super.c b/trunk/fs/nfs/super.c index f1cc0587cfef..ca278b3ff64f 100644 --- a/trunk/fs/nfs/super.c +++ b/trunk/fs/nfs/super.c @@ -1430,10 +1430,13 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, int status; if (args->mount_server.version == 0) { - if (args->flags & NFS_MOUNT_VER3) - args->mount_server.version = NFS_MNT3_VERSION; - else - args->mount_server.version = NFS_MNT_VERSION; + switch (args->version) { + default: + args->mount_server.version = NFS_MNT3_VERSION; + break; + case 2: + args->mount_server.version = NFS_MNT_VERSION; + } } request.version = args->mount_server.version; @@ -1778,7 +1781,7 @@ static int nfs_validate_mount_data(void *options, } #ifndef CONFIG_NFS_V3 - if (args->flags & NFS_MOUNT_VER3) + if (args->version == 3) goto out_v3_not_compiled; #endif /* !CONFIG_NFS_V3 */ @@ -1936,7 +1939,7 @@ static void nfs_fill_super(struct super_block *sb, if (data->bsize) sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); - if (server->flags & NFS_MOUNT_VER3) { + if (server->nfs_client->rpc_ops->version == 3) { /* The VFS shouldn't apply the umask to mode bits. We will do * so ourselves when necessary. */ @@ -1960,7 +1963,7 @@ static void nfs_clone_super(struct super_block *sb, sb->s_blocksize = old_sb->s_blocksize; sb->s_maxbytes = old_sb->s_maxbytes; - if (server->flags & NFS_MOUNT_VER3) { + if (server->nfs_client->rpc_ops->version == 3) { /* The VFS shouldn't apply the umask to mode bits. We will do * so ourselves when necessary. */ diff --git a/trunk/include/linux/cred.h b/trunk/include/linux/cred.h index 4e3387a89cb9..fb371601a3b4 100644 --- a/trunk/include/linux/cred.h +++ b/trunk/include/linux/cred.h @@ -176,7 +176,23 @@ extern void __invalid_creds(const struct cred *, const char *, unsigned); extern void __validate_process_creds(struct task_struct *, const char *, unsigned); -extern bool creds_are_invalid(const struct cred *cred); +static inline bool creds_are_invalid(const struct cred *cred) +{ + if (cred->magic != CRED_MAGIC) + return true; + if (atomic_read(&cred->usage) < atomic_read(&cred->subscribers)) + return true; +#ifdef CONFIG_SECURITY_SELINUX + if (selinux_is_enabled()) { + if ((unsigned long) cred->security < PAGE_SIZE) + return true; + if ((*(u32 *)cred->security & 0xffffff00) == + (POISON_FREE << 24 | POISON_FREE << 16 | POISON_FREE << 8)) + return true; + } +#endif + return false; +} static inline void __validate_creds(const struct cred *cred, const char *file, unsigned line) diff --git a/trunk/include/linux/serial_core.h b/trunk/include/linux/serial_core.h index fe661afe0713..d58e460844dd 100644 --- a/trunk/include/linux/serial_core.h +++ b/trunk/include/linux/serial_core.h @@ -477,7 +477,7 @@ static inline int uart_handle_break(struct uart_port *port) /** * uart_handle_dcd_change - handle a change of carrier detect state - * @uport: uart_port structure for the open port + * @port: uart_port structure for the open port * @status: new carrier detect status, nonzero if active */ static inline void @@ -503,7 +503,7 @@ uart_handle_dcd_change(struct uart_port *uport, unsigned int status) /** * uart_handle_cts_change - handle a change of clear-to-send state - * @uport: uart_port structure for the open port + * @port: uart_port structure for the open port * @status: new clear to send status, nonzero if active */ static inline void diff --git a/trunk/include/net/9p/9p.h b/trunk/include/net/9p/9p.h index a7fb54808a23..b77c1478c99f 100644 --- a/trunk/include/net/9p/9p.h +++ b/trunk/include/net/9p/9p.h @@ -38,8 +38,6 @@ * @P9_DEBUG_SLABS: memory management tracing * @P9_DEBUG_FCALL: verbose dump of protocol messages * @P9_DEBUG_FID: fid allocation/deallocation tracking - * @P9_DEBUG_PKT: packet marshalling/unmarshalling - * @P9_DEBUG_FSC: FS-cache tracing * * These flags are passed at mount time to turn on various levels of * verbosity and tracing which will be output to the system logs. @@ -56,7 +54,6 @@ enum p9_debug_flags { P9_DEBUG_FCALL = (1<<8), P9_DEBUG_FID = (1<<9), P9_DEBUG_PKT = (1<<10), - P9_DEBUG_FSC = (1<<11), }; #ifdef CONFIG_NET_9P_DEBUG diff --git a/trunk/kernel/cred.c b/trunk/kernel/cred.c index dd76cfe5f5b0..d7f7a01082eb 100644 --- a/trunk/kernel/cred.c +++ b/trunk/kernel/cred.c @@ -782,25 +782,6 @@ EXPORT_SYMBOL(set_create_files_as); #ifdef CONFIG_DEBUG_CREDENTIALS -bool creds_are_invalid(const struct cred *cred) -{ - if (cred->magic != CRED_MAGIC) - return true; - if (atomic_read(&cred->usage) < atomic_read(&cred->subscribers)) - return true; -#ifdef CONFIG_SECURITY_SELINUX - if (selinux_is_enabled()) { - if ((unsigned long) cred->security < PAGE_SIZE) - return true; - if ((*(u32 *)cred->security & 0xffffff00) == - (POISON_FREE << 24 | POISON_FREE << 16 | POISON_FREE << 8)) - return true; - } -#endif - return false; -} -EXPORT_SYMBOL(creds_are_invalid); - /* * dump invalid credentials */ diff --git a/trunk/security/keys/gc.c b/trunk/security/keys/gc.c index 4770be375ffe..485fc6233c38 100644 --- a/trunk/security/keys/gc.c +++ b/trunk/security/keys/gc.c @@ -169,9 +169,9 @@ static void key_garbage_collector(struct work_struct *work) /* trawl through the keys looking for keyrings */ for (;;) { - if (key->expiry > limit && key->expiry < new_timer) { + if (key->expiry > now && key->expiry < new_timer) { kdebug("will expire %x in %ld", - key_serial(key), key->expiry - limit); + key_serial(key), key->expiry - now); new_timer = key->expiry; } diff --git a/trunk/security/selinux/avc.c b/trunk/security/selinux/avc.c index b4b5da1c0a42..1ed0f076aadc 100644 --- a/trunk/security/selinux/avc.c +++ b/trunk/security/selinux/avc.c @@ -868,19 +868,8 @@ u32 avc_policy_seqno(void) void avc_disable(void) { - /* - * If you are looking at this because you have realized that we are - * not destroying the avc_node_cachep it might be easy to fix, but - * I don't know the memory barrier semantics well enough to know. It's - * possible that some other task dereferenced security_ops when - * it still pointed to selinux operations. If that is the case it's - * possible that it is about to use the avc and is about to need the - * avc_node_cachep. I know I could wrap the security.c security_ops call - * in an rcu_lock, but seriously, it's not worth it. Instead I just flush - * the cache and get that memory back. - */ - if (avc_node_cachep) { - avc_flush(); - /* kmem_cache_destroy(avc_node_cachep); */ - } + avc_flush(); + synchronize_rcu(); + if (avc_node_cachep) + kmem_cache_destroy(avc_node_cachep); }