* 'release' of master.kernel.org:/home/ftp/pub/scm/linux/kernel/git/aegl/linux-2.6:
[IA64] Move sg_dma_{len,address} from pci.h to scatterlist.h
lines associated with 'mm'.
This interface is used to handle whole address space
- page table operations such as what happens during
- fork, exit, and exec.
+ page table operations such as what happens during exit and exec.
+
+2) void flush_cache_dup_mm(struct mm_struct *mm)
+
+ This interface flushes an entire user address space from
+ the caches. That is, after running, there will be no cache
+ lines associated with 'mm'.
+
+ This interface is used to handle whole address space
+ page table operations such as what happens during fork.
+
+ This option is separate from flush_cache_mm to allow some
+ optimizations for VIPT caches.
-2) void flush_cache_range(struct vm_area_struct *vma,
+3) void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
Here we are flushing a specific range of (user) virtual
call flush_cache_page (see below) for each entry which may be
modified.
-3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
+4) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
This time we need to remove a PAGE_SIZE sized range
from the cache. The 'vma' is the backing structure used by
This is used primarily during fault processing.
-4) void flush_cache_kmaps(void)
+5) void flush_cache_kmaps(void)
This routine need only be implemented if the platform utilizes
highmem. It will be called right before all of the kmaps
This routing should be implemented in asm/highmem.h
-5) void flush_cache_vmap(unsigned long start, unsigned long end)
+6) void flush_cache_vmap(unsigned long start, unsigned long end)
void flush_cache_vunmap(unsigned long start, unsigned long end)
Here in these two interfaces we are flushing a specific range
---------------------------
-What: I2C interface of the it87 driver
-When: January 2007
-Why: The ISA interface is faster and should be always available. The I2C
- probing is also known to cause trouble in at least one case (see
- bug #5889.)
-Who: Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
What: Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
(temporary transition config option provided until then)
The transition config option will also be removed at the same time.
If you have any patches, questions or suggestions regarding this BFS
implementation please contact the author:
-Tigran A. Aivazian <tigran@veritas.com>
+Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
Prefix: 'f71805f'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Provided by Fintek on request
+ * Fintek F71872F/FG
+ Prefix: 'f71872f'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheet: Provided by Fintek on request
Author: Jean Delvare <khali@linux-fr.org>
test system (custom Jetway K8M8MS motherboard, with CPU and RAM) and
for providing initial documentation.
-Thanks to Kris Chen from Fintek for answering technical questions and
-providing additional documentation.
+Thanks to Kris Chen and Aaron Huang from Fintek for answering technical
+questions and providing additional documentation.
Thanks to Chris Lin from Jetway for providing wiring schematics and
answering technical questions.
source), 3 fans and 3 temperature sensors.
This chip also has fan controlling features, using either DC or PWM, in
-three different modes (one manual, two automatic). The driver doesn't
-support these features yet.
+three different modes (one manual, two automatic).
+
+The Fintek F71872F/FG Super I/O chip is almost the same, with two
+additional internal voltages monitored (VSB and battery). It also features
+6 VID inputs. The VID inputs are not yet supported by this driver.
The driver assumes that no more than one chip is present, which seems
reasonable.
range is thus from 0 to 2.040 V. Voltage values outside of this range
need external resistors. An exception is in0, which is used to monitor
the chip's own power source (+3.3V), and is divided internally by a
-factor 2.
+factor 2. For the F71872F/FG, in9 (VSB) and in10 (battery) are also
+divided internally by a factor 2.
The two LSB of the voltage limit registers are not used (always 0), so
you can only set the limits in steps of 32 mV (before scaling).
in6 VIN6 VCC1.5V 10K - 1.00 1.50 V
in7 VIN7 VCORE 10K - 1.00 ~1.40 V (1)
in8 VIN8 VSB5V 200K 47K 1.00 0.95 V
+in10 VSB VSB3.3V int. int. 2.00 1.65 V (3)
+in9 VBAT VBATTERY int. int. 2.00 1.50 V (3)
(1) Depends on your hardware setup.
(2) Obviously not correct, swapping R1 and R2 would make more sense.
+(3) F71872F/FG only.
These values can be used as hints at best, as motherboard manufacturers
are free to use a completely different setup. As a matter of fact, the
or a thermistor. The driver reports the currently selected mode, but
doesn't allow changing it. In theory, the BIOS should have configured
everything properly.
+
+
+Fan Control
+-----------
+
+Both PWM (pulse-width modulation) and DC fan speed control methods are
+supported. The right one to use depends on external circuitry on the
+motherboard, so the driver assumes that the BIOS set the method
+properly. The driver will report the method, but won't let you change
+it.
+
+When the PWM method is used, you can select the operating frequency,
+from 187.5 kHz (default) to 31 Hz. The best frequency depends on the
+fan model. As a rule of thumb, lower frequencies seem to give better
+control, but may generate annoying high-pitch noise. Fintek recommends
+not going below 1 kHz, as the fan tachometers get confused by lower
+frequencies as well.
+
+When the DC method is used, Fintek recommends not going below 5 V, which
+corresponds to a pwm value of 106 for the driver. The driver doesn't
+enforce this limit though.
+
+Three different fan control modes are supported:
+
+* Manual mode
+ You ask for a specific PWM duty cycle or DC voltage.
+
+* Fan speed mode
+ You ask for a specific fan speed. This mode assumes that pwm1
+ corresponds to fan1, pwm2 to fan2 and pwm3 to fan3.
+
+* Temperature mode
+ You define 3 temperature/fan speed trip points, and the fan speed is
+ adjusted depending on the measured temperature, using interpolation.
+ This mode is not yet supported by the driver.
http://www.ite.com.tw/
* IT8712F
Prefix: 'it8712'
- Addresses scanned: I2C 0x2d
- from Super I/O config space (8 I/O ports)
+ Addresses scanned: from Super I/O config space (8 I/O ports)
Datasheet: Publicly available at the ITE website
http://www.ite.com.tw/
* IT8716F
misconfigured by BIOS - PWM values would be inverted. This option tries
to fix this. Please contact your BIOS manufacturer and ask him for fix.
+
+Hardware Interfaces
+-------------------
+
+All the chips suported by this driver are LPC Super-I/O chips, accessed
+through the LPC bus (ISA-like I/O ports). The IT8712F additionally has an
+SMBus interface to the hardware monitoring functions. This driver no
+longer supports this interface though, as it is slower and less reliable
+than the ISA access, and was only available on a small number of
+motherboard models.
+
+
Description
-----------
Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
Author: Rudolf Marek
-Contact: Rudolf Marek <r.marek@sh.cvut.cz>
+Contact: Rudolf Marek <r.marek@assembler.cz>
Description
-----------
--- /dev/null
+Kernel driver pc87427
+=====================
+
+Supported chips:
+ * National Semiconductor PC87427
+ Prefix: 'pc87427'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/apc_007.html
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Thanks to Amir Habibi at Candelis for setting up a test system, and to
+Michael Kress for testing several iterations of this driver.
+
+
+Description
+-----------
+
+The National Semiconductor Super I/O chip includes complete hardware
+monitoring capabilities. It can monitor up to 18 voltages, 8 fans and
+6 temperature sensors. Only the fans are supported at the moment.
+
+This chip also has fan controlling features, which are not yet supported
+by this driver either.
+
+The driver assumes that no more than one chip is present, which seems
+reasonable.
+
+
+Fan Monitoring
+--------------
+
+Fan rotation speeds are reported as 14-bit values from a gated clock
+signal. Speeds down to 83 RPM can be measured.
+
+An alarm is triggered if the rotation speed drops below a programmable
+limit. Another alarm is triggered if the speed is too low to to be measured
+(including stalled or missing fan).
****************
temp[1-*]_type Sensor type selection.
- Integers 1 to 4 or thermistor Beta value (typically 3435)
+ Integers 1 to 6 or thermistor Beta value (typically 3435)
RW
1: PII/Celeron Diode
2: 3904 transistor
3: thermal diode
4: thermistor (default/unknown Beta)
+ 5: AMD AMDSI
+ 6: Intel PECI
Not all types are supported by all chips
temp[1-*]_max Temperature max value.
Authors:
Jean Delvare <khali@linux-fr.org>
Yuan Mu (Winbond)
- Rudolf Marek <r.marek@sh.cvut.cz>
+ Rudolf Marek <r.marek@assembler.cz>
Description
-----------
and Mark Studebaker <mdsxyz123@yahoo.com>
w83792d.c:
Chunhao Huang <DZShen@Winbond.com.tw>,
- Rudolf Marek <r.marek@sh.cvut.cz>
+ Rudolf Marek <r.marek@assembler.cz>
Additional contributors:
Sven Anders <anders@anduras.de>
--- /dev/null
+Kernel driver w83793
+====================
+
+Supported chips:
+ * Winbond W83793G/W83793R
+ Prefix: 'w83793'
+ Addresses scanned: I2C 0x2c - 0x2f
+ Datasheet: Still not published
+
+Authors:
+ Yuan Mu (Winbond Electronics)
+ Rudolf Marek <r.marek@assembler.cz>
+
+
+Module parameters
+-----------------
+
+* reset int
+ (default 0)
+ This parameter is not recommended, it will lose motherboard specific
+ settings. Use 'reset=1' to reset the chip when loading this module.
+
+* force_subclients=bus,caddr,saddr1,saddr2
+ This is used to force the i2c addresses for subclients of
+ a certain chip. Typical usage is `force_subclients=0,0x2f,0x4a,0x4b'
+ to force the subclients of chip 0x2f on bus 0 to i2c addresses
+ 0x4a and 0x4b.
+
+
+Description
+-----------
+
+This driver implements support for Winbond W83793G/W83793R chips.
+
+* Exported features
+ This driver exports 10 voltage sensors, up to 12 fan tachometer inputs,
+ 6 remote temperatures, up to 8 sets of PWM fan controls, SmartFan
+ (automatic fan speed control) on all temperature/PWM combinations, 2
+ sets of 6-pin CPU VID input.
+
+* Sensor resolutions
+ If your motherboard maker used the reference design, the resolution of
+ voltage0-2 is 2mV, resolution of voltage3/4/5 is 16mV, 8mV for voltage6,
+ 24mV for voltage7/8. Temp1-4 have a 0.25 degree Celsius resolution,
+ temp5-6 have a 1 degree Celsiis resolution.
+
+* Temperature sensor types
+ Temp1-4 have 3 possible types. It can be read from (and written to)
+ temp[1-4]_type.
+ - If the value of 0, the related temperature channel stops
+ monitoring.
+ - If the value is 3, it starts monitoring using a remote termal diode
+ (default).
+ - If the value is 5, it starts monitoring using the temperature sensor
+ in AMD CPU and get result by AMDSI.
+ - If the value is 6, it starts monitoring using the temperature sensor
+ in Intel CPU and get result by PECI.
+ Temp5-6 can be connected to external thermistors (value of
+ temp[5-6]_type is 4). They can also be disabled (value is 0).
+
+* Alarm mechanism
+ For voltage sensors, an alarm triggers if the measured value is below
+ the low voltage limit or over the high voltage limit.
+ For temperature sensors, an alarm triggers if the measured value goes
+ above the high temperature limit, and wears off only after the measured
+ value drops below the hysteresis value.
+ For fan sensors, an alarm triggers if the measured value is below the
+ low speed limit.
+
+* SmartFan/PWM control
+ If you want to set a pwm fan to manual mode, you just need to make sure it
+ is not controlled by any temp channel, for example, you want to set fan1
+ to manual mode, you need to check the value of temp[1-6]_fan_map, make
+ sure bit 0 is cleared in the 6 values. And then set the pwm1 value to
+ control the fan.
+
+ Each temperature channel can control all the 8 PWM outputs (by setting the
+ corresponding bit in tempX_fan_map), you can set the temperature channel
+ mode using temp[1-6]_pwm_enable, 2 is Thermal Cruise mode and 3
+ is the SmartFanII mode. Temperature channels will try to speed up or
+ slow down all controlled fans, this means one fan can receive different
+ PWM value requests from different temperature channels, but the chip
+ will always pick the safest (max) PWM value for each fan.
+
+ In Thermal Cruise mode, the chip attempts to keep the temperature at a
+ predefined value, within a tolerance margin. So if tempX_input >
+ thermal_cruiseX + toleranceX, the chip will increase the PWM value,
+ if tempX_input < thermal_cruiseX - toleranceX, the chip will decrease
+ the PWM value. If the temperature is within the tolerance range, the PWM
+ value is left unchanged.
+
+ SmartFanII works differently, you have to define up to 7 PWM, temperature
+ trip points, defining a PWM/temperature curve which the chip will follow.
+ While not fundamentally different from the Thermal Cruise mode, the
+ implementation is quite different, giving you a finer-grained control.
+
+* Chassis
+ If the case open alarm triggers, it will stay in this state unless cleared
+ by any write to the sysfs file "chassis".
+
+* VID and VRM
+ The VRM version is detected automatically, don't modify the it unless you
+ *do* know the cpu VRM version and it's not properly detected.
+
+
+Notes
+-----
+
+ Only Fan1-5 and PWM1-3 are guaranteed to always exist, other fan inputs and
+ PWM outputs may or may not exist depending on the chip pin configuration.
sym53c416= [HW,SCSI]
See header of drivers/scsi/sym53c416.c.
+ sysrq_always_enabled
+ [KNL]
+ Ignore sysrq setting - this boot parameter will
+ neutralize any effect of /proc/sys/kernel/sysrq.
+ Useful for debugging.
+
t128= [HW,SCSI]
See header of drivers/scsi/t128.c.
ALI1563 I2C DRIVER
P: Rudolf Marek
-M: r.marek@sh.cvut.cz
+M: r.marek@assembler.cz
L: i2c@lm-sensors.org
S: Maintained
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
S: Supported
+AMS (Apple Motion Sensor) DRIVER
+P: Stelian Pop
+M: stelian@popies.net
+P: Michael Hanselmann
+M: linux-kernel@hansmi.ch
+S: Supported
+
AMSO1100 RNIC DRIVER
P: Tom Tucker
M: tom@opengridcomputing.com
W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
S: Maintained
+KERNEL VIRTUAL MACHINE (KVM)
+P: Avi Kivity
+M: avi@qumranet.com
+L: kvm-devel@lists.sourceforge.net
+W: kvm.sourceforge.net
+S: Supported
+
KEXEC
P: Eric Biederman
M: ebiederm@xmission.com
L: lm-sensors@lm-sensors.org
S: Maintained
+W83793 HARDWARE MONITORING DRIVER
+P: Rudolf Marek
+M: r.marek@assembler.cz
+L: lm-sensors@lm-sensors.org
+S: Maintained
+
W83L51xD SD/MMC CARD INTERFACE DRIVER
P: Pierre Ossman
M: drzeus-wbsd@drzeus.cx
PHONY += checkstack kernelrelease kernelversion
-# Use $(SUBARCH) here instead of $(ARCH) so that this works for UML.
-# In the UML case, $(SUBARCH) is the name of the underlying
-# architecture, while for all other arches, it is the same as $(ARCH).
+# UML needs a little special treatment here. It wants to use the host
+# toolchain, so needs $(SUBARCH) passed to checkstack.pl. Everyone
+# else wants $(ARCH), including people doing cross-builds, which means
+# that $(SUBARCH) doesn't work here.
+ifeq ($(ARCH), um)
+CHECKSTACK_ARCH := $(SUBARCH)
+else
+CHECKSTACK_ARCH := $(ARCH)
+endif
checkstack:
$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
- $(PERL) $(src)/scripts/checkstack.pl $(SUBARCH)
+ $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
kernelrelease:
$(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
{
struct apm_user *as;
- as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
if (as) {
/*
* XXX - this is a tiny bit broken, when we consider BSD
}
if (c_id(&excd) == 0x80) { /* loader */
if (!ec->loader) {
- ec->loader = (loader_t)kmalloc(c_len(&excd),
+ ec->loader = kmalloc(c_len(&excd),
GFP_KERNEL);
if (ec->loader)
ecard_readbytes(ec->loader, ec,
config MACH_OMAP_OSK
bool "TI OSK Support"
depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ select TPS65010
help
TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
if you have such a board.
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
}
if (c_id(&excd) == 0x80) { /* loader */
if (!ec->loader) {
- ec->loader = (loader_t)kmalloc(c_len(&excd),
+ ec->loader = kmalloc(c_len(&excd),
GFP_KERNEL);
if (ec->loader)
ecard_readbytes(ec->loader, ec,
(irq_flags & IRQF_SHARED && !dev_id))
return -EINVAL;
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+ action = kmalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action)
return -ENOMEM;
#else
struct mtd_info *mtd_ram;
- mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
+ mtd_ram = kmalloc(sizeof(struct mtd_info),
GFP_KERNEL);
if (!mtd_ram) {
panic("axisflashmap couldn't allocate memory for "
if (p > GPIO_MINOR_LAST)
return -EINVAL;
- priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
+ priv = kmalloc(sizeof(struct gpio_private),
GFP_KERNEL);
if (!priv)
#else
struct mtd_info *mtd_ram;
- mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
+ mtd_ram = kmalloc(sizeof(struct mtd_info),
GFP_KERNEL);
if (!mtd_ram) {
panic("axisflashmap couldn't allocate memory for "
if (p > GPIO_MINOR_LAST)
return -EINVAL;
- priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
+ priv = kmalloc(sizeof(struct gpio_private),
GFP_KERNEL);
if (!priv)
int __init
cris_init_signal(void)
{
- u16* data = (u16*)kmalloc(PAGE_SIZE, GFP_KERNEL);
+ u16* data = kmalloc(PAGE_SIZE, GFP_KERNEL);
/* This is movu.w __NR_sigreturn, r9; break 13; */
data[0] = 0x9c5f;
__init init_cris_profile(void)
{
struct proc_dir_entry *entry;
- sample_buffer = (char*)kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
+ sample_buffer = kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
sample_buffer_pos = sample_buffer;
entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL);
if (entry) {
return -EBUSY;
if (use_kmalloc)
- irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
+ irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
else {
/* use bootmem allocater */
irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
}
if (use_kmalloc)
- irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
+ irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
else {
/* use bootmem allocater */
irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
{
struct apm_user * as;
- as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+ as = kmalloc(sizeof(*as), GFP_KERNEL);
if (as == NULL) {
printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
sizeof(*as));
/*
* Intel CPU Microcode Update Driver for Linux
*
- * Copyright (C) 2000-2004 Tigran Aivazian
+ * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
* 2006 Shaohua Li <shaohua.li@intel.com>
*
* This driver allows to upgrade microcode on Intel processors
#include <asm/processor.h>
MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
-MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
+MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
MODULE_LICENSE("GPL");
#define MICROCODE_VERSION "1.14a"
register_hotcpu_notifier(&mc_cpu_notifier);
printk(KERN_INFO
- "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
+ "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
return 0;
}
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
-#ifdef CONFIG_SMP
EXPORT_SYMBOL(smp_num_siblings);
-#endif
/* Last level cache ID of each logical CPU */
int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
int e;
for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) {
- if (!(p = (char *)kmalloc(sz, GFP_KERNEL)))
+ if (!(p = kmalloc(sz, GFP_KERNEL)))
break;
e = ia64_sn_ioif_get_pci_topology(__pa(p), sz);
if (e == SALRET_OK)
unsigned long addr;
struct vm_struct **p, *tmp, *area;
- area = (struct vm_struct *)kmalloc(sizeof(*area), GFP_KERNEL);
+ area = kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return NULL;
addr = KMAP_START;
{
struct apm_user *as;
- as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
if (as) {
/*
* XXX - this is a tiny bit broken, when we consider BSD
preempt_check_resched();
}
+void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma)
+{
+ void *vfrom, *vto;
+
+ vto = kmap_atomic(to, KM_USER1);
+ if (cpu_has_dc_aliases) {
+ vfrom = kmap_coherent(from, vaddr);
+ copy_page(vto, vfrom);
+ kunmap_coherent(from);
+ } else {
+ vfrom = kmap_atomic(from, KM_USER0);
+ copy_page(vto, vfrom);
+ kunmap_atomic(vfrom, KM_USER0);
+ }
+ if (((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) ||
+ pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
+ flush_data_cache_page((unsigned long)vto);
+ kunmap_atomic(vto, KM_USER1);
+ /* Make sure this page is cleared on other CPU's too before using it */
+ smp_wmb();
+}
+
+EXPORT_SYMBOL(copy_user_highpage);
+
void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)
printk(KERN_DEBUG "len of arg1 = %d\n", len);
if (len == 0)
return 0;
- fsname = (char *) kmalloc(len, GFP_KERNEL);
+ fsname = kmalloc(len, GFP_KERNEL);
if ( !fsname ) {
printk(KERN_DEBUG "failed to kmalloc fsname\n");
return 0;
struct pt_regs *r = &t->thread.regs;
struct pt_regs *r2;
- r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+ r2 = kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
if (!r2)
return;
*r2 = *r;
return -ENODEV;
total_size = ppc_md.nvram_size();
- header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
+ header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
if (!header) {
printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");
return -ENOMEM;
}
/* initialize our anchor for the nvram partition list */
- nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
+ nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
if (!nvram_part) {
printk(KERN_ERR "nvram_init: Failed kmalloc\n");
return -ENOMEM;
struct pci_controller* hose;
struct property *map_prop;
- pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
+ pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
if (!pci_to_OF_bus_map) {
printk(KERN_ERR "Can't allocate OF bus map !\n");
return;
struct vm_struct *vm2 = NULL;
struct vm_struct *new_vm = NULL;
- vm1 = (struct vm_struct *) kmalloc(sizeof(*vm1), GFP_KERNEL);
+ vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
if (vm1 == NULL) {
printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
return NULL;
* uppermost remainder, and use existing parent one for the
* lower remainder of parent range
*/
- vm2 = (struct vm_struct *) kmalloc(sizeof(*vm2), GFP_KERNEL);
+ vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
if (vm2 == NULL) {
printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
kfree(vm1);
break;
}
- area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+ area = kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return NULL;
area->flags = 0;
return piar;
}
}
- piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+ piar = kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
if (!piar)
return NULL;
/* Allocate space for the buffer descriptors from regular memory.
* Initialize base addresses for the buffer descriptors.
*/
- cep->rx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * RX_RING_SIZE,
+ cep->rx_bd_base = kmalloc(sizeof(cbd_t) * RX_RING_SIZE,
GFP_KERNEL | GFP_DMA);
ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
- cep->tx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * TX_RING_SIZE,
+ cep->tx_bd_base = kmalloc(sizeof(cbd_t) * TX_RING_SIZE,
GFP_KERNEL | GFP_DMA);
ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
/* Initialize beep stuff */
orig_mksound = kd_mksound;
kd_mksound = cs_mksound;
- beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
+ beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
if (beep_buf == NULL)
printk(KERN_WARNING "dmasound: no memory for "
"beep buffer\n");
config APPLDATA_MEM
tristate "Monitor memory management statistics"
- depends on APPLDATA_BASE
+ depends on APPLDATA_BASE && VM_EVENT_COUNTERS
help
This provides memory management related data to the Linux - VM Monitor
Stream, like paging/swapping rate, memory utilisation, etc.
debug_entry_t*** areas;
int i,j;
- areas = (debug_entry_t ***) kmalloc(nr_areas *
+ areas = kmalloc(nr_areas *
sizeof(debug_entry_t**),
GFP_KERNEL);
if (!areas)
goto fail_malloc_areas;
for (i = 0; i < nr_areas; i++) {
- areas[i] = (debug_entry_t**) kmalloc(pages_per_area *
+ areas[i] = kmalloc(pages_per_area *
sizeof(debug_entry_t*),GFP_KERNEL);
if (!areas[i]) {
goto fail_malloc_areas2;
/* alloc everything */
- rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_KERNEL);
+ rc = kmalloc(sizeof(debug_info_t), GFP_KERNEL);
if(!rc)
goto fail_malloc_rc;
rc->active_entries = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
rc = -ENOMEM;
goto out;
}
- p_info = (file_private_info_t *) kmalloc(sizeof(file_private_info_t),
+ p_info = kmalloc(sizeof(file_private_info_t),
GFP_KERNEL);
if(!p_info){
if(debug_info_snapshot)
ext_int_info_t *p;
int index;
- p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
+ p = kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
if (p == NULL)
return -ENOMEM;
p->code = code;
}
if (action == NULL)
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+ action = kmalloc(sizeof(struct irqaction),
GFP_ATOMIC);
if (!action) {
}
if (action == NULL)
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+ action = kmalloc(sizeof(struct irqaction),
GFP_ATOMIC);
if (!action) {
}
if (action == NULL)
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+ action = kmalloc(sizeof(struct irqaction),
GFP_ATOMIC);
if (!action) {
break;
case 2:
rval = -EFAULT;
- kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
+ kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
GFP_KERNEL);
if (!kmbuf)
break;
break;
case 3:
rval = -EFAULT;
- kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
+ kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
GFP_KERNEL);
if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2,
kmbuf, arg3))
return pkt_len;
}
-static void uml_dev_close(void* dev)
+static void uml_dev_close(struct work_struct *work)
{
- dev_close( (struct net_device *) dev);
+ struct uml_net_private *lp =
+ container_of(work, struct uml_net_private, work);
+ dev_close(lp->dev);
}
irqreturn_t uml_net_interrupt(int irq, void *dev_id)
spin_lock(&lp->lock);
while((err = uml_net_rx(dev)) > 0) ;
if(err < 0) {
- DECLARE_WORK(close_work, uml_dev_close, dev);
printk(KERN_ERR
"Device '%s' read returned %d, shutting it down\n",
dev->name, err);
* again lp->lock.
* And dev_close() can be safely called multiple times on the
* same device, since it tests for (dev->flags & IFF_UP). So
- * there's no harm in delaying the device shutdown. */
- schedule_work(&close_work);
-#error this is not permitted - close_work will go out of scope
+ * there's no harm in delaying the device shutdown.
+ * Furthermore, the workqueue will not re-enqueue an already
+ * enqueued work item. */
+ schedule_work(&lp->work);
goto out;
}
reactivate_fd(lp->fd, UM_ETH_IRQ);
/* This points to the transport private data. It's still clear, but we
* must memset it to 0 *now*. Let's help the drivers. */
memset(lp, 0, size);
+ INIT_WORK(&lp->work, uml_dev_close);
/* sysfs register */
if (!driver_registered) {
#include <linux/skbuff.h>
#include <linux/socket.h>
#include <linux/list.h>
+#include <linux/workqueue.h>
struct uml_net {
struct list_head list;
struct net_device *dev;
struct timer_list tl;
struct net_device_stats stats;
+ struct work_struct work;
int fd;
unsigned char mac[ETH_ALEN];
unsigned short (*protocol)(struct sk_buff *);
struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
.func = 0,
.bytecount = bytecount,
- .ptr = (void *)kmalloc(bytecount, GFP_KERNEL)};
+ .ptr = kmalloc(bytecount, GFP_KERNEL)};
u32 cpu;
if(ptrace_ldt.ptr == NULL)
host_ldt_entries = dummy_list;
else {
size = (size + 1) * sizeof(dummy_list[0]);
- host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
+ host_ldt_entries = kmalloc(size, GFP_KERNEL);
if(host_ldt_entries == NULL) {
printk("ldt_get_host_info: couldn't allocate host ldt list\n");
goto out_free;
obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \
- setup.o signal.o syscalls.o time.o traps.o vectors.o platform.o \
+ setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \
pci-dma.o
## windowspill.o
*
*/
#include <asm/uaccess.h>
-#include <asm/syscalls.h>
+#include <asm/syscall.h>
#include <asm/unistd.h>
#include <linux/linkage.h>
#include <linux/stringify.h>
static int __init as_init(void)
{
- int ret;
-
- ret = elv_register(&iosched_as);
- if (!ret) {
- /*
- * don't allow AS to get unregistered, since we would have
- * to browse all tasks in the system and release their
- * as_io_context first
- */
- __module_get(THIS_MODULE);
- return 0;
- }
-
- return ret;
+ return elv_register(&iosched_as);
}
static void __exit as_exit(void)
return !cfqd->busy_queues;
}
-static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
+static inline pid_t cfq_queue_pid(struct task_struct *task, int rw, int is_sync)
{
- if (rw == READ || rw == WRITE_SYNC)
+ /*
+ * Use the per-process queue, for read requests and syncronous writes
+ */
+ if (!(rw & REQ_RW) || is_sync)
return task->pid;
return CFQ_KEY_ASYNC;
cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
{
struct task_struct *tsk = current;
- pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio));
+ pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio), bio_sync(bio));
struct cfq_queue *cfqq;
cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
struct cfq_data *cfqd = q->elevator->elevator_data;
struct task_struct *tsk = current;
struct cfq_queue *cfqq;
+ unsigned int key;
+
+ key = cfq_queue_pid(tsk, rw, rw & REQ_RW_SYNC);
/*
* don't force setup of a queue from here, as a call to may_queue
* so just lookup a possibly existing queue, or return 'may queue'
* if that fails
*/
- cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio);
+ cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
if (cfqq) {
cfq_init_prio_data(cfqq);
cfq_prio_boost(cfqq);
struct task_struct *tsk = current;
struct cfq_io_context *cic;
const int rw = rq_data_dir(rq);
- pid_t key = cfq_queue_pid(tsk, rw);
+ const int is_sync = rq_is_sync(rq);
+ pid_t key = cfq_queue_pid(tsk, rw, is_sync);
struct cfq_queue *cfqq;
unsigned long flags;
- int is_sync = key != CFQ_KEY_ASYNC;
might_sleep_if(gfp_mask & __GFP_WAIT);
* Returns NULL on failure, with queue_lock held.
* Returns !NULL on success, with queue_lock *not held*.
*/
-static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
- gfp_t gfp_mask)
+static struct request *get_request(request_queue_t *q, int rw_flags,
+ struct bio *bio, gfp_t gfp_mask)
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
struct io_context *ioc = NULL;
+ const int rw = rw_flags & 0x01;
int may_queue, priv;
- may_queue = elv_may_queue(q, rw);
+ may_queue = elv_may_queue(q, rw_flags);
if (may_queue == ELV_MQUEUE_NO)
goto rq_starved;
spin_unlock_irq(q->queue_lock);
- rq = blk_alloc_request(q, rw, priv, gfp_mask);
+ rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
if (unlikely(!rq)) {
/*
* Allocation failed presumably due to memory. Undo anything
*
* Called with q->queue_lock held, and returns with it unlocked.
*/
-static struct request *get_request_wait(request_queue_t *q, int rw,
+static struct request *get_request_wait(request_queue_t *q, int rw_flags,
struct bio *bio)
{
+ const int rw = rw_flags & 0x01;
struct request *rq;
- rq = get_request(q, rw, bio, GFP_NOIO);
+ rq = get_request(q, rw_flags, bio, GFP_NOIO);
while (!rq) {
DEFINE_WAIT(wait);
struct request_list *rl = &q->rq;
prepare_to_wait_exclusive(&rl->wait[rw], &wait,
TASK_UNINTERRUPTIBLE);
- rq = get_request(q, rw, bio, GFP_NOIO);
+ rq = get_request(q, rw_flags, bio, GFP_NOIO);
if (!rq) {
struct io_context *ioc;
int el_ret, nr_sectors, barrier, err;
const unsigned short prio = bio_prio(bio);
const int sync = bio_sync(bio);
+ int rw_flags;
nr_sectors = bio_sectors(bio);
}
get_rq:
+ /*
+ * This sync check and mask will be re-done in init_request_from_bio(),
+ * but we need to set it earlier to expose the sync flag to the
+ * rq allocator and io schedulers.
+ */
+ rw_flags = bio_data_dir(bio);
+ if (sync)
+ rw_flags |= REQ_RW_SYNC;
+
/*
* Grab a free request. This is might sleep but can not fail.
* Returns with the queue unlocked.
*/
- req = get_request_wait(q, bio_data_dir(bio), bio);
+ req = get_request_wait(q, rw_flags, bio);
/*
* After dropping the lock and possibly sleeping here, our request
#include <linux/crypto.h>
#include <linux/errno.h>
#include <linux/kernel.h>
-#include <linux/io.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/seq_file.h>
#ifdef TRACKBUFFER
BufferDrive = BufferSide = BufferTrack = -1;
/* Atari uses 512 - I want to eventually cope with 1K sectors */
- DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
+ DMABuffer = kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
TrackBuffer = DMABuffer + 512;
#else
/* Allocate memory for the DMAbuffer - on the Atari this takes it
out of some special memory... */
- DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */
+ DMABuffer = kmalloc(2048); /* Copes with pretty large sectors */
#endif
err = -ENOMEM;
if (!DMAbuffer)
return rc;
adma_enter_reg_mode(ap);
rc = -ENOMEM;
- pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+ pp = kzalloc(sizeof(*pp), GFP_KERNEL);
if (!pp)
goto err_out;
pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
if (rc)
goto err_out_iounmap;
- probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
+ probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) {
rc = -ENOMEM;
goto err_out_iounmap;
/* initialize memory management */
buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
- eni_dev->free_list = (struct eni_free *) kmalloc(
+ eni_dev->free_list = kmalloc(
sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);
if (!eni_dev->free_list) {
printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
goto out0;
}
- eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
+ eni_dev = kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
if (!eni_dev) goto out0;
if (!cpu_zeroes) {
cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE,
cid = he_mkcid(he_dev, vpi, vci);
- he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
+ he_vcc = kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
if (he_vcc == NULL) {
hprintk("unable to allocate he_vcc during open\n");
return -ENOMEM;
struct atm_dev *atmdev;
int result;
- lanai = (struct lanai_dev *) kmalloc(sizeof(*lanai), GFP_KERNEL);
+ lanai = kmalloc(sizeof(*lanai), GFP_KERNEL);
if (lanai == NULL) {
printk(KERN_ERR DEV_LABEL
": couldn't allocate dev_data structure!\n");
if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
return NULL;
- scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
+ scq = kmalloc(sizeof(scq_info), GFP_KERNEL);
if (scq == NULL)
return NULL;
scq->org = kmalloc(2 * size, GFP_KERNEL);
kfree(scq);
return NULL;
}
- scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
+ scq->skb = kmalloc(sizeof(struct sk_buff *) *
(size / NS_SCQE_SIZE), GFP_KERNEL);
if (scq->skb == NULL)
{
DPRINTK("start_tx\n");
zatm_dev = ZATM_DEV(dev);
- zatm_dev->tx_map = (struct atm_vcc **) kmalloc(sizeof(struct atm_vcc *)*
+ zatm_dev->tx_map = kmalloc(sizeof(struct atm_vcc *)*
zatm_dev->chans,GFP_KERNEL);
if (!zatm_dev->tx_map) return -ENOMEM;
zatm_dev->tx_bw = ATM_OC3_PCR;
struct zatm_dev *zatm_dev;
int ret = -ENOMEM;
- zatm_dev = (struct zatm_dev *) kmalloc(sizeof(*zatm_dev), GFP_KERNEL);
+ zatm_dev = kmalloc(sizeof(*zatm_dev), GFP_KERNEL);
if (!zatm_dev) {
printk(KERN_EMERG "%s: memory shortage\n", DEV_LABEL);
goto out;
void class_unregister(struct class * cls)
{
pr_debug("device class '%s': unregistering\n", cls->name);
+ if (cls->virtual_dir)
+ kobject_unregister(cls->virtual_dir);
remove_class_attrs(cls);
subsystem_unregister(&cls->subsys);
}
mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
mapsize *= sizeof (long);
- page = (struct dma_page *) kmalloc (mapsize + sizeof *page, mem_flags);
+ page = kmalloc(mapsize + sizeof *page, mem_flags);
if (!page)
return NULL;
page->vaddr = dma_alloc_coherent (pool->dev,
* pointer. The memory associated with the platform data will be freed
* when the platform device is released.
*/
-int platform_device_add_data(struct platform_device *pdev, void *data, size_t size)
+int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size)
{
void *d;
* Returns zero if the driver registered and bound to a device, else returns
* a negative error code and with the driver not registered.
*/
-int platform_driver_probe(struct platform_driver *drv,
+int __init_or_module platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))
{
int retval, code;
tristate "Atari floppy support"
depends on ATARI
-config BLK_DEV_SWIM_IOP
- bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)"
- depends on MAC && EXPERIMENTAL && BROKEN
- help
- Say Y here to support the SWIM (Super Woz Integrated Machine) IOP
- floppy controller on the Macintosh IIfx and Quadra 900/950.
-
config MAC_FLOPPY
tristate "Support for PowerMac floppy"
depends on PPC_PMAC && !PPC_PMAC64
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
-obj-$(CONFIG_BLK_DEV_SWIM_IOP) += swim_iop.o
obj-$(CONFIG_ATARI_ACSI) += acsi.o
obj-$(CONFIG_ATARI_SLM) += acsi_slm.o
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
status = -ENOMEM;
goto cleanup1;
}
- buff_size = (int *)kmalloc(MAXSGENTRIES * sizeof(int),
+ buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
GFP_KERNEL);
if (!buff_size) {
status = -ENOMEM;
if (err) {
printk(KERN_ERR "cciss: Cannot obtain PCI resources, "
"aborting\n");
- goto err_out_disable_pdev;
+ return err;
}
subsystem_vendor_id = pdev->subsystem_vendor;
#ifdef CCISS_DEBUG
printk("address 0 = %x\n", c->paddr);
#endif /* CCISS_DEBUG */
- c->vaddr = remap_pci_mem(c->paddr, 200);
+ c->vaddr = remap_pci_mem(c->paddr, 0x250);
/* Wait for the board to become ready. (PCI hotplug needs this.)
* We poll for up to 120 secs, once per 100ms. */
}
return 0;
- err_out_free_res:
+err_out_free_res:
+ /*
+ * Deliberately omit pci_disable_device(): it does something nasty to
+ * Smart Array controllers that pci_enable_device does not undo
+ */
pci_release_regions(pdev);
-
- err_out_disable_pdev:
- pci_disable_device(pdev);
return err;
}
if (drv->queue)
blk_cleanup_queue(drv->queue);
}
+ /*
+ * Deliberately omit pci_disable_device(): it does something nasty to
+ * Smart Array controllers that pci_enable_device does not undo
+ */
pci_release_regions(pdev);
- pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_hba(i);
return -1;
#ifdef CONFIG_CISS_SCSI_TAPE
kfree(hba[i]->scsi_rejects.complete);
#endif
+ /*
+ * Deliberately omit pci_disable_device(): it does something nasty to
+ * Smart Array controllers that pci_enable_device does not undo
+ */
pci_release_regions(pdev);
- pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_hba(i);
}
" processing\n");
/* Command does not return anything, but idasend command needs a
buffer */
- id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+ id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
if(id_ctlr_buf==NULL)
{
printk(KERN_WARNING "cpqarray: Out of memory. "
info_p->log_drv_map = 0;
- id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
+ id_ldrive = kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
if(id_ldrive == NULL)
{
printk( KERN_ERR "cpqarray: out of memory.\n");
return;
}
- id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+ id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
if(id_ctlr_buf == NULL)
{
kfree(id_ldrive);
return;
}
- id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
+ id_lstatus_buf = kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
if(id_lstatus_buf == NULL)
{
kfree(id_ctlr_buf);
return;
}
- sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL);
+ sense_config_buf = kmalloc(sizeof(config_t), GFP_KERNEL);
if(sense_config_buf == NULL)
{
kfree(id_lstatus_buf);
+++ /dev/null
-/*
- * Driver for the SWIM (Super Woz Integrated Machine) IOP
- * floppy controller on the Macintosh IIfx and Quadra 900/950
- *
- * Written by Joshua M. Thompson (funaho@jurai.org)
- * based on the SWIM3 driver (c) 1996 by Paul Mackerras.
- *
- * 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.
- *
- * 1999-06-12 (jmt) - Initial implementation.
- */
-
-/*
- * -------------------
- * Theory of Operation
- * -------------------
- *
- * Since the SWIM IOP is message-driven we implement a simple request queue
- * system. One outstanding request may be queued at any given time (this is
- * an IOP limitation); only when that request has completed can a new request
- * be sent.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/fd.h>
-#include <linux/ioctl.h>
-#include <linux/blkdev.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mac_iop.h>
-#include <asm/swim_iop.h>
-
-#define DRIVER_VERSION "Version 0.1 (1999-06-12)"
-
-#define MAX_FLOPPIES 4
-
-enum swim_state {
- idle,
- available,
- revalidating,
- transferring,
- ejecting
-};
-
-struct floppy_state {
- enum swim_state state;
- int drive_num; /* device number */
- int secpercyl; /* disk geometry information */
- int secpertrack;
- int total_secs;
- int write_prot; /* 1 if write-protected, 0 if not, -1 dunno */
- int ref_count;
- struct timer_list timeout;
- int ejected;
- struct wait_queue *wait;
- int wanted;
- int timeout_pending;
-};
-
-struct swim_iop_req {
- int sent;
- int complete;
- __u8 command[32];
- struct floppy_state *fs;
- void (*done)(struct swim_iop_req *);
-};
-
-static struct swim_iop_req *current_req;
-static int floppy_count;
-
-static struct floppy_state floppy_states[MAX_FLOPPIES];
-static DEFINE_SPINLOCK(swim_iop_lock);
-
-#define CURRENT elv_next_request(swim_queue)
-
-static char *drive_names[7] = {
- "not installed", /* DRV_NONE */
- "unknown (1)", /* DRV_UNKNOWN */
- "a 400K drive", /* DRV_400K */
- "an 800K drive" /* DRV_800K */
- "unknown (4)", /* ???? */
- "an FDHD", /* DRV_FDHD */
- "unknown (6)", /* ???? */
- "an Apple HD20" /* DRV_HD20 */
-};
-
-int swimiop_init(void);
-static void swimiop_init_request(struct swim_iop_req *);
-static int swimiop_send_request(struct swim_iop_req *);
-static void swimiop_receive(struct iop_msg *);
-static void swimiop_status_update(int, struct swim_drvstatus *);
-static int swimiop_eject(struct floppy_state *fs);
-
-static int floppy_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long param);
-static int floppy_open(struct inode *inode, struct file *filp);
-static int floppy_release(struct inode *inode, struct file *filp);
-static int floppy_check_change(struct gendisk *disk);
-static int floppy_revalidate(struct gendisk *disk);
-static int grab_drive(struct floppy_state *fs, enum swim_state state,
- int interruptible);
-static void release_drive(struct floppy_state *fs);
-static void set_timeout(struct floppy_state *fs, int nticks,
- void (*proc)(unsigned long));
-static void fd_request_timeout(unsigned long);
-static void do_fd_request(request_queue_t * q);
-static void start_request(struct floppy_state *fs);
-
-static struct block_device_operations floppy_fops = {
- .open = floppy_open,
- .release = floppy_release,
- .ioctl = floppy_ioctl,
- .media_changed = floppy_check_change,
- .revalidate_disk= floppy_revalidate,
-};
-
-static struct request_queue *swim_queue;
-/*
- * SWIM IOP initialization
- */
-
-int swimiop_init(void)
-{
- volatile struct swim_iop_req req;
- struct swimcmd_status *cmd = (struct swimcmd_status *) &req.command[0];
- struct swim_drvstatus *ds = &cmd->status;
- struct floppy_state *fs;
- int i;
-
- current_req = NULL;
- floppy_count = 0;
-
- if (!iop_ism_present)
- return -ENODEV;
-
- if (register_blkdev(FLOPPY_MAJOR, "fd"))
- return -EBUSY;
-
- swim_queue = blk_init_queue(do_fd_request, &swim_iop_lock);
- if (!swim_queue) {
- unregister_blkdev(FLOPPY_MAJOR, "fd");
- return -ENOMEM;
- }
-
- printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
- DRIVER_VERSION);
-
- if (iop_listen(SWIM_IOP, SWIM_CHAN, swimiop_receive, "SWIM") != 0) {
- printk(KERN_ERR "SWIM-IOP: IOP channel already in use; can't initialize.\n");
- unregister_blkdev(FLOPPY_MAJOR, "fd");
- blk_cleanup_queue(swim_queue);
- return -EBUSY;
- }
-
- printk(KERN_ERR "SWIM_IOP: probing for installed drives.\n");
-
- for (i = 0 ; i < MAX_FLOPPIES ; i++) {
- memset(&floppy_states[i], 0, sizeof(struct floppy_state));
- fs = &floppy_states[floppy_count];
-
- swimiop_init_request(&req);
- cmd->code = CMD_STATUS;
- cmd->drive_num = i + 1;
- if (swimiop_send_request(&req) != 0) continue;
- while (!req.complete);
- if (cmd->error != 0) {
- printk(KERN_ERR "SWIM-IOP: probe on drive %d returned error %d\n", i, (uint) cmd->error);
- continue;
- }
- if (ds->installed != 0x01) continue;
- printk("SWIM-IOP: drive %d is %s (%s, %s, %s, %s)\n", i,
- drive_names[ds->info.type],
- ds->info.external? "ext" : "int",
- ds->info.scsi? "scsi" : "floppy",
- ds->info.fixed? "fixed" : "removable",
- ds->info.secondary? "secondary" : "primary");
- swimiop_status_update(floppy_count, ds);
- fs->state = idle;
-
- init_timer(&fs->timeout);
- floppy_count++;
- }
- printk("SWIM-IOP: detected %d installed drives.\n", floppy_count);
-
- for (i = 0; i < floppy_count; i++) {
- struct gendisk *disk = alloc_disk(1);
- if (!disk)
- continue;
- disk->major = FLOPPY_MAJOR;
- disk->first_minor = i;
- disk->fops = &floppy_fops;
- sprintf(disk->disk_name, "fd%d", i);
- disk->private_data = &floppy_states[i];
- disk->queue = swim_queue;
- set_capacity(disk, 2880 * 2);
- add_disk(disk);
- }
-
- return 0;
-}
-
-static void swimiop_init_request(struct swim_iop_req *req)
-{
- req->sent = 0;
- req->complete = 0;
- req->done = NULL;
-}
-
-static int swimiop_send_request(struct swim_iop_req *req)
-{
- unsigned long flags;
- int err;
-
- /* It's doubtful an interrupt routine would try to send */
- /* a SWIM request, but I'd rather play it safe here. */
-
- local_irq_save(flags);
-
- if (current_req != NULL) {
- local_irq_restore(flags);
- return -ENOMEM;
- }
-
- current_req = req;
-
- /* Interrupts should be back on for iop_send_message() */
-
- local_irq_restore(flags);
-
- err = iop_send_message(SWIM_IOP, SWIM_CHAN, (void *) req,
- sizeof(req->command), (__u8 *) &req->command[0],
- swimiop_receive);
-
- /* No race condition here; we own current_req at this point */
-
- if (err) {
- current_req = NULL;
- } else {
- req->sent = 1;
- }
- return err;
-}
-
-/*
- * Receive a SWIM message from the IOP.
- *
- * This will be called in two cases:
- *
- * 1. A message has been successfully sent to the IOP.
- * 2. An unsolicited message was received from the IOP.
- */
-
-void swimiop_receive(struct iop_msg *msg)
-{
- struct swim_iop_req *req;
- struct swimmsg_status *sm;
- struct swim_drvstatus *ds;
-
- req = current_req;
-
- switch(msg->status) {
- case IOP_MSGSTATUS_COMPLETE:
- memcpy(&req->command[0], &msg->reply[0], sizeof(req->command));
- req->complete = 1;
- if (req->done) (*req->done)(req);
- current_req = NULL;
- break;
- case IOP_MSGSTATUS_UNSOL:
- sm = (struct swimmsg_status *) &msg->message[0];
- ds = &sm->status;
- swimiop_status_update(sm->drive_num, ds);
- iop_complete_message(msg);
- break;
- }
-}
-
-static void swimiop_status_update(int drive_num, struct swim_drvstatus *ds)
-{
- struct floppy_state *fs = &floppy_states[drive_num];
-
- fs->write_prot = (ds->write_prot == 0x80);
- if ((ds->disk_in_drive != 0x01) && (ds->disk_in_drive != 0x02)) {
- fs->ejected = 1;
- } else {
- fs->ejected = 0;
- }
- switch(ds->info.type) {
- case DRV_400K:
- fs->secpercyl = 10;
- fs->secpertrack = 10;
- fs->total_secs = 800;
- break;
- case DRV_800K:
- fs->secpercyl = 20;
- fs->secpertrack = 10;
- fs->total_secs = 1600;
- break;
- case DRV_FDHD:
- fs->secpercyl = 36;
- fs->secpertrack = 18;
- fs->total_secs = 2880;
- break;
- default:
- fs->secpercyl = 0;
- fs->secpertrack = 0;
- fs->total_secs = 0;
- break;
- }
-}
-
-static int swimiop_eject(struct floppy_state *fs)
-{
- int err, n;
- struct swim_iop_req req;
- struct swimcmd_eject *cmd = (struct swimcmd_eject *) &req.command[0];
-
- err = grab_drive(fs, ejecting, 1);
- if (err) return err;
-
- swimiop_init_request(&req);
- cmd->code = CMD_EJECT;
- cmd->drive_num = fs->drive_num;
- err = swimiop_send_request(&req);
- if (err) {
- release_drive(fs);
- return err;
- }
- for (n = 2*HZ; n > 0; --n) {
- if (req.complete) break;
- if (signal_pending(current)) {
- err = -EINTR;
- break;
- }
- schedule_timeout_interruptible(1);
- }
- release_drive(fs);
- return cmd->error;
-}
-
-static struct floppy_struct floppy_type =
- { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
-
-static int floppy_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long param)
-{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
- int err;
-
- if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- switch (cmd) {
- case FDEJECT:
- if (fs->ref_count != 1)
- return -EBUSY;
- err = swimiop_eject(fs);
- return err;
- case FDGETPRM:
- if (copy_to_user((void *) param, (void *) &floppy_type,
- sizeof(struct floppy_struct)))
- return -EFAULT;
- return 0;
- }
- return -ENOTTY;
-}
-
-static int floppy_open(struct inode *inode, struct file *filp)
-{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
-
- if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
- return -EBUSY;
-
- if ((filp->f_flags & O_NDELAY) == 0 && (filp->f_mode & 3)) {
- check_disk_change(inode->i_bdev);
- if (fs->ejected)
- return -ENXIO;
- }
-
- if ((filp->f_mode & 2) && fs->write_prot)
- return -EROFS;
-
- if (filp->f_flags & O_EXCL)
- fs->ref_count = -1;
- else
- ++fs->ref_count;
-
- return 0;
-}
-
-static int floppy_release(struct inode *inode, struct file *filp)
-{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
- if (fs->ref_count > 0)
- fs->ref_count--;
- return 0;
-}
-
-static int floppy_check_change(struct gendisk *disk)
-{
- struct floppy_state *fs = disk->private_data;
- return fs->ejected;
-}
-
-static int floppy_revalidate(struct gendisk *disk)
-{
- struct floppy_state *fs = disk->private_data;
- grab_drive(fs, revalidating, 0);
- /* yadda, yadda */
- release_drive(fs);
- return 0;
-}
-
-static void floppy_off(unsigned int nr)
-{
-}
-
-static int grab_drive(struct floppy_state *fs, enum swim_state state,
- int interruptible)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- if (fs->state != idle) {
- ++fs->wanted;
- while (fs->state != available) {
- if (interruptible && signal_pending(current)) {
- --fs->wanted;
- local_irq_restore(flags);
- return -EINTR;
- }
- interruptible_sleep_on(&fs->wait);
- }
- --fs->wanted;
- }
- fs->state = state;
- local_irq_restore(flags);
- return 0;
-}
-
-static void release_drive(struct floppy_state *fs)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- fs->state = idle;
- start_request(fs);
- local_irq_restore(flags);
-}
-
-static void set_timeout(struct floppy_state *fs, int nticks,
- void (*proc)(unsigned long))
-{
- unsigned long flags;
-
- local_irq_save(flags);
- if (fs->timeout_pending)
- del_timer(&fs->timeout);
- init_timer(&fs->timeout);
- fs->timeout.expires = jiffies + nticks;
- fs->timeout.function = proc;
- fs->timeout.data = (unsigned long) fs;
- add_timer(&fs->timeout);
- fs->timeout_pending = 1;
- local_irq_restore(flags);
-}
-
-static void do_fd_request(request_queue_t * q)
-{
- int i;
-
- for (i = 0 ; i < floppy_count ; i++) {
- start_request(&floppy_states[i]);
- }
-}
-
-static void fd_request_complete(struct swim_iop_req *req)
-{
- struct floppy_state *fs = req->fs;
- struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req->command[0];
-
- del_timer(&fs->timeout);
- fs->timeout_pending = 0;
- fs->state = idle;
- if (cmd->error) {
- printk(KERN_ERR "SWIM-IOP: error %d on read/write request.\n", cmd->error);
- end_request(CURRENT, 0);
- } else {
- CURRENT->sector += cmd->num_blocks;
- CURRENT->current_nr_sectors -= cmd->num_blocks;
- if (CURRENT->current_nr_sectors <= 0) {
- end_request(CURRENT, 1);
- return;
- }
- }
- start_request(fs);
-}
-
-static void fd_request_timeout(unsigned long data)
-{
- struct floppy_state *fs = (struct floppy_state *) data;
-
- fs->timeout_pending = 0;
- end_request(CURRENT, 0);
- fs->state = idle;
-}
-
-static void start_request(struct floppy_state *fs)
-{
- volatile struct swim_iop_req req;
- struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req.command[0];
-
- if (fs->state == idle && fs->wanted) {
- fs->state = available;
- wake_up(&fs->wait);
- return;
- }
- while (CURRENT && fs->state == idle) {
- if (CURRENT->bh && !buffer_locked(CURRENT->bh))
- panic("floppy: block not locked");
-#if 0
- printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
- CURRENT->rq_disk->disk_name, CURRENT->cmd,
- CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer);
- printk(" errors=%d current_nr_sectors=%ld\n",
- CURRENT->errors, CURRENT->current_nr_sectors);
-#endif
-
- if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
- end_request(CURRENT, 0);
- continue;
- }
- if (CURRENT->current_nr_sectors == 0) {
- end_request(CURRENT, 1);
- continue;
- }
- if (fs->ejected) {
- end_request(CURRENT, 0);
- continue;
- }
-
- swimiop_init_request(&req);
- req.fs = fs;
- req.done = fd_request_complete;
-
- if (CURRENT->cmd == WRITE) {
- if (fs->write_prot) {
- end_request(CURRENT, 0);
- continue;
- }
- cmd->code = CMD_WRITE;
- } else {
- cmd->code = CMD_READ;
-
- }
- cmd->drive_num = fs->drive_num;
- cmd->buffer = CURRENT->buffer;
- cmd->first_block = CURRENT->sector;
- cmd->num_blocks = CURRENT->current_nr_sectors;
-
- if (swimiop_send_request(&req)) {
- end_request(CURRENT, 0);
- continue;
- }
-
- set_timeout(fs, HZ*CURRENT->current_nr_sectors,
- fd_request_timeout);
-
- fs->state = transferring;
- }
-}
size = sizeof(s->disckey.value) + 4;
- if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
+ if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
return -ENOMEM;
init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
size = sizeof(s->manufact.value) + 4;
- if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
+ if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
return -ENOMEM;
init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
/* FIXME: we need upper bound checking, too!! */
if (lba < 0)
return -EINVAL;
- cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL);
+ cgc.buffer = kmalloc(blocksize, GFP_KERNEL);
if (cgc.buffer == NULL)
return -ENOMEM;
memset(&sense, 0, sizeof(sense));
int size = sizeof(dvd_struct);
if (!CDROM_CAN(CDC_DVD))
return -ENOSYS;
- if ((s = (dvd_struct *) kmalloc(size, GFP_KERNEL)) == NULL)
+ if ((s = kmalloc(size, GFP_KERNEL)) == NULL)
return -ENOMEM;
cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n");
if (copy_from_user(s, (dvd_struct __user *)arg, size)) {
return -EIO;
}
printk(" adapter at 0x%x", cm206_base);
- cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
+ cd = kmalloc(size, GFP_KERNEL);
if (!cd)
goto out_base;
/* Now we have found the adaptor card, try to reset it. As we have
config COMPUTONE
tristate "Computone IntelliPort Plus serial support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
---help---
This driver supports the entire family of Intelliport II/Plus
controllers with the exception of the MicroChannel controllers and
config MOXA_SMARTIO_NEW
tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
help
Say Y here if you have a Moxa SmartIO multiport serial card and/or
want to help develop a new version of this driver.
config ISI
tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && PCI
select FW_LOADER
help
This is a driver for the Multi-Tech cards which provide several
config SX
tristate "Specialix SX (and SI) card support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
help
This is a driver for the SX and SI multiport serial cards.
Please read the file <file:Documentation/sx.txt> for details.
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p && p->readonly) return -EIO;
if (!p || --p->refcount) {
- q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
+ q = kmalloc(sizeof(*p), GFP_KERNEL);
if (!q) {
if (p) p->refcount++;
return -ENOMEM;
(&display, (struct lcd_display *) arg,
sizeof(struct lcd_display)))
return -EFAULT;
- rom = (unsigned char *) kmalloc((128), GFP_ATOMIC);
+ rom = kmalloc((128), GFP_ATOMIC);
if (rom == NULL) {
printk(KERN_ERR LCD "kmalloc() failed in %s\n",
__FUNCTION__);
return -EIO;
}
}
- lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
+ lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
if (!lp_table[minor].lp_buffer) {
LP_F(minor) &= ~LP_BUSY;
return -ENOMEM;
static int mxser_set_baud_method[MXSER_PORTS + 1];
static spinlock_t gm_lock;
+#ifdef CONFIG_PCI
static int CheckIsMoxaMust(int io)
{
u8 oldmcr, hwid;
}
return MOXA_OTHER_UART;
}
+#endif
static void process_txrx_fifo(struct mxser_port *info)
{
if (irq)
free_irq(brd->irq, brd);
if (pdev != NULL) { /* PCI */
+#ifdef CONFIG_PCI
pci_release_region(pdev, 2);
pci_release_region(pdev, 3);
pci_dev_put(pdev);
+#endif
} else {
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
release_region(brd->vector, 1);
static int __devinit mxser_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+#ifdef CONFIG_PCI
struct mxser_board *brd;
unsigned int i, j;
unsigned long ioaddress;
brd->info = NULL;
err:
return retval;
+#else
+ return -ENODEV;
+#endif
}
static void __devexit mxser_remove(struct pci_dev *pdev)
static void receive_char(struct r3964_info *pInfo, const unsigned char c);
static void receive_error(struct r3964_info *pInfo, const char flag);
static void on_timeout(unsigned long priv);
-static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg);
-static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char __user *buf);
+static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg);
+static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf);
static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
int error_code, struct r3964_block_header *pBlock);
static struct r3964_message* remove_msg(struct r3964_info *pInfo,
}
static struct r3964_client_info *findClient(
- struct r3964_info *pInfo, pid_t pid)
+ struct r3964_info *pInfo, struct pid *pid)
{
struct r3964_client_info *pClient;
return NULL;
}
-static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
+static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg)
{
struct r3964_client_info *pClient;
struct r3964_client_info **ppClient;
if(pClient->pid == pid)
{
- TRACE_PS("removing client %d from client list", pid);
+ TRACE_PS("removing client %d from client list", pid_nr(pid));
*ppClient = pClient->next;
while(pClient->msg_count)
{
TRACE_M("enable_signals - msg kfree %p",pMsg);
}
}
+ put_pid(pClient->pid);
kfree(pClient);
TRACE_M("enable_signals - kfree %p",pClient);
return 0;
if(pClient==NULL)
return -ENOMEM;
- TRACE_PS("add client %d to client list", pid);
+ TRACE_PS("add client %d to client list", pid_nr(pid));
spin_lock_init(&pClient->lock);
pClient->sig_flags=arg;
- pClient->pid = pid;
+ pClient->pid = get_pid(pid);
pClient->next=pInfo->firstClient;
pClient->first_msg = NULL;
pClient->last_msg = NULL;
return 0;
}
-static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char __user *buf)
+static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf)
{
struct r3964_client_info *pClient;
struct r3964_block_header *block;
/* Send SIGIO signal to client process: */
if(pClient->sig_flags & R3964_USE_SIGIO)
{
- kill_proc(pClient->pid, SIGIO, 1);
+ kill_pid(pClient->pid, SIGIO, 1);
}
}
{
struct r3964_block_header *block;
- TRACE_PS("remove_client_block PID %d", pClient->pid);
+ TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid));
block=pClient->next_block_to_read;
if(block)
TRACE_M("r3964_close - msg kfree %p",pMsg);
}
}
+ put_pid(pClient->pid);
kfree(pClient);
TRACE_M("r3964_close - client kfree %p",pClient);
pClient=pNext;
struct r3964_client_message theMsg;
DECLARE_WAITQUEUE (wait, current);
- int pid = current->pid;
int count;
TRACE_L("read()");
- pClient=findClient(pInfo, pid);
+ pClient=findClient(pInfo, task_pid(current));
if(pClient)
{
pMsg = remove_msg(pInfo, pClient);
struct r3964_block_header *pHeader;
struct r3964_client_info *pClient;
unsigned char *new_data;
- int pid;
TRACE_L("write request, %d characters", count);
/*
pHeader->locks = 0;
pHeader->owner = NULL;
- pid=current->pid;
-
- pClient=findClient(pInfo, pid);
+ pClient=findClient(pInfo, task_pid(current));
if(pClient)
{
pHeader->owner = pClient;
switch(cmd)
{
case R3964_ENABLE_SIGNALS:
- return enable_signals(pInfo, current->pid, arg);
+ return enable_signals(pInfo, task_pid(current), arg);
case R3964_SETPRIORITY:
if(arg<R3964_MASTER || arg>R3964_SLAVE)
return -EINVAL;
pInfo->flags &= ~R3964_BCC;
return 0;
case R3964_READ_TELEGRAM:
- return read_telegram(pInfo, current->pid, (unsigned char __user *)arg);
+ return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg);
default:
return -ENOIOCTLCMD;
}
struct poll_table_struct *wait)
{
struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
- int pid=current->pid;
struct r3964_client_info *pClient;
struct r3964_message *pMsg=NULL;
unsigned long flags;
TRACE_L("POLL");
- pClient=findClient(pInfo,pid);
+ pClient=findClient(pInfo, task_pid(current));
if(pClient)
{
poll_wait(file, &pInfo->read_wait, wait);
n = min(*nr, n);
spin_unlock_irqrestore(&tty->read_lock, flags);
if (n) {
- mb();
retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
n -= retval;
spin_lock_irqsave(&tty->read_lock, flags);
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_attach\n");
- info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
+ info = kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
if (!info) {
printk("Error can't allocate device instance data\n");
return -ENOMEM;
{
struct CmdBlk *CmdBlkP;
- CmdBlkP = (struct CmdBlk *)kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
+ CmdBlkP = kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
if (CmdBlkP)
memset(CmdBlkP, 0, sizeof(struct CmdBlk));
return CmdBlkP;
#define hpet_set_rtc_irq_bit(arg) 0
#define hpet_rtc_timer_init() do { } while (0)
#define hpet_rtc_dropped_irq() 0
-static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;}
+static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;}
#else
extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
#endif
}
#endif
+#ifdef CONFIG_PROC_FS
static int rtc_proc_open(struct inode *inode, struct file *file);
+#endif
/*
* Bits in rtc_status. (6 bits of room for future expansion)
.fops = &rtc_fops,
};
+#ifdef CONFIG_PROC_FS
static const struct file_operations rtc_proc_fops = {
.owner = THIS_MODULE,
.open = rtc_proc_open,
.llseek = seq_lseek,
.release = single_release,
};
-
-#if defined(RTC_IRQ) && !defined(__sparc__)
-static irq_handler_t rtc_int_handler_ptr;
#endif
static int __init rtc_init(void)
{
+#ifdef CONFIG_PROC_FS
struct proc_dir_entry *ent;
+#endif
#if defined(__alpha__) || defined(__mips__)
unsigned int year, ctrl;
char *guess = NULL;
struct sparc_isa_bridge *isa_br;
struct sparc_isa_device *isa_dev;
#endif
-#endif
-#ifndef __sparc__
+#else
void *r;
+#ifdef RTC_IRQ
+ irq_handler_t rtc_int_handler_ptr;
+#endif
#endif
#ifdef __sparc__
}
}
#endif
+ rtc_has_irq = 0;
printk(KERN_ERR "rtc_init: no PC rtc found\n");
return -EIO;
* PCI Slot 2 INTA# (and some INTx# in Slot 1).
*/
if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) {
+ rtc_has_irq = 0;
printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
return -EIO;
}
else
r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
if (!r) {
+#ifdef RTC_IRQ
+ rtc_has_irq = 0;
+#endif
printk(KERN_ERR "rtc: I/O resource %lx is not free.\n",
(long)(RTC_PORT(0)));
return -EIO;
if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) {
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
+ rtc_has_irq = 0;
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
if (RTC_IOMAPPED)
release_region(RTC_PORT(0), RTC_IO_EXTENT);
if (misc_register(&rtc_dev)) {
#ifdef RTC_IRQ
free_irq(RTC_IRQ, NULL);
+ rtc_has_irq = 0;
#endif
release_region(RTC_PORT(0), RTC_IO_EXTENT);
return -ENODEV;
}
+#ifdef CONFIG_PROC_FS
ent = create_proc_entry("driver/rtc", 0, NULL);
- if (!ent) {
-#ifdef RTC_IRQ
- free_irq(RTC_IRQ, NULL);
+ if (ent)
+ ent->proc_fops = &rtc_proc_fops;
+ else
+ printk(KERN_WARNING "rtc: Failed to register with procfs.\n");
#endif
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
- misc_deregister(&rtc_dev);
- return -ENOMEM;
- }
- ent->proc_fops = &rtc_proc_fops;
#if defined(__alpha__) || defined(__mips__)
rtc_freq = HZ;
}
#endif
+#ifdef CONFIG_PROC_FS
/*
* Info exported via "/proc/driver/rtc".
*/
{
return single_open(file, rtc_proc_show, NULL);
}
+#endif
void rtc_get_rtc_time(struct rtc_time *rtc_tm)
{
/* It is safe/allowed to del_timer a non-active timer */
del_timer(&board->timer);
if (pdev) {
+#ifdef CONFIG_PCI
pci_iounmap(pdev, board->base);
pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
+#endif
} else {
iounmap(board->base);
release_region(board->hw_base, board->hw_len);
#endif
+#ifdef CONFIG_PCI
/********************************************************
* Setting bit 17 in the CNTRL register of the PLX 9050 *
* chip forces a retry on writes while a read is pending.*
}
iounmap(rebase);
}
+#endif
static int __devinit sx_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+#ifdef CONFIG_PCI
struct sx_board *board;
unsigned int i, reg;
int retval = -EIO;
board->flags &= ~SX_BOARD_PRESENT;
err:
return retval;
+#else
+ return -ENODEV;
+#endif
}
static void __devexit sx_pci_remove(struct pci_dev *pdev)
{
struct mgsl_struct *info;
- info = (struct mgsl_struct *)kmalloc(sizeof(struct mgsl_struct),
+ info = kmalloc(sizeof(struct mgsl_struct),
GFP_KERNEL);
if (!info) {
return 0;
if (!info->tx_buf) {
- info->tx_buf = (unsigned char *)kmalloc(info->max_frame_size, GFP_KERNEL);
+ info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
if (!info->tx_buf) {
printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
__FILE__,__LINE__,info->device_name);
{
SLMP_INFO *info;
- info = (SLMP_INFO *)kmalloc(sizeof(SLMP_INFO),
+ info = kmalloc(sizeof(SLMP_INFO),
GFP_KERNEL);
if (!info) {
#include <asm/irq_regs.h>
/* Whether we react on sysrq keys or just ignore them */
-int sysrq_enabled = 1;
+int __read_mostly __sysrq_enabled = 1;
+
+static int __read_mostly sysrq_always_enabled;
+
+int sysrq_on(void)
+{
+ return __sysrq_enabled || sysrq_always_enabled;
+}
+
+/*
+ * A value of 1 means 'all', other nonzero values are an op mask:
+ */
+static inline int sysrq_on_mask(int mask)
+{
+ return sysrq_always_enabled || __sysrq_enabled == 1 ||
+ (__sysrq_enabled & mask);
+}
+
+static int __init sysrq_always_enabled_setup(char *str)
+{
+ sysrq_always_enabled = 1;
+ printk(KERN_INFO "debug: sysrq always enabled.\n");
+
+ return 1;
+}
+
+__setup("sysrq_always_enabled", sysrq_always_enabled_setup);
+
static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
{
* Should we check for enabled operations (/proc/sysrq-trigger
* should not) and is the invoked operation enabled?
*/
- if (!check_mask || sysrq_enabled == 1 ||
- (sysrq_enabled & op_p->enable_mask)) {
+ if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
printk("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
op_p->handler(key, tty);
*/
void handle_sysrq(int key, struct tty_struct *tty)
{
- if (!sysrq_enabled)
- return;
- __handle_sysrq(key, tty, 1);
+ if (sysrq_on())
+ __handle_sysrq(key, tty, 1);
}
EXPORT_SYMBOL(handle_sysrq);
int session;
int i;
struct file *filp;
- struct tty_ldisc *disc;
struct fdtable *fdt;
if (!tty)
return;
session = tty->session;
- /* We don't want an ldisc switch during this */
- disc = tty_ldisc_ref(tty);
- if (disc && disc->flush_buffer)
- disc->flush_buffer(tty);
- tty_ldisc_deref(disc);
+ tty_ldisc_flush(tty);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
barrier();
return tty;
}
+EXPORT_SYMBOL_GPL(get_current_tty);
/*
* Initialize the console device. This is called *early*, so
static DEFINE_SPINLOCK(consolelock);
static DEFINE_SPINLOCK(consoleloglock);
-#ifdef CONFIG_MAGIC_SYSRQ
static int vio_sysrq_pressed;
-extern int sysrq_enabled;
-#endif
#define VIOCHAR_NUM_BUF 16
*/
num_pushed = 0;
for (index = 0; index < cevent->len; index++) {
-#ifdef CONFIG_MAGIC_SYSRQ
- if (sysrq_enabled) {
+ /*
+ * Will be optimized away if !CONFIG_MAGIC_SYSRQ:
+ */
+ if (sysrq_on()) {
/* 0x0f is the ascii character for ^O */
if (cevent->data[index] == '\x0f') {
vio_sysrq_pressed = 1;
continue;
}
}
-#endif
/*
* The sysrq sequence isn't included in this check if
* sysrq is enabled and compiled into the kernel because
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0;
- newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
+ newscreen = kmalloc(new_screen_size, GFP_USER);
if (!newscreen)
return -ENOMEM;
!capable(CAP_SYS_RESOURCE))
return -EPERM;
- key_map = (ushort *) kmalloc(sizeof(plain_map),
+ key_map = kmalloc(sizeof(plain_map),
GFP_KERNEL);
if (!key_map)
return -ENOMEM;
sz = 256;
while (sz < funcbufsize - funcbufleft + delta)
sz <<= 1;
- fnw = (char *) kmalloc(sz, GFP_KERNEL);
+ fnw = kmalloc(sz, GFP_KERNEL);
if(!fnw) {
ret = -ENOMEM;
goto reterr;
switch_screen(vc);
/*
- * This can't appear below a successful kill_proc(). If it did,
+ * This can't appear below a successful kill_pid(). If it did,
* then the *blank_screen operation could occur while X, having
* received acqsig, is waking up on another processor. This
* condition can lead to overlapping accesses to the VGA range
*/
if (vc->vt_mode.mode == VT_PROCESS) {
/*
- * Send the signal as privileged - kill_proc() will
+ * Send the signal as privileged - kill_pid() will
* tell us if the process has gone or something else
* is awry
*/
vc = vc_cons[fg_console].d;
if (vc->vt_mode.mode == VT_PROCESS) {
/*
- * Send the signal as privileged - kill_proc() will
+ * Send the signal as privileged - kill_pid() will
* tell us if the process has gone or something else
* is awry
*/
printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
fc->state = FC_STATE_OFFLINE;
} else {
- fc->posmap = (fcp_posmap *)kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
+ fc->posmap = kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
if (!fc->posmap) {
printk("FC: Not enough memory, offlining channel\n");
fc->state = FC_STATE_OFFLINE;
for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
set_bit (i, fc->scsi_bitmap);
fc->scsi_free = fc->can_queue;
- fc->cmd_slots = (fcp_cmnd **)kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
+ fc->cmd_slots = kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
fc->abort_count = 0;
} else {
fc->scsi_name[0] = 0;
DECLARE_MUTEX_LOCKED(sem);
if (!fc->rst_pkt) {
- fc->rst_pkt = (struct scsi_cmnd *) kmalloc(sizeof(SCpnt), GFP_KERNEL);
+ fc->rst_pkt = kmalloc(sizeof(SCpnt), GFP_KERNEL);
if (!fc->rst_pkt) return FAILED;
fcmd = FCP_CMND(fc->rst_pkt);
logi *l;
int status;
- l = (logi *)kzalloc(2 * sizeof(logi), GFP_KERNEL);
+ l = kzalloc(2 * sizeof(logi), GFP_KERNEL);
if (!l) return -ENOMEM;
l->code = LS_PLOGI;
memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
prli *p;
int status;
- p = (prli *)kzalloc(2 * sizeof(prli), GFP_KERNEL);
+ p = kzalloc(2 * sizeof(prli), GFP_KERNEL);
if (!p) return -ENOMEM;
p->code = LS_PRLI;
p->params[0] = 0x08002000;
This driver can also be built as a module. If so, the module
will be called k8temp.
+config SENSORS_AMS
+ tristate "Apple Motion Sensor driver"
+ depends on HWMON && PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
+ help
+ Support for the motion sensor included in PowerBooks. Includes
+ implementations for PMU and I2C.
+
+ This driver can also be built as a module. If so, the module
+ will be called ams.
+
+config SENSORS_AMS_PMU
+ bool "PMU variant"
+ depends on SENSORS_AMS && ADB_PMU
+ default y
+ help
+ PMU variant of motion sensor, found in late 2005 PowerBooks.
+
+config SENSORS_AMS_I2C
+ bool "I2C variant"
+ depends on SENSORS_AMS && I2C
+ default y
+ help
+ I2C variant of motion sensor, found in early 2005 PowerBooks and
+ iBooks.
+
config SENSORS_ASB100
tristate "Asus ASB100 Bach"
depends on HWMON && I2C && EXPERIMENTAL
will be called ds1621.
config SENSORS_F71805F
- tristate "Fintek F71805F/FG"
+ tristate "Fintek F71805F/FG and F71872F/FG"
depends on HWMON && EXPERIMENTAL
help
If you say yes here you get support for hardware monitoring
- features of the Fintek F71805F/FG chips.
+ features of the Fintek F71805F/FG and F71872F/FG Super-I/O
+ chips.
This driver can also be built as a module. If so, the module
will be called f71805f.
This driver can also be built as a module. If so, the module
will be called pc87360.
+config SENSORS_PC87427
+ tristate "National Semiconductor PC87427"
+ depends on HWMON && EXPERIMENTAL
+ help
+ If you say yes here you get access to the hardware monitoring
+ functions of the National Semiconductor PC87427 Super-I/O chip.
+ The chip has two distinct logical devices, one for fan speed
+ monitoring and control, and one for voltage and temperature
+ monitoring. Only fan speed monitoring is supported right now.
+
+ This driver can also be built as a module. If so, the module
+ will be called pc87427.
+
config SENSORS_SIS5595
tristate "Silicon Integrated Systems Corp. SiS5595"
depends on HWMON && I2C && PCI && EXPERIMENTAL
This driver can also be built as a module. If so, the module
will be called w83792d.
+config SENSORS_W83793
+ tristate "Winbond W83793"
+ depends on HWMON && I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Winbond W83793
+ hardware monitoring chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called w83793.
+
config SENSORS_W83L785TS
tristate "Winbond W83L785TS-S"
depends on HWMON && I2C && EXPERIMENTAL
This driver also provides an absolute input class device, allowing
the laptop to act as a pinball machine-esque joystick.
+ If your ThinkPad is not recognized by the driver, please update to latest
+ BIOS. This is especially the case for some R52 ThinkPads.
+
Say Y here if you have an applicable laptop and want to experience
the awesome power of hdaps.
obj-$(CONFIG_SENSORS_ASB100) += asb100.o
obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o
obj-$(CONFIG_SENSORS_W83792D) += w83792d.o
+obj-$(CONFIG_SENSORS_W83793) += w83793.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
obj-$(CONFIG_SENSORS_W83791D) += w83791d.o
obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
+obj-$(CONFIG_SENSORS_AMS) += ams/
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
+obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
--- /dev/null
+#
+# Makefile for Apple Motion Sensor driver
+#
+
+ams-y := ams-core.o ams-input.o
+ams-$(CONFIG_SENSORS_AMS_PMU) += ams-pmu.o
+ams-$(CONFIG_SENSORS_AMS_I2C) += ams-i2c.o
+obj-$(CONFIG_SENSORS_AMS) += ams.o
--- /dev/null
+/*
+ * Apple Motion Sensor driver
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/pmac_pfunc.h>
+#include <asm/of_platform.h>
+
+#include "ams.h"
+
+/* There is only one motion sensor per machine */
+struct ams ams_info;
+
+static unsigned int verbose;
+module_param(verbose, bool, 0644);
+MODULE_PARM_DESC(verbose, "Show free falls and shocks in kernel output");
+
+/* Call with ams_info.lock held! */
+void ams_sensors(s8 *x, s8 *y, s8 *z)
+{
+ u32 orient = ams_info.vflag? ams_info.orient1 : ams_info.orient2;
+
+ if (orient & 0x80)
+ /* X and Y swapped */
+ ams_info.get_xyz(y, x, z);
+ else
+ ams_info.get_xyz(x, y, z);
+
+ if (orient & 0x04)
+ *z = ~(*z);
+ if (orient & 0x02)
+ *y = ~(*y);
+ if (orient & 0x01)
+ *x = ~(*x);
+}
+
+static ssize_t ams_show_current(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s8 x, y, z;
+
+ mutex_lock(&ams_info.lock);
+ ams_sensors(&x, &y, &z);
+ mutex_unlock(&ams_info.lock);
+
+ return snprintf(buf, PAGE_SIZE, "%d %d %d\n", x, y, z);
+}
+
+static DEVICE_ATTR(current, S_IRUGO, ams_show_current, NULL);
+
+static void ams_handle_irq(void *data)
+{
+ enum ams_irq irq = *((enum ams_irq *)data);
+
+ spin_lock(&ams_info.irq_lock);
+
+ ams_info.worker_irqs |= irq;
+ schedule_work(&ams_info.worker);
+
+ spin_unlock(&ams_info.irq_lock);
+}
+
+static enum ams_irq ams_freefall_irq_data = AMS_IRQ_FREEFALL;
+static struct pmf_irq_client ams_freefall_client = {
+ .owner = THIS_MODULE,
+ .handler = ams_handle_irq,
+ .data = &ams_freefall_irq_data,
+};
+
+static enum ams_irq ams_shock_irq_data = AMS_IRQ_SHOCK;
+static struct pmf_irq_client ams_shock_client = {
+ .owner = THIS_MODULE,
+ .handler = ams_handle_irq,
+ .data = &ams_shock_irq_data,
+};
+
+/* Once hard disk parking is implemented in the kernel, this function can
+ * trigger it.
+ */
+static void ams_worker(struct work_struct *work)
+{
+ mutex_lock(&ams_info.lock);
+
+ if (ams_info.has_device) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&ams_info.irq_lock, flags);
+
+ if (ams_info.worker_irqs & AMS_IRQ_FREEFALL) {
+ if (verbose)
+ printk(KERN_INFO "ams: freefall detected!\n");
+
+ ams_info.worker_irqs &= ~AMS_IRQ_FREEFALL;
+
+ /* we must call this with interrupts enabled */
+ spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+ ams_info.clear_irq(AMS_IRQ_FREEFALL);
+ spin_lock_irqsave(&ams_info.irq_lock, flags);
+ }
+
+ if (ams_info.worker_irqs & AMS_IRQ_SHOCK) {
+ if (verbose)
+ printk(KERN_INFO "ams: shock detected!\n");
+
+ ams_info.worker_irqs &= ~AMS_IRQ_SHOCK;
+
+ /* we must call this with interrupts enabled */
+ spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+ ams_info.clear_irq(AMS_IRQ_SHOCK);
+ spin_lock_irqsave(&ams_info.irq_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+ }
+
+ mutex_unlock(&ams_info.lock);
+}
+
+/* Call with ams_info.lock held! */
+int ams_sensor_attach(void)
+{
+ int result;
+ u32 *prop;
+
+ /* Get orientation */
+ prop = (u32*)get_property(ams_info.of_node, "orientation", NULL);
+ if (!prop)
+ return -ENODEV;
+ ams_info.orient1 = *prop;
+ ams_info.orient2 = *(prop + 1);
+
+ /* Register freefall interrupt handler */
+ result = pmf_register_irq_client(ams_info.of_node,
+ "accel-int-1",
+ &ams_freefall_client);
+ if (result < 0)
+ return -ENODEV;
+
+ /* Reset saved irqs */
+ ams_info.worker_irqs = 0;
+
+ /* Register shock interrupt handler */
+ result = pmf_register_irq_client(ams_info.of_node,
+ "accel-int-2",
+ &ams_shock_client);
+ if (result < 0)
+ goto release_freefall;
+
+ /* Create device */
+ ams_info.of_dev = of_platform_device_create(ams_info.of_node, "ams", NULL);
+ if (!ams_info.of_dev) {
+ result = -ENODEV;
+ goto release_shock;
+ }
+
+ /* Create attributes */
+ result = device_create_file(&ams_info.of_dev->dev, &dev_attr_current);
+ if (result)
+ goto release_of;
+
+ ams_info.vflag = !!(ams_info.get_vendor() & 0x10);
+
+ /* Init input device */
+ result = ams_input_init();
+ if (result)
+ goto release_device_file;
+
+ return result;
+release_device_file:
+ device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+release_of:
+ of_device_unregister(ams_info.of_dev);
+release_shock:
+ pmf_unregister_irq_client(&ams_shock_client);
+release_freefall:
+ pmf_unregister_irq_client(&ams_freefall_client);
+ return result;
+}
+
+int __init ams_init(void)
+{
+ struct device_node *np;
+
+ spin_lock_init(&ams_info.irq_lock);
+ mutex_init(&ams_info.lock);
+ INIT_WORK(&ams_info.worker, ams_worker);
+
+#ifdef CONFIG_SENSORS_AMS_I2C
+ np = of_find_node_by_name(NULL, "accelerometer");
+ if (np && device_is_compatible(np, "AAPL,accelerometer_1"))
+ /* Found I2C motion sensor */
+ return ams_i2c_init(np);
+#endif
+
+#ifdef CONFIG_SENSORS_AMS_PMU
+ np = of_find_node_by_name(NULL, "sms");
+ if (np && device_is_compatible(np, "sms"))
+ /* Found PMU motion sensor */
+ return ams_pmu_init(np);
+#endif
+
+ printk(KERN_ERR "ams: No motion sensor found.\n");
+
+ return -ENODEV;
+}
+
+void ams_exit(void)
+{
+ mutex_lock(&ams_info.lock);
+
+ if (ams_info.has_device) {
+ /* Remove input device */
+ ams_input_exit();
+
+ /* Shut down implementation */
+ ams_info.exit();
+
+ /* Flush interrupt worker
+ *
+ * We do this after ams_info.exit(), because an interrupt might
+ * have arrived before disabling them.
+ */
+ flush_scheduled_work();
+
+ /* Remove attributes */
+ device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+
+ /* Remove device */
+ of_device_unregister(ams_info.of_dev);
+
+ /* Remove handler */
+ pmf_unregister_irq_client(&ams_shock_client);
+ pmf_unregister_irq_client(&ams_freefall_client);
+ }
+
+ mutex_unlock(&ams_info.lock);
+}
+
+MODULE_AUTHOR("Stelian Pop, Michael Hanselmann");
+MODULE_DESCRIPTION("Apple Motion Sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(ams_init);
+module_exit(ams_exit);
--- /dev/null
+/*
+ * Apple Motion Sensor driver (I2C variant)
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * Clean room implementation based on the reverse engineered Mac OS X driver by
+ * Johannes Berg <johannes@sipsolutions.net>, documentation available at
+ * http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include "ams.h"
+
+/* AMS registers */
+#define AMS_COMMAND 0x00 /* command register */
+#define AMS_STATUS 0x01 /* status register */
+#define AMS_CTRL1 0x02 /* read control 1 (number of values) */
+#define AMS_CTRL2 0x03 /* read control 2 (offset?) */
+#define AMS_CTRL3 0x04 /* read control 3 (size of each value?) */
+#define AMS_DATA1 0x05 /* read data 1 */
+#define AMS_DATA2 0x06 /* read data 2 */
+#define AMS_DATA3 0x07 /* read data 3 */
+#define AMS_DATA4 0x08 /* read data 4 */
+#define AMS_DATAX 0x20 /* data X */
+#define AMS_DATAY 0x21 /* data Y */
+#define AMS_DATAZ 0x22 /* data Z */
+#define AMS_FREEFALL 0x24 /* freefall int control */
+#define AMS_SHOCK 0x25 /* shock int control */
+#define AMS_SENSLOW 0x26 /* sensitivity low limit */
+#define AMS_SENSHIGH 0x27 /* sensitivity high limit */
+#define AMS_CTRLX 0x28 /* control X */
+#define AMS_CTRLY 0x29 /* control Y */
+#define AMS_CTRLZ 0x2A /* control Z */
+#define AMS_UNKNOWN1 0x2B /* unknown 1 */
+#define AMS_UNKNOWN2 0x2C /* unknown 2 */
+#define AMS_UNKNOWN3 0x2D /* unknown 3 */
+#define AMS_VENDOR 0x2E /* vendor */
+
+/* AMS commands - use with the AMS_COMMAND register */
+enum ams_i2c_cmd {
+ AMS_CMD_NOOP = 0,
+ AMS_CMD_VERSION,
+ AMS_CMD_READMEM,
+ AMS_CMD_WRITEMEM,
+ AMS_CMD_ERASEMEM,
+ AMS_CMD_READEE,
+ AMS_CMD_WRITEEE,
+ AMS_CMD_RESET,
+ AMS_CMD_START,
+};
+
+static int ams_i2c_attach(struct i2c_adapter *adapter);
+static int ams_i2c_detach(struct i2c_adapter *adapter);
+
+static struct i2c_driver ams_i2c_driver = {
+ .driver = {
+ .name = "ams",
+ .owner = THIS_MODULE,
+ },
+ .attach_adapter = ams_i2c_attach,
+ .detach_adapter = ams_i2c_detach,
+};
+
+static s32 ams_i2c_read(u8 reg)
+{
+ return i2c_smbus_read_byte_data(&ams_info.i2c_client, reg);
+}
+
+static int ams_i2c_write(u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(&ams_info.i2c_client, reg, value);
+}
+
+static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
+{
+ s32 result;
+ int remaining = HZ / 20;
+
+ ams_i2c_write(AMS_COMMAND, cmd);
+ mdelay(5);
+
+ while (remaining) {
+ result = ams_i2c_read(AMS_COMMAND);
+ if (result == 0 || result & 0x80)
+ return 0;
+
+ remaining = schedule_timeout(remaining);
+ }
+
+ return -1;
+}
+
+static void ams_i2c_set_irq(enum ams_irq reg, char enable)
+{
+ if (reg & AMS_IRQ_FREEFALL) {
+ u8 val = ams_i2c_read(AMS_CTRLX);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_i2c_write(AMS_CTRLX, val);
+ }
+
+ if (reg & AMS_IRQ_SHOCK) {
+ u8 val = ams_i2c_read(AMS_CTRLY);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_i2c_write(AMS_CTRLY, val);
+ }
+
+ if (reg & AMS_IRQ_GLOBAL) {
+ u8 val = ams_i2c_read(AMS_CTRLZ);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_i2c_write(AMS_CTRLZ, val);
+ }
+}
+
+static void ams_i2c_clear_irq(enum ams_irq reg)
+{
+ if (reg & AMS_IRQ_FREEFALL)
+ ams_i2c_write(AMS_FREEFALL, 0);
+
+ if (reg & AMS_IRQ_SHOCK)
+ ams_i2c_write(AMS_SHOCK, 0);
+}
+
+static u8 ams_i2c_get_vendor(void)
+{
+ return ams_i2c_read(AMS_VENDOR);
+}
+
+static void ams_i2c_get_xyz(s8 *x, s8 *y, s8 *z)
+{
+ *x = ams_i2c_read(AMS_DATAX);
+ *y = ams_i2c_read(AMS_DATAY);
+ *z = ams_i2c_read(AMS_DATAZ);
+}
+
+static int ams_i2c_attach(struct i2c_adapter *adapter)
+{
+ unsigned long bus;
+ int vmaj, vmin;
+ int result;
+
+ /* There can be only one */
+ if (unlikely(ams_info.has_device))
+ return -ENODEV;
+
+ if (strncmp(adapter->name, "uni-n", 5))
+ return -ENODEV;
+
+ bus = simple_strtoul(adapter->name + 6, NULL, 10);
+ if (bus != ams_info.i2c_bus)
+ return -ENODEV;
+
+ ams_info.i2c_client.addr = ams_info.i2c_address;
+ ams_info.i2c_client.adapter = adapter;
+ ams_info.i2c_client.driver = &ams_i2c_driver;
+ strcpy(ams_info.i2c_client.name, "Apple Motion Sensor");
+
+ if (ams_i2c_cmd(AMS_CMD_RESET)) {
+ printk(KERN_INFO "ams: Failed to reset the device\n");
+ return -ENODEV;
+ }
+
+ if (ams_i2c_cmd(AMS_CMD_START)) {
+ printk(KERN_INFO "ams: Failed to start the device\n");
+ return -ENODEV;
+ }
+
+ /* get version/vendor information */
+ ams_i2c_write(AMS_CTRL1, 0x02);
+ ams_i2c_write(AMS_CTRL2, 0x85);
+ ams_i2c_write(AMS_CTRL3, 0x01);
+
+ ams_i2c_cmd(AMS_CMD_READMEM);
+
+ vmaj = ams_i2c_read(AMS_DATA1);
+ vmin = ams_i2c_read(AMS_DATA2);
+ if (vmaj != 1 || vmin != 52) {
+ printk(KERN_INFO "ams: Incorrect device version (%d.%d)\n",
+ vmaj, vmin);
+ return -ENODEV;
+ }
+
+ ams_i2c_cmd(AMS_CMD_VERSION);
+
+ vmaj = ams_i2c_read(AMS_DATA1);
+ vmin = ams_i2c_read(AMS_DATA2);
+ if (vmaj != 0 || vmin != 1) {
+ printk(KERN_INFO "ams: Incorrect firmware version (%d.%d)\n",
+ vmaj, vmin);
+ return -ENODEV;
+ }
+
+ /* Disable interrupts */
+ ams_i2c_set_irq(AMS_IRQ_ALL, 0);
+
+ result = ams_sensor_attach();
+ if (result < 0)
+ return result;
+
+ /* Set default values */
+ ams_i2c_write(AMS_SENSLOW, 0x15);
+ ams_i2c_write(AMS_SENSHIGH, 0x60);
+ ams_i2c_write(AMS_CTRLX, 0x08);
+ ams_i2c_write(AMS_CTRLY, 0x0F);
+ ams_i2c_write(AMS_CTRLZ, 0x4F);
+ ams_i2c_write(AMS_UNKNOWN1, 0x14);
+
+ /* Clear interrupts */
+ ams_i2c_clear_irq(AMS_IRQ_ALL);
+
+ ams_info.has_device = 1;
+
+ /* Enable interrupts */
+ ams_i2c_set_irq(AMS_IRQ_ALL, 1);
+
+ printk(KERN_INFO "ams: Found I2C based motion sensor\n");
+
+ return 0;
+}
+
+static int ams_i2c_detach(struct i2c_adapter *adapter)
+{
+ if (ams_info.has_device) {
+ /* Disable interrupts */
+ ams_i2c_set_irq(AMS_IRQ_ALL, 0);
+
+ /* Clear interrupts */
+ ams_i2c_clear_irq(AMS_IRQ_ALL);
+
+ printk(KERN_INFO "ams: Unloading\n");
+
+ ams_info.has_device = 0;
+ }
+
+ return 0;
+}
+
+static void ams_i2c_exit(void)
+{
+ i2c_del_driver(&ams_i2c_driver);
+}
+
+int __init ams_i2c_init(struct device_node *np)
+{
+ char *tmp_bus;
+ int result;
+ u32 *prop;
+
+ mutex_lock(&ams_info.lock);
+
+ /* Set implementation stuff */
+ ams_info.of_node = np;
+ ams_info.exit = ams_i2c_exit;
+ ams_info.get_vendor = ams_i2c_get_vendor;
+ ams_info.get_xyz = ams_i2c_get_xyz;
+ ams_info.clear_irq = ams_i2c_clear_irq;
+ ams_info.bustype = BUS_I2C;
+
+ /* look for bus either using "reg" or by path */
+ prop = (u32*)get_property(ams_info.of_node, "reg", NULL);
+ if (!prop) {
+ result = -ENODEV;
+
+ goto exit;
+ }
+
+ tmp_bus = strstr(ams_info.of_node->full_name, "/i2c-bus@");
+ if (tmp_bus)
+ ams_info.i2c_bus = *(tmp_bus + 9) - '0';
+ else
+ ams_info.i2c_bus = ((*prop) >> 8) & 0x0f;
+ ams_info.i2c_address = ((*prop) & 0xff) >> 1;
+
+ result = i2c_add_driver(&ams_i2c_driver);
+
+exit:
+ mutex_unlock(&ams_info.lock);
+
+ return result;
+}
--- /dev/null
+/*
+ * Apple Motion Sensor driver (joystick emulation)
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include "ams.h"
+
+static unsigned int joystick;
+module_param(joystick, bool, 0644);
+MODULE_PARM_DESC(joystick, "Enable the input class device on module load");
+
+static unsigned int invert;
+module_param(invert, bool, 0644);
+MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
+
+static int ams_input_kthread(void *data)
+{
+ s8 x, y, z;
+
+ while (!kthread_should_stop()) {
+ mutex_lock(&ams_info.lock);
+
+ ams_sensors(&x, &y, &z);
+
+ x -= ams_info.xcalib;
+ y -= ams_info.ycalib;
+ z -= ams_info.zcalib;
+
+ input_report_abs(ams_info.idev, ABS_X, invert ? -x : x);
+ input_report_abs(ams_info.idev, ABS_Y, invert ? -y : y);
+ input_report_abs(ams_info.idev, ABS_Z, z);
+
+ input_sync(ams_info.idev);
+
+ mutex_unlock(&ams_info.lock);
+
+ msleep(25);
+ }
+
+ return 0;
+}
+
+static int ams_input_open(struct input_dev *dev)
+{
+ ams_info.kthread = kthread_run(ams_input_kthread, NULL, "kams");
+ return IS_ERR(ams_info.kthread) ? PTR_ERR(ams_info.kthread) : 0;
+}
+
+static void ams_input_close(struct input_dev *dev)
+{
+ kthread_stop(ams_info.kthread);
+}
+
+/* Call with ams_info.lock held! */
+static void ams_input_enable(void)
+{
+ s8 x, y, z;
+
+ if (ams_info.idev)
+ return;
+
+ ams_sensors(&x, &y, &z);
+ ams_info.xcalib = x;
+ ams_info.ycalib = y;
+ ams_info.zcalib = z;
+
+ ams_info.idev = input_allocate_device();
+ if (!ams_info.idev)
+ return;
+
+ ams_info.idev->name = "Apple Motion Sensor";
+ ams_info.idev->id.bustype = ams_info.bustype;
+ ams_info.idev->id.vendor = 0;
+ ams_info.idev->open = ams_input_open;
+ ams_info.idev->close = ams_input_close;
+ ams_info.idev->cdev.dev = &ams_info.of_dev->dev;
+
+ input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0);
+ input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0);
+ input_set_abs_params(ams_info.idev, ABS_Z, -50, 50, 3, 0);
+
+ set_bit(EV_ABS, ams_info.idev->evbit);
+ set_bit(EV_KEY, ams_info.idev->evbit);
+ set_bit(BTN_TOUCH, ams_info.idev->keybit);
+
+ if (input_register_device(ams_info.idev)) {
+ input_free_device(ams_info.idev);
+ ams_info.idev = NULL;
+ return;
+ }
+}
+
+/* Call with ams_info.lock held! */
+static void ams_input_disable(void)
+{
+ if (ams_info.idev) {
+ input_unregister_device(ams_info.idev);
+ ams_info.idev = NULL;
+ }
+}
+
+static ssize_t ams_input_show_joystick(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", joystick);
+}
+
+static ssize_t ams_input_store_joystick(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ if (sscanf(buf, "%d\n", &joystick) != 1)
+ return -EINVAL;
+
+ mutex_lock(&ams_info.lock);
+
+ if (joystick)
+ ams_input_enable();
+ else
+ ams_input_disable();
+
+ mutex_unlock(&ams_info.lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(joystick, S_IRUGO | S_IWUSR,
+ ams_input_show_joystick, ams_input_store_joystick);
+
+/* Call with ams_info.lock held! */
+int ams_input_init(void)
+{
+ int result;
+
+ result = device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick);
+
+ if (!result && joystick)
+ ams_input_enable();
+ return result;
+}
+
+/* Call with ams_info.lock held! */
+void ams_input_exit()
+{
+ ams_input_disable();
+ device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick);
+}
--- /dev/null
+/*
+ * Apple Motion Sensor driver (PMU variant)
+ *
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+#include "ams.h"
+
+/* Attitude */
+#define AMS_X 0x00
+#define AMS_Y 0x01
+#define AMS_Z 0x02
+
+/* Not exactly known, maybe chip vendor */
+#define AMS_VENDOR 0x03
+
+/* Freefall registers */
+#define AMS_FF_CLEAR 0x04
+#define AMS_FF_ENABLE 0x05
+#define AMS_FF_LOW_LIMIT 0x06
+#define AMS_FF_DEBOUNCE 0x07
+
+/* Shock registers */
+#define AMS_SHOCK_CLEAR 0x08
+#define AMS_SHOCK_ENABLE 0x09
+#define AMS_SHOCK_HIGH_LIMIT 0x0a
+#define AMS_SHOCK_DEBOUNCE 0x0b
+
+/* Global interrupt and power control register */
+#define AMS_CONTROL 0x0c
+
+static u8 ams_pmu_cmd;
+
+static void ams_pmu_req_complete(struct adb_request *req)
+{
+ complete((struct completion *)req->arg);
+}
+
+/* Only call this function from task context */
+static void ams_pmu_set_register(u8 reg, u8 value)
+{
+ static struct adb_request req;
+ DECLARE_COMPLETION(req_complete);
+
+ req.arg = &req_complete;
+ if (pmu_request(&req, ams_pmu_req_complete, 4, ams_pmu_cmd, 0x00, reg, value))
+ return;
+
+ wait_for_completion(&req_complete);
+}
+
+/* Only call this function from task context */
+static u8 ams_pmu_get_register(u8 reg)
+{
+ static struct adb_request req;
+ DECLARE_COMPLETION(req_complete);
+
+ req.arg = &req_complete;
+ if (pmu_request(&req, ams_pmu_req_complete, 3, ams_pmu_cmd, 0x01, reg))
+ return 0;
+
+ wait_for_completion(&req_complete);
+
+ if (req.reply_len > 0)
+ return req.reply[0];
+ else
+ return 0;
+}
+
+/* Enables or disables the specified interrupts */
+static void ams_pmu_set_irq(enum ams_irq reg, char enable)
+{
+ if (reg & AMS_IRQ_FREEFALL) {
+ u8 val = ams_pmu_get_register(AMS_FF_ENABLE);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_pmu_set_register(AMS_FF_ENABLE, val);
+ }
+
+ if (reg & AMS_IRQ_SHOCK) {
+ u8 val = ams_pmu_get_register(AMS_SHOCK_ENABLE);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_pmu_set_register(AMS_SHOCK_ENABLE, val);
+ }
+
+ if (reg & AMS_IRQ_GLOBAL) {
+ u8 val = ams_pmu_get_register(AMS_CONTROL);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_pmu_set_register(AMS_CONTROL, val);
+ }
+}
+
+static void ams_pmu_clear_irq(enum ams_irq reg)
+{
+ if (reg & AMS_IRQ_FREEFALL)
+ ams_pmu_set_register(AMS_FF_CLEAR, 0x00);
+
+ if (reg & AMS_IRQ_SHOCK)
+ ams_pmu_set_register(AMS_SHOCK_CLEAR, 0x00);
+}
+
+static u8 ams_pmu_get_vendor(void)
+{
+ return ams_pmu_get_register(AMS_VENDOR);
+}
+
+static void ams_pmu_get_xyz(s8 *x, s8 *y, s8 *z)
+{
+ *x = ams_pmu_get_register(AMS_X);
+ *y = ams_pmu_get_register(AMS_Y);
+ *z = ams_pmu_get_register(AMS_Z);
+}
+
+static void ams_pmu_exit(void)
+{
+ /* Disable interrupts */
+ ams_pmu_set_irq(AMS_IRQ_ALL, 0);
+
+ /* Clear interrupts */
+ ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+ ams_info.has_device = 0;
+
+ printk(KERN_INFO "ams: Unloading\n");
+}
+
+int __init ams_pmu_init(struct device_node *np)
+{
+ u32 *prop;
+ int result;
+
+ mutex_lock(&ams_info.lock);
+
+ /* Set implementation stuff */
+ ams_info.of_node = np;
+ ams_info.exit = ams_pmu_exit;
+ ams_info.get_vendor = ams_pmu_get_vendor;
+ ams_info.get_xyz = ams_pmu_get_xyz;
+ ams_info.clear_irq = ams_pmu_clear_irq;
+ ams_info.bustype = BUS_HOST;
+
+ /* Get PMU command, should be 0x4e, but we can never know */
+ prop = (u32*)get_property(ams_info.of_node, "reg", NULL);
+ if (!prop) {
+ result = -ENODEV;
+ goto exit;
+ }
+ ams_pmu_cmd = ((*prop) >> 8) & 0xff;
+
+ /* Disable interrupts */
+ ams_pmu_set_irq(AMS_IRQ_ALL, 0);
+
+ /* Clear interrupts */
+ ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+ result = ams_sensor_attach();
+ if (result < 0)
+ goto exit;
+
+ /* Set default values */
+ ams_pmu_set_register(AMS_FF_LOW_LIMIT, 0x15);
+ ams_pmu_set_register(AMS_FF_ENABLE, 0x08);
+ ams_pmu_set_register(AMS_FF_DEBOUNCE, 0x14);
+
+ ams_pmu_set_register(AMS_SHOCK_HIGH_LIMIT, 0x60);
+ ams_pmu_set_register(AMS_SHOCK_ENABLE, 0x0f);
+ ams_pmu_set_register(AMS_SHOCK_DEBOUNCE, 0x14);
+
+ ams_pmu_set_register(AMS_CONTROL, 0x4f);
+
+ /* Clear interrupts */
+ ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+ ams_info.has_device = 1;
+
+ /* Enable interrupts */
+ ams_pmu_set_irq(AMS_IRQ_ALL, 1);
+
+ printk(KERN_INFO "ams: Found PMU based motion sensor\n");
+
+ result = 0;
+
+exit:
+ mutex_unlock(&ams_info.lock);
+
+ return result;
+}
--- /dev/null
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <asm/of_device.h>
+
+enum ams_irq {
+ AMS_IRQ_FREEFALL = 0x01,
+ AMS_IRQ_SHOCK = 0x02,
+ AMS_IRQ_GLOBAL = 0x04,
+ AMS_IRQ_ALL =
+ AMS_IRQ_FREEFALL |
+ AMS_IRQ_SHOCK |
+ AMS_IRQ_GLOBAL,
+};
+
+struct ams {
+ /* Locks */
+ spinlock_t irq_lock;
+ struct mutex lock;
+
+ /* General properties */
+ struct device_node *of_node;
+ struct of_device *of_dev;
+ char has_device;
+ char vflag;
+ u32 orient1;
+ u32 orient2;
+
+ /* Interrupt worker */
+ struct work_struct worker;
+ u8 worker_irqs;
+
+ /* Implementation
+ *
+ * Only call these functions with the main lock held.
+ */
+ void (*exit)(void);
+
+ void (*get_xyz)(s8 *x, s8 *y, s8 *z);
+ u8 (*get_vendor)(void);
+
+ void (*clear_irq)(enum ams_irq reg);
+
+#ifdef CONFIG_SENSORS_AMS_I2C
+ /* I2C properties */
+ int i2c_bus;
+ int i2c_address;
+ struct i2c_client i2c_client;
+#endif
+
+ /* Joystick emulation */
+ struct task_struct *kthread;
+ struct input_dev *idev;
+ __u16 bustype;
+
+ /* calibrated null values */
+ int xcalib, ycalib, zcalib;
+};
+
+extern struct ams ams_info;
+
+extern void ams_sensors(s8 *x, s8 *y, s8 *z);
+extern int ams_sensor_attach(void);
+
+extern int ams_pmu_init(struct device_node *np);
+extern int ams_i2c_init(struct device_node *np);
+
+extern int ams_input_init(void);
+extern void ams_input_exit(void);
/*
- * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
- * hardware monitoring features
+ * f71805f.c - driver for the Fintek F71805F/FG and F71872F/FG Super-I/O
+ * chips integrated hardware monitoring features
* Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.org>
*
* The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
* complete hardware monitoring features: voltage, fan and temperature
* sensors, and manual and automatic fan speed control.
*
+ * The F71872F/FG is almost the same, with two more voltages monitored,
+ * and 6 VID inputs.
+ *
* 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
static struct platform_device *pdev;
#define DRVNAME "f71805f"
+enum kinds { f71805f, f71872f };
/*
* Super-I/O constants and functions
#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
#define SIO_REG_DEVREV 0x22 /* Device revision */
#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
+#define SIO_REG_FNSEL1 0x29 /* Multi Function Select 1 (F71872F) */
#define SIO_REG_ENABLE 0x30 /* Logical device enable */
#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
#define SIO_FINTEK_ID 0x1934
#define SIO_F71805F_ID 0x0406
+#define SIO_F71872F_ID 0x0341
static inline int
superio_inb(int base, int reg)
* ISA constants
*/
-#define REGION_LENGTH 2
-#define ADDR_REG_OFFSET 0
-#define DATA_REG_OFFSET 1
+#define REGION_LENGTH 8
+#define ADDR_REG_OFFSET 5
+#define DATA_REG_OFFSET 6
/*
* Registers
*/
-/* in nr from 0 to 8 (8-bit values) */
+/* in nr from 0 to 10 (8-bit values) */
#define F71805F_REG_IN(nr) (0x10 + (nr))
-#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr))
-#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr))
+#define F71805F_REG_IN_HIGH(nr) ((nr) < 10 ? 0x40 + 2 * (nr) : 0x2E)
+#define F71805F_REG_IN_LOW(nr) ((nr) < 10 ? 0x41 + 2 * (nr) : 0x2F)
/* fan nr from 0 to 2 (12-bit values, two registers) */
#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
+#define F71805F_REG_FAN_TARGET(nr) (0x69 + 16 * (nr))
#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
+#define F71805F_REG_PWM_FREQ(nr) (0x63 + 16 * (nr))
+#define F71805F_REG_PWM_DUTY(nr) (0x6B + 16 * (nr))
/* temp nr from 0 to 2 (8-bit values) */
#define F71805F_REG_TEMP(nr) (0x1B + (nr))
#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
/* status nr from 0 to 2 */
#define F71805F_REG_STATUS(nr) (0x36 + (nr))
+/* individual register bits */
+#define FAN_CTRL_DC_MODE 0x10
+#define FAN_CTRL_LATCH_FULL 0x08
+#define FAN_CTRL_MODE_MASK 0x03
+#define FAN_CTRL_MODE_SPEED 0x00
+#define FAN_CTRL_MODE_TEMPERATURE 0x01
+#define FAN_CTRL_MODE_MANUAL 0x02
+
/*
* Data structures and manipulation thereof
*/
unsigned long last_limits; /* In jiffies */
/* Register values */
- u8 in[9];
- u8 in_high[9];
- u8 in_low[9];
+ u8 in[11];
+ u8 in_high[11];
+ u8 in_low[11];
+ u16 has_in;
u16 fan[3];
u16 fan_low[3];
- u8 fan_enabled; /* Read once at init time */
+ u16 fan_target[3];
+ u8 fan_ctrl[3];
+ u8 pwm[3];
+ u8 pwm_freq[3];
u8 temp[3];
u8 temp_high[3];
u8 temp_hyst[3];
unsigned long alarms;
};
+struct f71805f_sio_data {
+ enum kinds kind;
+ u8 fnsel1;
+};
+
static inline long in_from_reg(u8 reg)
{
return (reg * 8);
return (1500000 / rpm);
}
+static inline unsigned long pwm_freq_from_reg(u8 reg)
+{
+ unsigned long clock = (reg & 0x80) ? 48000000UL : 1000000UL;
+
+ reg &= 0x7f;
+ if (reg == 0)
+ reg++;
+ return clock / (reg << 8);
+}
+
+static inline u8 pwm_freq_to_reg(unsigned long val)
+{
+ if (val >= 187500) /* The highest we can do */
+ return 0x80;
+ if (val >= 1475) /* Use 48 MHz clock */
+ return 0x80 | (48000000UL / (val << 8));
+ if (val < 31) /* The lowest we can do */
+ return 0x7f;
+ else /* Use 1 MHz clock */
+ return 1000000UL / (val << 8);
+}
+
+static inline int pwm_mode_from_reg(u8 reg)
+{
+ return !(reg & FAN_CTRL_DC_MODE);
+}
+
static inline long temp_from_reg(u8 reg)
{
return (reg * 1000);
/* Limit registers cache is refreshed after 60 seconds */
if (time_after(jiffies, data->last_updated + 60 * HZ)
|| !data->valid) {
- for (nr = 0; nr < 9; nr++) {
+ for (nr = 0; nr < 11; nr++) {
+ if (!(data->has_in & (1 << nr)))
+ continue;
data->in_high[nr] = f71805f_read8(data,
F71805F_REG_IN_HIGH(nr));
data->in_low[nr] = f71805f_read8(data,
F71805F_REG_IN_LOW(nr));
}
for (nr = 0; nr < 3; nr++) {
- if (data->fan_enabled & (1 << nr))
- data->fan_low[nr] = f71805f_read16(data,
- F71805F_REG_FAN_LOW(nr));
+ data->fan_low[nr] = f71805f_read16(data,
+ F71805F_REG_FAN_LOW(nr));
+ data->fan_target[nr] = f71805f_read16(data,
+ F71805F_REG_FAN_TARGET(nr));
+ data->pwm_freq[nr] = f71805f_read8(data,
+ F71805F_REG_PWM_FREQ(nr));
}
for (nr = 0; nr < 3; nr++) {
data->temp_high[nr] = f71805f_read8(data,
/* Measurement registers cache is refreshed after 1 second */
if (time_after(jiffies, data->last_updated + HZ)
|| !data->valid) {
- for (nr = 0; nr < 9; nr++) {
+ for (nr = 0; nr < 11; nr++) {
+ if (!(data->has_in & (1 << nr)))
+ continue;
data->in[nr] = f71805f_read8(data,
F71805F_REG_IN(nr));
}
for (nr = 0; nr < 3; nr++) {
- if (data->fan_enabled & (1 << nr))
- data->fan[nr] = f71805f_read16(data,
- F71805F_REG_FAN(nr));
+ data->fan[nr] = f71805f_read16(data,
+ F71805F_REG_FAN(nr));
+ data->fan_ctrl[nr] = f71805f_read8(data,
+ F71805F_REG_FAN_CTRL(nr));
+ data->pwm[nr] = f71805f_read8(data,
+ F71805F_REG_PWM_DUTY(nr));
}
for (nr = 0; nr < 3; nr++) {
data->temp[nr] = f71805f_read8(data,
char *buf)
{
struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
- return sprintf(buf, "%ld\n", in0_from_reg(data->in[0]));
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in[nr]));
}
static ssize_t show_in0_max(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
- return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0]));
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[nr]));
}
static ssize_t show_in0_min(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
- return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0]));
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[nr]));
}
static ssize_t set_in0_max(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
mutex_lock(&data->update_lock);
- data->in_high[0] = in0_to_reg(val);
- f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
+ data->in_high[nr] = in0_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
mutex_unlock(&data->update_lock);
return count;
*devattr, const char *buf, size_t count)
{
struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
mutex_lock(&data->update_lock);
- data->in_low[0] = in0_to_reg(val);
- f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
+ data->in_low[nr] = in0_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
mutex_unlock(&data->update_lock);
return count;
return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
}
+static ssize_t show_fan_target(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr]));
+}
+
static ssize_t set_fan_min(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
return count;
}
+static ssize_t set_fan_target(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->fan_target[nr] = fan_to_reg(val);
+ f71805f_write16(data, F71805F_REG_FAN_TARGET(nr),
+ data->fan_target[nr]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%d\n", (int)data->pwm[nr]);
+}
+
+static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ int mode;
+
+ switch (data->fan_ctrl[nr] & FAN_CTRL_MODE_MASK) {
+ case FAN_CTRL_MODE_SPEED:
+ mode = 3;
+ break;
+ case FAN_CTRL_MODE_TEMPERATURE:
+ mode = 2;
+ break;
+ default: /* MANUAL */
+ mode = 1;
+ }
+
+ return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t show_pwm_freq(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%lu\n", pwm_freq_from_reg(data->pwm_freq[nr]));
+}
+
+static ssize_t show_pwm_mode(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%d\n", pwm_mode_from_reg(data->fan_ctrl[nr]));
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ if (val > 255)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->pwm[nr] = val;
+ f71805f_write8(data, F71805F_REG_PWM_DUTY(nr), data->pwm[nr]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static struct attribute *f71805f_attr_pwm[];
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ u8 reg;
+
+ if (val < 1 || val > 3)
+ return -EINVAL;
+
+ if (val > 1) { /* Automatic mode, user can't set PWM value */
+ if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
+ S_IRUGO))
+ dev_dbg(dev, "chmod -w pwm%d failed\n", nr + 1);
+ }
+
+ mutex_lock(&data->update_lock);
+ reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(nr))
+ & ~FAN_CTRL_MODE_MASK;
+ switch (val) {
+ case 1:
+ reg |= FAN_CTRL_MODE_MANUAL;
+ break;
+ case 2:
+ reg |= FAN_CTRL_MODE_TEMPERATURE;
+ break;
+ case 3:
+ reg |= FAN_CTRL_MODE_SPEED;
+ break;
+ }
+ data->fan_ctrl[nr] = reg;
+ f71805f_write8(data, F71805F_REG_FAN_CTRL(nr), reg);
+ mutex_unlock(&data->update_lock);
+
+ if (val == 1) { /* Manual mode, user can set PWM value */
+ if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
+ S_IRUGO | S_IWUSR))
+ dev_dbg(dev, "chmod +w pwm%d failed\n", nr + 1);
+ }
+
+ return count;
+}
+
+static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->pwm_freq[nr] = pwm_freq_to_reg(val);
+ f71805f_write8(data, F71805F_REG_PWM_FREQ(nr), data->pwm_freq[nr]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
char *buf)
{
{
struct f71805f_data *data = f71805f_update_device(dev);
- return sprintf(buf, "%lu\n", data->alarms & 0x1ff);
+ return sprintf(buf, "%lu\n", data->alarms & 0x7ff);
}
static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
return sprintf(buf, "%s\n", data->name);
}
-static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
-static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
-static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0);
+static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR,
+ show_in0_max, set_in0_max, 0);
+static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR,
+ show_in0_min, set_in0_min, 0);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 1);
show_in_max, set_in_max, 8);
static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 8);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in0, NULL, 9);
+static SENSOR_DEVICE_ATTR(in9_max, S_IRUGO | S_IWUSR,
+ show_in0_max, set_in0_max, 9);
+static SENSOR_DEVICE_ATTR(in9_min, S_IRUGO | S_IWUSR,
+ show_in0_min, set_in0_min, 9);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in0, NULL, 10);
+static SENSOR_DEVICE_ATTR(in10_max, S_IRUGO | S_IWUSR,
+ show_in0_max, set_in0_max, 10);
+static SENSOR_DEVICE_ATTR(in10_min, S_IRUGO | S_IWUSR,
+ show_in0_min, set_in0_min, 10);
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR,
+ show_fan_target, set_fan_target, 0);
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR,
+ show_fan_target, set_fan_target, 1);
static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR,
+ show_fan_target, set_fan_target, 2);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
show_temp_hyst, set_temp_hyst, 2);
static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
+/* pwm (value) files are created read-only, write permission is
+ then added or removed dynamically as needed */
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+ show_pwm_enable, set_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR,
+ show_pwm_freq, set_pwm_freq, 0);
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
+ show_pwm_enable, set_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO | S_IWUSR,
+ show_pwm_freq, set_pwm_freq, 1);
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO, show_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
+ show_pwm_enable, set_pwm_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR,
+ show_pwm_freq, set_pwm_freq, 2);
+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
+
static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static struct attribute *f71805f_attributes[] = {
- &dev_attr_in0_input.attr,
- &dev_attr_in0_max.attr,
- &dev_attr_in0_min.attr,
+ &sensor_dev_attr_in0_input.dev_attr.attr,
+ &sensor_dev_attr_in0_max.dev_attr.attr,
+ &sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in1_max.dev_attr.attr,
&sensor_dev_attr_in1_min.dev_attr.attr,
&sensor_dev_attr_in3_input.dev_attr.attr,
&sensor_dev_attr_in3_max.dev_attr.attr,
&sensor_dev_attr_in3_min.dev_attr.attr,
- &sensor_dev_attr_in4_input.dev_attr.attr,
- &sensor_dev_attr_in4_max.dev_attr.attr,
- &sensor_dev_attr_in4_min.dev_attr.attr,
&sensor_dev_attr_in5_input.dev_attr.attr,
&sensor_dev_attr_in5_max.dev_attr.attr,
&sensor_dev_attr_in5_min.dev_attr.attr,
&sensor_dev_attr_in7_input.dev_attr.attr,
&sensor_dev_attr_in7_max.dev_attr.attr,
&sensor_dev_attr_in7_min.dev_attr.attr,
- &sensor_dev_attr_in8_input.dev_attr.attr,
- &sensor_dev_attr_in8_max.dev_attr.attr,
- &sensor_dev_attr_in8_min.dev_attr.attr,
+
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_min.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan1_target.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_min.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan2_target.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_min.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan3_target.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm1_mode.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2_mode.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3_mode.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_in1_alarm.dev_attr.attr,
&sensor_dev_attr_in2_alarm.dev_attr.attr,
&sensor_dev_attr_in3_alarm.dev_attr.attr,
- &sensor_dev_attr_in4_alarm.dev_attr.attr,
&sensor_dev_attr_in5_alarm.dev_attr.attr,
&sensor_dev_attr_in6_alarm.dev_attr.attr,
&sensor_dev_attr_in7_alarm.dev_attr.attr,
- &sensor_dev_attr_in8_alarm.dev_attr.attr,
&dev_attr_alarms_in.attr,
&sensor_dev_attr_temp1_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_alarm.dev_attr.attr,
.attrs = f71805f_attributes,
};
-static struct attribute *f71805f_attributes_fan[3][4] = {
+static struct attribute *f71805f_attributes_optin[4][5] = {
{
- &sensor_dev_attr_fan1_input.dev_attr.attr,
- &sensor_dev_attr_fan1_min.dev_attr.attr,
- &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_in4_input.dev_attr.attr,
+ &sensor_dev_attr_in4_max.dev_attr.attr,
+ &sensor_dev_attr_in4_min.dev_attr.attr,
+ &sensor_dev_attr_in4_alarm.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_in8_input.dev_attr.attr,
+ &sensor_dev_attr_in8_max.dev_attr.attr,
+ &sensor_dev_attr_in8_min.dev_attr.attr,
+ &sensor_dev_attr_in8_alarm.dev_attr.attr,
NULL
}, {
- &sensor_dev_attr_fan2_input.dev_attr.attr,
- &sensor_dev_attr_fan2_min.dev_attr.attr,
- &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_in9_input.dev_attr.attr,
+ &sensor_dev_attr_in9_max.dev_attr.attr,
+ &sensor_dev_attr_in9_min.dev_attr.attr,
+ &sensor_dev_attr_in9_alarm.dev_attr.attr,
NULL
}, {
- &sensor_dev_attr_fan3_input.dev_attr.attr,
- &sensor_dev_attr_fan3_min.dev_attr.attr,
- &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_in10_input.dev_attr.attr,
+ &sensor_dev_attr_in10_max.dev_attr.attr,
+ &sensor_dev_attr_in10_min.dev_attr.attr,
+ &sensor_dev_attr_in10_alarm.dev_attr.attr,
NULL
}
};
-static const struct attribute_group f71805f_group_fan[3] = {
- { .attrs = f71805f_attributes_fan[0] },
- { .attrs = f71805f_attributes_fan[1] },
- { .attrs = f71805f_attributes_fan[2] },
+static const struct attribute_group f71805f_group_optin[4] = {
+ { .attrs = f71805f_attributes_optin[0] },
+ { .attrs = f71805f_attributes_optin[1] },
+ { .attrs = f71805f_attributes_optin[2] },
+ { .attrs = f71805f_attributes_optin[3] },
+};
+
+/* We don't include pwm_freq files in the arrays above, because they must be
+ created conditionally (only if pwm_mode is 1 == PWM) */
+static struct attribute *f71805f_attributes_pwm_freq[] = {
+ &sensor_dev_attr_pwm1_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm2_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm3_freq.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group f71805f_group_pwm_freq = {
+ .attrs = f71805f_attributes_pwm_freq,
+};
+
+/* We also need an indexed access to pwmN files to toggle writability */
+static struct attribute *f71805f_attr_pwm[] = {
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
};
/*
/* Fan monitoring can be disabled. If it is, we won't be polling
the register values, and won't create the related sysfs files. */
for (i = 0; i < 3; i++) {
- reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i));
- if (!(reg & 0x80))
- data->fan_enabled |= (1 << i);
+ data->fan_ctrl[i] = f71805f_read8(data,
+ F71805F_REG_FAN_CTRL(i));
+ /* Clear latch full bit, else "speed mode" fan speed control
+ doesn't work */
+ if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) {
+ data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL;
+ f71805f_write8(data, F71805F_REG_FAN_CTRL(i),
+ data->fan_ctrl[i]);
+ }
}
}
static int __devinit f71805f_probe(struct platform_device *pdev)
{
+ struct f71805f_sio_data *sio_data = pdev->dev.platform_data;
struct f71805f_data *data;
struct resource *res;
int i, err;
+ static const char *names[] = {
+ "f71805f",
+ "f71872f",
+ };
+
if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Out of memory\n");
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
data->addr = res->start;
mutex_init(&data->lock);
- data->name = "f71805f";
+ data->name = names[sio_data->kind];
mutex_init(&data->update_lock);
platform_set_drvdata(pdev, data);
+ /* Some voltage inputs depend on chip model and configuration */
+ switch (sio_data->kind) {
+ case f71805f:
+ data->has_in = 0x1ff;
+ break;
+ case f71872f:
+ data->has_in = 0x6ef;
+ if (sio_data->fnsel1 & 0x01)
+ data->has_in |= (1 << 4); /* in4 */
+ if (sio_data->fnsel1 & 0x02)
+ data->has_in |= (1 << 8); /* in8 */
+ break;
+ }
+
/* Initialize the F71805F chip */
f71805f_init_device(data);
/* Register sysfs interface files */
if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
goto exit_free;
- for (i = 0; i < 3; i++) {
- if (!(data->fan_enabled & (1 << i)))
- continue;
+ if (data->has_in & (1 << 4)) { /* in4 */
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &f71805f_group_optin[0])))
+ goto exit_remove_files;
+ }
+ if (data->has_in & (1 << 8)) { /* in8 */
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &f71805f_group_optin[1])))
+ goto exit_remove_files;
+ }
+ if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */
if ((err = sysfs_create_group(&pdev->dev.kobj,
- &f71805f_group_fan[i])))
+ &f71805f_group_optin[2])))
goto exit_remove_files;
}
+ if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &f71805f_group_optin[3])))
+ goto exit_remove_files;
+ }
+ for (i = 0; i < 3; i++) {
+ /* If control mode is PWM, create pwm_freq file */
+ if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) {
+ if ((err = sysfs_create_file(&pdev->dev.kobj,
+ f71805f_attributes_pwm_freq[i])))
+ goto exit_remove_files;
+ }
+ /* If PWM is in manual mode, add write permission */
+ if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) {
+ if ((err = sysfs_chmod_file(&pdev->dev.kobj,
+ f71805f_attr_pwm[i],
+ S_IRUGO | S_IWUSR))) {
+ dev_err(&pdev->dev, "chmod +w pwm%d failed\n",
+ i + 1);
+ goto exit_remove_files;
+ }
+ }
+ }
data->class_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->class_dev)) {
exit_remove_files:
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
- for (i = 0; i < 3; i++)
- sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
+ for (i = 0; i < 4; i++)
+ sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
+ sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
exit_free:
platform_set_drvdata(pdev, NULL);
kfree(data);
platform_set_drvdata(pdev, NULL);
hwmon_device_unregister(data->class_dev);
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
- for (i = 0; i < 3; i++)
- sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
+ for (i = 0; i < 4; i++)
+ sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
+ sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
kfree(data);
return 0;
.remove = __devexit_p(f71805f_remove),
};
-static int __init f71805f_device_add(unsigned short address)
+static int __init f71805f_device_add(unsigned short address,
+ const struct f71805f_sio_data *sio_data)
{
struct resource res = {
.start = address,
goto exit_device_put;
}
+ pdev->dev.platform_data = kmalloc(sizeof(struct f71805f_sio_data),
+ GFP_KERNEL);
+ if (!pdev->dev.platform_data) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+ goto exit_device_put;
+ }
+ memcpy(pdev->dev.platform_data, sio_data,
+ sizeof(struct f71805f_sio_data));
+
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
- goto exit_device_put;
+ goto exit_kfree_data;
}
return 0;
+exit_kfree_data:
+ kfree(pdev->dev.platform_data);
+ pdev->dev.platform_data = NULL;
exit_device_put:
platform_device_put(pdev);
exit:
return err;
}
-static int __init f71805f_find(int sioaddr, unsigned short *address)
+static int __init f71805f_find(int sioaddr, unsigned short *address,
+ struct f71805f_sio_data *sio_data)
{
int err = -ENODEV;
u16 devid;
+ static const char *names[] = {
+ "F71805F/FG",
+ "F71872F/FG",
+ };
+
superio_enter(sioaddr);
devid = superio_inw(sioaddr, SIO_REG_MANID);
goto exit;
devid = superio_inw(sioaddr, SIO_REG_DEVID);
- if (devid != SIO_F71805F_ID) {
+ switch (devid) {
+ case SIO_F71805F_ID:
+ sio_data->kind = f71805f;
+ break;
+ case SIO_F71872F_ID:
+ sio_data->kind = f71872f;
+ sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
+ break;
+ default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
"skipping\n");
goto exit;
"skipping\n");
goto exit;
}
+ *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
err = 0;
- printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
- *address, superio_inb(sioaddr, SIO_REG_DEVREV));
+ printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
+ names[sio_data->kind], *address,
+ superio_inb(sioaddr, SIO_REG_DEVREV));
exit:
superio_exit(sioaddr);
{
int err;
unsigned short address;
+ struct f71805f_sio_data sio_data;
- if (f71805f_find(0x2e, &address)
- && f71805f_find(0x4e, &address))
+ if (f71805f_find(0x2e, &address, &sio_data)
+ && f71805f_find(0x4e, &address, &sio_data))
return -ENODEV;
err = platform_driver_register(&f71805f_driver);
goto exit;
/* Sets global pdev as a side effect */
- err = f71805f_device_add(address);
+ err = f71805f_device_add(address, &sio_data);
if (err)
goto exit_driver;
static void __exit f71805f_exit(void)
{
+ kfree(pdev->dev.platform_data);
+ pdev->dev.platform_data = NULL;
platform_device_unregister(pdev);
+
platform_driver_unregister(&f71805f_driver);
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("F71805F hardware monitoring driver");
+MODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver");
module_init(f71805f_init);
module_exit(f71805f_exit);
/* Module stuff */
/* hdaps_dmi_match - found a match. return one, short-circuiting the hunt. */
-static int hdaps_dmi_match(struct dmi_system_id *id)
+static int __init hdaps_dmi_match(struct dmi_system_id *id)
{
printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
return 1;
}
/* hdaps_dmi_match_invert - found an inverted match. */
-static int hdaps_dmi_match_invert(struct dmi_system_id *id)
+static int __init hdaps_dmi_match_invert(struct dmi_system_id *id)
{
hdaps_invert = 1;
printk(KERN_INFO "hdaps: inverting axis readings.\n");
return hdaps_dmi_match(id);
}
-#define HDAPS_DMI_MATCH_NORMAL(model) { \
- .ident = "IBM " model, \
+#define HDAPS_DMI_MATCH_NORMAL(vendor, model) { \
+ .ident = vendor " " model, \
.callback = hdaps_dmi_match, \
.matches = { \
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
+ DMI_MATCH(DMI_BOARD_VENDOR, vendor), \
DMI_MATCH(DMI_PRODUCT_VERSION, model) \
} \
}
-#define HDAPS_DMI_MATCH_INVERT(model) { \
- .ident = "IBM " model, \
+#define HDAPS_DMI_MATCH_INVERT(vendor, model) { \
+ .ident = vendor " " model, \
.callback = hdaps_dmi_match_invert, \
.matches = { \
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
+ DMI_MATCH(DMI_BOARD_VENDOR, vendor), \
DMI_MATCH(DMI_PRODUCT_VERSION, model) \
} \
}
-#define HDAPS_DMI_MATCH_LENOVO(model) { \
- .ident = "Lenovo " model, \
- .callback = hdaps_dmi_match_invert, \
- .matches = { \
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), \
- DMI_MATCH(DMI_PRODUCT_VERSION, model) \
- } \
-}
+/* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
+ "ThinkPad T42p", so the order of the entries matters.
+ If your ThinkPad is not recognized, please update to latest
+ BIOS. This is especially the case for some R52 ThinkPads. */
+static struct dmi_system_id __initdata hdaps_whitelist[] = {
+ HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
+ HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
+ HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"),
+ HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"),
+ HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"),
+ { .ident = NULL }
+};
static int __init hdaps_init(void)
{
int ret;
- /* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
- "ThinkPad T42p", so the order of the entries matters */
- struct dmi_system_id hdaps_whitelist[] = {
- HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),
- HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad H"), /* R52 (1846AQG) */
- HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
- HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
- HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"),
- HDAPS_DMI_MATCH_LENOVO("ThinkPad T60"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
- HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad Z60m"),
- { .ident = NULL }
- };
-
if (!dmi_check_system(hdaps_whitelist)) {
printk(KERN_WARNING "hdaps: supported laptop not found!\n");
ret = -ENODEV;
/*
hwmon-vid.c - VID/VRM/VRD voltage conversions
- Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
+ Copyright (c) 2004 Rudolf Marek <r.marek@assembler.cz>
Partly imported from i2c-vid.h of the lm_sensors project
Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
EXPORT_SYMBOL(vid_from_reg);
EXPORT_SYMBOL(vid_which_vrm);
-MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
MODULE_DESCRIPTION("hwmon-vid driver");
MODULE_LICENSE("GPL");
monitoring.
Supports: IT8705F Super I/O chip w/LPC interface
- IT8712F Super I/O chip w/LPC interface & SMBus
+ IT8712F Super I/O chip w/LPC interface
IT8716F Super I/O chip w/LPC interface
IT8718F Super I/O chip w/LPC interface
Sis950 A clone of the IT8705F
#include <asm/io.h>
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
static unsigned short isa_address;
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD_4(it87, it8712, it8716, it8718);
+enum chips { it87, it8712, it8716, it8718 };
#define REG 0x2e /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
#define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2)
#define IT87_REG_TEMP_LOW(nr) (0x41 + (nr) * 2)
-#define IT87_REG_I2C_ADDR 0x48
-
#define IT87_REG_VIN_ENABLE 0x50
#define IT87_REG_TEMP_ENABLE 0x51
};
-static int it87_attach_adapter(struct i2c_adapter *adapter);
-static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
-static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
+static int it87_detect(struct i2c_adapter *adapter);
static int it87_detach_client(struct i2c_client *client);
static int it87_read_value(struct i2c_client *client, u8 reg);
-static int it87_write_value(struct i2c_client *client, u8 reg, u8 value);
+static void it87_write_value(struct i2c_client *client, u8 reg, u8 value);
static struct it87_data *it87_update_device(struct device *dev);
static int it87_check_pwm(struct i2c_client *client);
static void it87_init_client(struct i2c_client *client, struct it87_data *data);
-static struct i2c_driver it87_driver = {
- .driver = {
- .name = "it87",
- },
- .id = I2C_DRIVERID_IT87,
- .attach_adapter = it87_attach_adapter,
- .detach_client = it87_detach_client,
-};
-
static struct i2c_driver it87_isa_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "it87-isa",
},
- .attach_adapter = it87_isa_attach_adapter,
+ .attach_adapter = it87_detect,
.detach_client = it87_detach_client,
};
.attrs = it87_attributes_opt,
};
-/* This function is called when:
- * it87_driver is inserted (when this module is loaded), for each
- available adapter
- * when a new adapter is inserted (and it87_driver is still present) */
-static int it87_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, it87_detect);
-}
-
-static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
-{
- return it87_detect(adapter, isa_address, -1);
-}
-
/* SuperIO detection - will change isa_address if a chip is found */
static int __init it87_find(unsigned short *address)
{
}
/* This function is called by i2c_probe */
-static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
+static int it87_detect(struct i2c_adapter *adapter)
{
- int i;
struct i2c_client *new_client;
struct it87_data *data;
int err = 0;
- const char *name = "";
- int is_isa = i2c_is_isa_adapter(adapter);
+ const char *name;
int enable_pwm_interface;
- if (!is_isa &&
- !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto ERROR0;
-
/* Reserve the ISA region */
- if (is_isa)
- if (!request_region(address, IT87_EXTENT,
- it87_isa_driver.driver.name))
- goto ERROR0;
-
- /* For now, we presume we have a valid client. We create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access it87_{read,write}_value. */
+ if (!request_region(isa_address, IT87_EXTENT,
+ it87_isa_driver.driver.name)){
+ err = -EBUSY;
+ goto ERROR0;
+ }
if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
err = -ENOMEM;
}
new_client = &data->client;
- if (is_isa)
- mutex_init(&data->lock);
+ mutex_init(&data->lock);
i2c_set_clientdata(new_client, data);
- new_client->addr = address;
+ new_client->addr = isa_address;
new_client->adapter = adapter;
- new_client->driver = is_isa ? &it87_isa_driver : &it87_driver;
- new_client->flags = 0;
+ new_client->driver = &it87_isa_driver;
/* Now, we do the remaining detection. */
-
- if (kind < 0) {
- if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
- || (!is_isa
- && it87_read_value(new_client, IT87_REG_I2C_ADDR) != address)) {
- err = -ENODEV;
- goto ERROR2;
- }
+ if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
+ || it87_read_value(new_client, IT87_REG_CHIPID) != 0x90) {
+ err = -ENODEV;
+ goto ERROR2;
}
/* Determine the chip type. */
- if (kind <= 0) {
- i = it87_read_value(new_client, IT87_REG_CHIPID);
- if (i == 0x90) {
- kind = it87;
- if (is_isa) {
- switch (chip_type) {
- case IT8712F_DEVID:
- kind = it8712;
- break;
- case IT8716F_DEVID:
- kind = it8716;
- break;
- case IT8718F_DEVID:
- kind = it8718;
- break;
- }
- }
- }
- else {
- if (kind == 0)
- dev_info(&adapter->dev,
- "Ignoring 'force' parameter for unknown chip at "
- "adapter %d, address 0x%02x\n",
- i2c_adapter_id(adapter), address);
- err = -ENODEV;
- goto ERROR2;
- }
- }
-
- if (kind == it87) {
- name = "it87";
- } else if (kind == it8712) {
+ switch (chip_type) {
+ case IT8712F_DEVID:
+ data->type = it8712;
name = "it8712";
- } else if (kind == it8716) {
+ break;
+ case IT8716F_DEVID:
+ data->type = it8716;
name = "it8716";
- } else if (kind == it8718) {
+ break;
+ case IT8718F_DEVID:
+ data->type = it8718;
name = "it8718";
+ break;
+ default:
+ data->type = it87;
+ name = "it87";
}
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
- data->type = kind;
- data->valid = 0;
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto ERROR2;
- if (!is_isa)
- dev_info(&new_client->dev, "The I2C interface to IT87xxF "
- "hardware monitoring chips is deprecated. Please "
- "report if you still rely on it.\n");
-
/* Check PWM configuration */
enable_pwm_interface = it87_check_pwm(new_client);
ERROR2:
kfree(data);
ERROR1:
- if (is_isa)
- release_region(address, IT87_EXTENT);
+ release_region(isa_address, IT87_EXTENT);
ERROR0:
return err;
}
if ((err = i2c_detach_client(client)))
return err;
- if(i2c_is_isa_client(client))
- release_region(client->addr, IT87_EXTENT);
+ release_region(client->addr, IT87_EXTENT);
kfree(data);
return 0;
}
-/* The SMBus locks itself, but ISA access must be locked explicitly!
- We don't want to lock the whole ISA bus, so we lock each client
- separately.
+/* ISA access must be locked explicitly!
We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
would slow down the IT87 access and should not be necessary. */
static int it87_read_value(struct i2c_client *client, u8 reg)
{
struct it87_data *data = i2c_get_clientdata(client);
-
int res;
- if (i2c_is_isa_client(client)) {
- mutex_lock(&data->lock);
- outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
- res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
- mutex_unlock(&data->lock);
- return res;
- } else
- return i2c_smbus_read_byte_data(client, reg);
+
+ mutex_lock(&data->lock);
+ outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
+ res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
+ mutex_unlock(&data->lock);
+
+ return res;
}
-/* The SMBus locks itself, but ISA access muse be locked explicitly!
- We don't want to lock the whole ISA bus, so we lock each client
- separately.
+/* ISA access must be locked explicitly!
We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
would slow down the IT87 access and should not be necessary. */
-static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
+static void it87_write_value(struct i2c_client *client, u8 reg, u8 value)
{
struct it87_data *data = i2c_get_clientdata(client);
- if (i2c_is_isa_client(client)) {
- mutex_lock(&data->lock);
- outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
- outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
- mutex_unlock(&data->lock);
- return 0;
- } else
- return i2c_smbus_write_byte_data(client, reg, value);
+ mutex_lock(&data->lock);
+ outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
+ outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
+ mutex_unlock(&data->lock);
}
/* Return 1 if and only if the PWM interface is safe to use */
{
int res;
- res = i2c_add_driver(&it87_driver);
- if (res)
+ if ((res = it87_find(&isa_address)))
return res;
-
- if (!it87_find(&isa_address)) {
- res = i2c_isa_add_driver(&it87_isa_driver);
- if (res) {
- i2c_del_driver(&it87_driver);
- return res;
- }
- }
-
- return 0;
+ return i2c_isa_add_driver(&it87_isa_driver);
}
static void __exit sm_it87_exit(void)
{
- if (isa_address)
- i2c_isa_del_driver(&it87_isa_driver);
- i2c_del_driver(&it87_driver);
+ i2c_isa_del_driver(&it87_isa_driver);
}
/*
* k8temp.c - Linux kernel module for hardware monitoring
*
- * Copyright (C) 2006 Rudolf Marek <r.marek@sh.cvut.cz>
+ * Copyright (C) 2006 Rudolf Marek <r.marek@assembler.cz>
*
* Inspired from the w83785 and amd756 drivers.
*
pci_unregister_driver(&k8temp_driver);
}
-MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
MODULE_DESCRIPTION("AMD K8 core temperature monitor");
MODULE_LICENSE("GPL");
(i&0x02) ? "external" : "internal");
data->vid_conf = confreg[3];
- data->vrm = 90;
+ data->vrm = vid_which_vrm();
}
/* Fan clock dividers may be needed before any data is read */
--- /dev/null
+/*
+ * pc87427.c - hardware monitoring driver for the
+ * National Semiconductor PC87427 Super-I/O chip
+ * Copyright (C) 2006 Jean Delvare <khali@linux-fr.org>
+ *
+ * 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.
+ *
+ * Supports the following chips:
+ *
+ * Chip #vin #fan #pwm #temp devid
+ * PC87427 - 8 - - 0xF2
+ *
+ * This driver assumes that no more than one chip is present.
+ * Only fan inputs are supported so far, although the chip can do much more.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <asm/io.h>
+
+static struct platform_device *pdev;
+
+#define DRVNAME "pc87427"
+
+/* The lock mutex protects both the I/O accesses (needed because the
+ device is using banked registers) and the register cache (needed to keep
+ the data in the registers and the cache in sync at any time). */
+struct pc87427_data {
+ struct class_device *class_dev;
+ struct mutex lock;
+ int address[2];
+ const char *name;
+
+ unsigned long last_updated; /* in jiffies */
+ u8 fan_enabled; /* bit vector */
+ u16 fan[8]; /* register values */
+ u16 fan_min[8]; /* register values */
+ u8 fan_status[8]; /* register values */
+};
+
+/*
+ * Super-I/O registers and operations
+ */
+
+#define SIOREG_LDSEL 0x07 /* Logical device select */
+#define SIOREG_DEVID 0x20 /* Device ID */
+#define SIOREG_ACT 0x30 /* Device activation */
+#define SIOREG_MAP 0x50 /* I/O or memory mapping */
+#define SIOREG_IOBASE 0x60 /* I/O base address */
+
+static const u8 logdev[2] = { 0x09, 0x14 };
+static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" };
+#define LD_FAN 0
+#define LD_IN 1
+#define LD_TEMP 1
+
+static inline void superio_outb(int sioaddr, int reg, int val)
+{
+ outb(reg, sioaddr);
+ outb(val, sioaddr + 1);
+}
+
+static inline int superio_inb(int sioaddr, int reg)
+{
+ outb(reg, sioaddr);
+ return inb(sioaddr + 1);
+}
+
+static inline void superio_exit(int sioaddr)
+{
+ outb(0x02, sioaddr);
+ outb(0x02, sioaddr + 1);
+}
+
+/*
+ * Logical devices
+ */
+
+#define REGION_LENGTH 32
+#define PC87427_REG_BANK 0x0f
+#define BANK_FM(nr) (nr)
+#define BANK_FT(nr) (0x08 + (nr))
+#define BANK_FC(nr) (0x10 + (nr) * 2)
+
+/*
+ * I/O access functions
+ */
+
+/* ldi is the logical device index */
+static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg)
+{
+ return inb(data->address[ldi] + reg);
+}
+
+/* Must be called with data->lock held, except during init */
+static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi,
+ u8 bank, u8 reg)
+{
+ outb(bank, data->address[ldi] + PC87427_REG_BANK);
+ return inb(data->address[ldi] + reg);
+}
+
+/* Must be called with data->lock held, except during init */
+static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
+ u8 bank, u8 reg, u8 value)
+{
+ outb(bank, data->address[ldi] + PC87427_REG_BANK);
+ outb(value, data->address[ldi] + reg);
+}
+
+/*
+ * Fan registers and conversions
+ */
+
+/* fan data registers are 16-bit wide */
+#define PC87427_REG_FAN 0x12
+#define PC87427_REG_FAN_MIN 0x14
+#define PC87427_REG_FAN_STATUS 0x10
+
+#define FAN_STATUS_STALL (1 << 3)
+#define FAN_STATUS_LOSPD (1 << 1)
+#define FAN_STATUS_MONEN (1 << 0)
+
+/* Dedicated function to read all registers related to a given fan input.
+ This saves us quite a few locks and bank selections.
+ Must be called with data->lock held.
+ nr is from 0 to 7 */
+static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
+{
+ int iobase = data->address[LD_FAN];
+
+ outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
+ data->fan[nr] = inw(iobase + PC87427_REG_FAN);
+ data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN);
+ data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS);
+ /* Clear fan alarm bits */
+ outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
+}
+
+/* The 2 LSB of fan speed registers are used for something different.
+ The actual 2 LSB of the measurements are not available. */
+static inline unsigned long fan_from_reg(u16 reg)
+{
+ reg &= 0xfffc;
+ if (reg == 0x0000 || reg == 0xfffc)
+ return 0;
+ return 5400000UL / reg;
+}
+
+/* The 2 LSB of the fan speed limit registers are not significant. */
+static inline u16 fan_to_reg(unsigned long val)
+{
+ if (val < 83UL)
+ return 0xffff;
+ if (val >= 1350000UL)
+ return 0x0004;
+ return ((1350000UL + val / 2) / val) << 2;
+}
+
+/*
+ * Data interface
+ */
+
+static struct pc87427_data *pc87427_update_device(struct device *dev)
+{
+ struct pc87427_data *data = dev_get_drvdata(dev);
+ int i;
+
+ mutex_lock(&data->lock);
+ if (!time_after(jiffies, data->last_updated + HZ)
+ && data->last_updated)
+ goto done;
+
+ /* Fans */
+ for (i = 0; i < 8; i++) {
+ if (!(data->fan_enabled & (1 << i)))
+ continue;
+ pc87427_readall_fan(data, i);
+ }
+ data->last_updated = jiffies;
+
+done:
+ mutex_unlock(&data->lock);
+ return data;
+}
+
+static ssize_t show_fan_input(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87427_data *data = pc87427_update_device(dev);
+ int nr = attr->index;
+
+ return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87427_data *data = pc87427_update_device(dev);
+ int nr = attr->index;
+
+ return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
+}
+
+static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87427_data *data = pc87427_update_device(dev);
+ int nr = attr->index;
+
+ return sprintf(buf, "%d\n", !!(data->fan_status[nr]
+ & FAN_STATUS_LOSPD));
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87427_data *data = pc87427_update_device(dev);
+ int nr = attr->index;
+
+ return sprintf(buf, "%d\n", !!(data->fan_status[nr]
+ & FAN_STATUS_STALL));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct pc87427_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ int iobase = data->address[LD_FAN];
+
+ mutex_lock(&data->lock);
+ outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
+ /* The low speed limit registers are read-only while monitoring
+ is enabled, so we have to disable monitoring, then change the
+ limit, and finally enable monitoring again. */
+ outb(0, iobase + PC87427_REG_FAN_STATUS);
+ data->fan_min[nr] = fan_to_reg(val);
+ outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
+ outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 3);
+static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 4);
+static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 5);
+static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 6);
+static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
+
+static struct attribute *pc87427_attributes_fan[8][5] = {
+ {
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_min.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan1_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_min.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan2_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_min.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan3_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan4_input.dev_attr.attr,
+ &sensor_dev_attr_fan4_min.dev_attr.attr,
+ &sensor_dev_attr_fan4_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan4_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan5_input.dev_attr.attr,
+ &sensor_dev_attr_fan5_min.dev_attr.attr,
+ &sensor_dev_attr_fan5_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan5_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan6_input.dev_attr.attr,
+ &sensor_dev_attr_fan6_min.dev_attr.attr,
+ &sensor_dev_attr_fan6_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan6_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan7_input.dev_attr.attr,
+ &sensor_dev_attr_fan7_min.dev_attr.attr,
+ &sensor_dev_attr_fan7_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan7_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan8_input.dev_attr.attr,
+ &sensor_dev_attr_fan8_min.dev_attr.attr,
+ &sensor_dev_attr_fan8_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan8_fault.dev_attr.attr,
+ NULL
+ }
+};
+
+static const struct attribute_group pc87427_group_fan[8] = {
+ { .attrs = pc87427_attributes_fan[0] },
+ { .attrs = pc87427_attributes_fan[1] },
+ { .attrs = pc87427_attributes_fan[2] },
+ { .attrs = pc87427_attributes_fan[3] },
+ { .attrs = pc87427_attributes_fan[4] },
+ { .attrs = pc87427_attributes_fan[5] },
+ { .attrs = pc87427_attributes_fan[6] },
+ { .attrs = pc87427_attributes_fan[7] },
+};
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct pc87427_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+
+/*
+ * Device detection, attach and detach
+ */
+
+static void __devinit pc87427_init_device(struct device *dev)
+{
+ struct pc87427_data *data = dev_get_drvdata(dev);
+ int i;
+ u8 reg;
+
+ /* The FMC module should be ready */
+ reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
+ if (!(reg & 0x80))
+ dev_warn(dev, "FMC module not ready!\n");
+
+ /* Check which fans are enabled */
+ for (i = 0; i < 8; i++) {
+ reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
+ PC87427_REG_FAN_STATUS);
+ if (reg & FAN_STATUS_MONEN)
+ data->fan_enabled |= (1 << i);
+ }
+
+ if (!data->fan_enabled) {
+ dev_dbg(dev, "Enabling all fan inputs\n");
+ for (i = 0; i < 8; i++)
+ pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
+ PC87427_REG_FAN_STATUS,
+ FAN_STATUS_MONEN);
+ data->fan_enabled = 0xff;
+ }
+}
+
+static int __devinit pc87427_probe(struct platform_device *pdev)
+{
+ struct pc87427_data *data;
+ struct resource *res;
+ int i, err;
+
+ if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Out of memory\n");
+ goto exit;
+ }
+
+ /* This will need to be revisited when we add support for
+ temperature and voltage monitoring. */
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ data->address[0] = res->start;
+
+ mutex_init(&data->lock);
+ data->name = "pc87427";
+ platform_set_drvdata(pdev, data);
+ pc87427_init_device(&pdev->dev);
+
+ /* Register sysfs hooks */
+ if ((err = device_create_file(&pdev->dev, &dev_attr_name)))
+ goto exit_kfree;
+ for (i = 0; i < 8; i++) {
+ if (!(data->fan_enabled & (1 << i)))
+ continue;
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &pc87427_group_fan[i])))
+ goto exit_remove_files;
+ }
+
+ data->class_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
+ goto exit_remove_files;
+ }
+
+ return 0;
+
+exit_remove_files:
+ for (i = 0; i < 8; i++) {
+ if (!(data->fan_enabled & (1 << i)))
+ continue;
+ sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
+ }
+exit_kfree:
+ platform_set_drvdata(pdev, NULL);
+ kfree(data);
+exit:
+ return err;
+}
+
+static int __devexit pc87427_remove(struct platform_device *pdev)
+{
+ struct pc87427_data *data = platform_get_drvdata(pdev);
+ int i;
+
+ platform_set_drvdata(pdev, NULL);
+ hwmon_device_unregister(data->class_dev);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ for (i = 0; i < 8; i++) {
+ if (!(data->fan_enabled & (1 << i)))
+ continue;
+ sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
+ }
+ kfree(data);
+
+ return 0;
+}
+
+
+static struct platform_driver pc87427_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .probe = pc87427_probe,
+ .remove = __devexit_p(pc87427_remove),
+};
+
+static int __init pc87427_device_add(unsigned short address)
+{
+ struct resource res = {
+ .start = address,
+ .end = address + REGION_LENGTH - 1,
+ .name = logdev_str[0],
+ .flags = IORESOURCE_IO,
+ };
+ int err;
+
+ pdev = platform_device_alloc(DRVNAME, address);
+ if (!pdev) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+ goto exit;
+ }
+
+ err = platform_device_add_resources(pdev, &res, 1);
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Device resource addition failed "
+ "(%d)\n", err);
+ goto exit_device_put;
+ }
+
+ err = platform_device_add(pdev);
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+ err);
+ goto exit_device_put;
+ }
+
+ return 0;
+
+exit_device_put:
+ platform_device_put(pdev);
+exit:
+ return err;
+}
+
+static int __init pc87427_find(int sioaddr, unsigned short *address)
+{
+ u16 val;
+ int i, err = 0;
+
+ /* Identify device */
+ val = superio_inb(sioaddr, SIOREG_DEVID);
+ if (val != 0xf2) { /* PC87427 */
+ err = -ENODEV;
+ goto exit;
+ }
+
+ for (i = 0; i < 2; i++) {
+ address[i] = 0;
+ /* Select logical device */
+ superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
+
+ val = superio_inb(sioaddr, SIOREG_ACT);
+ if (!(val & 0x01)) {
+ printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
+ "not activated\n", logdev[i]);
+ continue;
+ }
+
+ val = superio_inb(sioaddr, SIOREG_MAP);
+ if (val & 0x01) {
+ printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
+ "is memory-mapped, can't use\n", logdev[i]);
+ continue;
+ }
+
+ val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
+ | superio_inb(sioaddr, SIOREG_IOBASE + 1);
+ if (!val) {
+ printk(KERN_INFO DRVNAME ": I/O base address not set "
+ "for logical device 0x%02x\n", logdev[i]);
+ continue;
+ }
+ address[i] = val;
+ }
+
+exit:
+ superio_exit(sioaddr);
+ return err;
+}
+
+static int __init pc87427_init(void)
+{
+ int err;
+ unsigned short address[2];
+
+ if (pc87427_find(0x2e, address)
+ && pc87427_find(0x4e, address))
+ return -ENODEV;
+
+ /* For now the driver only handles fans so we only care about the
+ first address. */
+ if (!address[0])
+ return -ENODEV;
+
+ err = platform_driver_register(&pc87427_driver);
+ if (err)
+ goto exit;
+
+ /* Sets global pdev as a side effect */
+ err = pc87427_device_add(address[0]);
+ if (err)
+ goto exit_driver;
+
+ return 0;
+
+exit_driver:
+ platform_driver_unregister(&pc87427_driver);
+exit:
+ return err;
+}
+
+static void __exit pc87427_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&pc87427_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
+MODULE_LICENSE("GPL");
+
+module_init(pc87427_init);
+module_exit(pc87427_exit);
the Winbond W83627EHF Super-I/O chip
Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
Copyright (C) 2006 Yuan Mu (Winbond),
- Rudolf Marek <r.marek@sh.cvut.cz>
+ Rudolf Marek <r.marek@assembler.cz>
David Hubbard <david.c.hubbard@gmail.com>
Shamelessly ripped from the w83627hf driver
monitoring
Copyright (C) 2004, 2005 Winbond Electronics Corp.
Chunhao Huang <DZShen@Winbond.com.tw>,
- Rudolf Marek <r.marek@sh.cvut.cz>
+ Rudolf Marek <r.marek@assembler.cz>
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
--- /dev/null
+/*
+ w83793.c - Linux kernel driver for hardware monitoring
+ Copyright (C) 2006 Winbond Electronics Corp.
+ Yuan Mu
+ Rudolf Marek <r.marek@assembler.cz>
+
+ 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 - version 2.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/*
+ Supports following chips:
+
+ Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ w83793 10 12 8 6 0x7b 0x5ca3 yes no
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83793);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+ "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
+
+/*
+ Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved
+ as ID, Bank Select registers
+*/
+#define W83793_REG_BANKSEL 0x00
+#define W83793_REG_VENDORID 0x0d
+#define W83793_REG_CHIPID 0x0e
+#define W83793_REG_DEVICEID 0x0f
+
+#define W83793_REG_CONFIG 0x40
+#define W83793_REG_MFC 0x58
+#define W83793_REG_FANIN_CTRL 0x5c
+#define W83793_REG_FANIN_SEL 0x5d
+#define W83793_REG_I2C_ADDR 0x0b
+#define W83793_REG_I2C_SUBADDR 0x0c
+#define W83793_REG_VID_INA 0x05
+#define W83793_REG_VID_INB 0x06
+#define W83793_REG_VID_LATCHA 0x07
+#define W83793_REG_VID_LATCHB 0x08
+#define W83793_REG_VID_CTRL 0x59
+
+static u16 W83793_REG_TEMP_MODE[2] = { 0x5e, 0x5f };
+
+#define TEMP_READ 0
+#define TEMP_CRIT 1
+#define TEMP_CRIT_HYST 2
+#define TEMP_WARN 3
+#define TEMP_WARN_HYST 4
+/* only crit and crit_hyst affect real-time alarm status
+ current crit crit_hyst warn warn_hyst */
+static u16 W83793_REG_TEMP[][5] = {
+ {0x1c, 0x78, 0x79, 0x7a, 0x7b},
+ {0x1d, 0x7c, 0x7d, 0x7e, 0x7f},
+ {0x1e, 0x80, 0x81, 0x82, 0x83},
+ {0x1f, 0x84, 0x85, 0x86, 0x87},
+ {0x20, 0x88, 0x89, 0x8a, 0x8b},
+ {0x21, 0x8c, 0x8d, 0x8e, 0x8f},
+};
+
+#define W83793_REG_TEMP_LOW_BITS 0x22
+
+#define W83793_REG_BEEP(index) (0x53 + (index))
+#define W83793_REG_ALARM(index) (0x4b + (index))
+
+#define W83793_REG_CLR_CHASSIS 0x4a /* SMI MASK4 */
+#define W83793_REG_IRQ_CTRL 0x50
+#define W83793_REG_OVT_CTRL 0x51
+#define W83793_REG_OVT_BEEP 0x52
+
+#define IN_READ 0
+#define IN_MAX 1
+#define IN_LOW 2
+static const u16 W83793_REG_IN[][3] = {
+ /* Current, High, Low */
+ {0x10, 0x60, 0x61}, /* Vcore A */
+ {0x11, 0x62, 0x63}, /* Vcore B */
+ {0x12, 0x64, 0x65}, /* Vtt */
+ {0x14, 0x6a, 0x6b}, /* VSEN1 */
+ {0x15, 0x6c, 0x6d}, /* VSEN2 */
+ {0x16, 0x6e, 0x6f}, /* +3VSEN */
+ {0x17, 0x70, 0x71}, /* +12VSEN */
+ {0x18, 0x72, 0x73}, /* 5VDD */
+ {0x19, 0x74, 0x75}, /* 5VSB */
+ {0x1a, 0x76, 0x77}, /* VBAT */
+};
+
+/* Low Bits of Vcore A/B Vtt Read/High/Low */
+static const u16 W83793_REG_IN_LOW_BITS[] = { 0x1b, 0x68, 0x69 };
+static u8 scale_in[] = { 2, 2, 2, 16, 16, 16, 8, 24, 24, 16 };
+
+#define W83793_REG_FAN(index) (0x23 + 2 * (index)) /* High byte */
+#define W83793_REG_FAN_MIN(index) (0x90 + 2 * (index)) /* High byte */
+
+#define W83793_REG_PWM_DEFAULT 0xb2
+#define W83793_REG_PWM_ENABLE 0x207
+#define W83793_REG_PWM_UPTIME 0xc3 /* Unit in 0.1 second */
+#define W83793_REG_PWM_DOWNTIME 0xc4 /* Unit in 0.1 second */
+#define W83793_REG_TEMP_CRITICAL 0xc5
+
+#define PWM_DUTY 0
+#define PWM_START 1
+#define PWM_NONSTOP 2
+#define W83793_REG_PWM(index, nr) (((nr) == 0 ? 0xb3 : \
+ (nr) == 1 ? 0x220 : 0x218) + (index))
+
+/* bit field, fan1 is bit0, fan2 is bit1 ... */
+#define W83793_REG_TEMP_FAN_MAP(index) (0x201 + (index))
+#define W83793_REG_TEMP_TOL(index) (0x208 + (index))
+#define W83793_REG_TEMP_CRUISE(index) (0x210 + (index))
+#define W83793_REG_PWM_STOP_TIME(index) (0x228 + (index))
+#define W83793_REG_SF2_TEMP(index, nr) (0x230 + ((index) << 4) + (nr))
+#define W83793_REG_SF2_PWM(index, nr) (0x238 + ((index) << 4) + (nr))
+
+static inline unsigned long FAN_FROM_REG(u16 val)
+{
+ if ((val >= 0xfff) || (val == 0))
+ return 0;
+ return (1350000UL / val);
+}
+
+static inline u16 FAN_TO_REG(long rpm)
+{
+ if (rpm <= 0)
+ return 0x0fff;
+ return SENSORS_LIMIT((1350000 + (rpm >> 1)) / rpm, 1, 0xffe);
+}
+
+static inline unsigned long TIME_FROM_REG(u8 reg)
+{
+ return (reg * 100);
+}
+
+static inline u8 TIME_TO_REG(unsigned long val)
+{
+ return SENSORS_LIMIT((val + 50) / 100, 0, 0xff);
+}
+
+static inline long TEMP_FROM_REG(s8 reg)
+{
+ return (reg * 1000);
+}
+
+static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
+{
+ return SENSORS_LIMIT((val + (val < 0 ? -500 : 500)) / 1000, min, max);
+}
+
+struct w83793_data {
+ struct i2c_client client;
+ struct i2c_client *lm75[2];
+ struct class_device *class_dev;
+ struct mutex update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+ unsigned long last_nonvolatile; /* In jiffies, last time we update the
+ nonvolatile registers */
+
+ u8 bank;
+ u8 vrm;
+ u8 vid[2];
+ u8 in[10][3]; /* Register value, read/high/low */
+ u8 in_low_bits[3]; /* Additional resolution for VCore A/B Vtt */
+
+ u16 has_fan; /* Only fan1- fan5 has own pins */
+ u16 fan[12]; /* Register value combine */
+ u16 fan_min[12]; /* Register value combine */
+
+ s8 temp[6][5]; /* current, crit, crit_hyst,warn, warn_hyst */
+ u8 temp_low_bits; /* Additional resolution TD1-TD4 */
+ u8 temp_mode[2]; /* byte 0: Temp D1-D4 mode each has 2 bits
+ byte 1: Temp R1,R2 mode, each has 1 bit */
+ u8 temp_critical; /* If reached all fan will be at full speed */
+ u8 temp_fan_map[6]; /* Temp controls which pwm fan, bit field */
+
+ u8 has_pwm;
+ u8 pwm_enable; /* Register value, each Temp has 1 bit */
+ u8 pwm_uptime; /* Register value */
+ u8 pwm_downtime; /* Register value */
+ u8 pwm_default; /* All fan default pwm, next poweron valid */
+ u8 pwm[8][3]; /* Register value */
+ u8 pwm_stop_time[8];
+ u8 temp_cruise[6];
+
+ u8 alarms[5]; /* realtime status registers */
+ u8 beeps[5];
+ u8 beep_enable;
+ u8 tolerance[3]; /* Temp tolerance(Smart Fan I/II) */
+ u8 sf2_pwm[6][7]; /* Smart FanII: Fan duty cycle */
+ u8 sf2_temp[6][7]; /* Smart FanII: Temp level point */
+};
+
+static u8 w83793_read_value(struct i2c_client *client, u16 reg);
+static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value);
+static int w83793_attach_adapter(struct i2c_adapter *adapter);
+static int w83793_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83793_detach_client(struct i2c_client *client);
+static void w83793_init_client(struct i2c_client *client);
+static void w83793_update_nonvolatile(struct device *dev);
+static struct w83793_data *w83793_update_device(struct device *dev);
+
+static struct i2c_driver w83793_driver = {
+ .driver = {
+ .name = "w83793",
+ },
+ .attach_adapter = w83793_attach_adapter,
+ .detach_client = w83793_detach_client,
+};
+
+static ssize_t
+show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t
+show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83793_data *data = w83793_update_device(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index;
+
+ return sprintf(buf, "%d\n", vid_from_reg(data->vid[index], data->vrm));
+}
+
+static ssize_t
+store_vrm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+
+ data->vrm = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+#define ALARM_STATUS 0
+#define BEEP_ENABLE 1
+static ssize_t
+show_alarm_beep(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83793_data *data = w83793_update_device(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index >> 3;
+ int bit = sensor_attr->index & 0x07;
+ u8 val;
+
+ if (ALARM_STATUS == nr) {
+ val = (data->alarms[index] >> (bit)) & 1;
+ } else { /* BEEP_ENABLE */
+ val = (data->beeps[index] >> (bit)) & 1;
+ }
+
+ return sprintf(buf, "%u\n", val);
+}
+
+static ssize_t
+store_beep(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index >> 3;
+ int shift = sensor_attr->index & 0x07;
+ u8 beep_bit = 1 << shift;
+ u8 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->beeps[index] = w83793_read_value(client, W83793_REG_BEEP(index));
+ data->beeps[index] &= ~beep_bit;
+ data->beeps[index] |= val << shift;
+ w83793_write_value(client, W83793_REG_BEEP(index), data->beeps[index]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t
+show_beep_enable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83793_data *data = w83793_update_device(dev);
+ return sprintf(buf, "%u\n", (data->beep_enable >> 1) & 0x01);
+}
+
+static ssize_t
+store_beep_enable(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u8 val = simple_strtoul(buf, NULL, 10);
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP)
+ & 0xfd;
+ data->beep_enable |= val << 1;
+ w83793_write_value(client, W83793_REG_OVT_BEEP, data->beep_enable);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+/* Write any value to clear chassis alarm */
+static ssize_t
+store_chassis_clear(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u8 val;
+
+ mutex_lock(&data->update_lock);
+ val = w83793_read_value(client, W83793_REG_CLR_CHASSIS);
+ val |= 0x80;
+ w83793_write_value(client, W83793_REG_CLR_CHASSIS, val);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+#define FAN_INPUT 0
+#define FAN_MIN 1
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+ u16 val;
+
+ if (FAN_INPUT == nr) {
+ val = data->fan[index] & 0x0fff;
+ } else {
+ val = data->fan_min[index] & 0x0fff;
+ }
+
+ return sprintf(buf, "%lu\n", FAN_FROM_REG(val));
+}
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u16 val = FAN_TO_REG(simple_strtoul(buf, NULL, 10));
+
+ mutex_lock(&data->update_lock);
+ data->fan_min[index] = val;
+ w83793_write_value(client, W83793_REG_FAN_MIN(index),
+ (val >> 8) & 0xff);
+ w83793_write_value(client, W83793_REG_FAN_MIN(index) + 1, val & 0xff);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+#define PWM_DUTY 0
+#define PWM_START 1
+#define PWM_NONSTOP 2
+#define PWM_STOP_TIME 3
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ struct w83793_data *data = w83793_update_device(dev);
+ u16 val;
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+
+ if (PWM_STOP_TIME == nr)
+ val = TIME_FROM_REG(data->pwm_stop_time[index]);
+ else
+ val = (data->pwm[index][nr] & 0x3f) << 2;
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ u8 val;
+
+ mutex_lock(&data->update_lock);
+ if (PWM_STOP_TIME == nr) {
+ val = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+ data->pwm_stop_time[index] = val;
+ w83793_write_value(client, W83793_REG_PWM_STOP_TIME(index),
+ val);
+ } else {
+ val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff)
+ >> 2;
+ data->pwm[index][nr] =
+ w83793_read_value(client, W83793_REG_PWM(index, nr)) & 0xc0;
+ data->pwm[index][nr] |= val;
+ w83793_write_value(client, W83793_REG_PWM(index, nr),
+ data->pwm[index][nr]);
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+ long temp = TEMP_FROM_REG(data->temp[index][nr]);
+
+ if (TEMP_READ == nr && index < 4) { /* Only TD1-TD4 have low bits */
+ int low = ((data->temp_low_bits >> (index * 2)) & 0x03) * 250;
+ temp += temp > 0 ? low : -low;
+ }
+ return sprintf(buf, "%ld\n", temp);
+}
+
+static ssize_t
+store_temp(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ long tmp = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->temp[index][nr] = TEMP_TO_REG(tmp, -128, 127);
+ w83793_write_value(client, W83793_REG_TEMP[index][nr],
+ data->temp[index][nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ TD1-TD4
+ each has 4 mode:(2 bits)
+ 0: Stop monitor
+ 1: Use internal temp sensor(default)
+ 2: Use sensor in AMD CPU and get result by AMDSI
+ 3: Use sensor in Intel CPU and get result by PECI
+
+ TR1-TR2
+ each has 2 mode:(1 bit)
+ 0: Disable temp sensor monitor
+ 1: To enable temp sensors monitor
+*/
+
+/* 0 disable, 5 AMDSI, 6 PECI */
+static u8 TO_TEMP_MODE[] = { 0, 0, 5, 6 };
+
+static ssize_t
+show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83793_data *data = w83793_update_device(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index;
+ u8 mask = (index < 4) ? 0x03 : 0x01;
+ u8 shift = (index < 4) ? (2 * index) : (index - 4);
+ u8 tmp;
+ index = (index < 4) ? 0 : 1;
+
+ tmp = (data->temp_mode[index] >> shift) & mask;
+
+ /* for the internal sensor, found out if diode or thermistor */
+ if (tmp == 1) {
+ tmp = index == 0 ? 3 : 4;
+ } else {
+ tmp = TO_TEMP_MODE[tmp];
+ }
+
+ return sprintf(buf, "%d\n", tmp);
+}
+
+static ssize_t
+store_temp_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index;
+ u8 mask = (index < 4) ? 0x03 : 0x01;
+ u8 shift = (index < 4) ? (2 * index) : (index - 4);
+ u8 val = simple_strtoul(buf, NULL, 10);
+
+ /* transform the sysfs interface values into table above */
+ if ((val == 5 || val == 6) && (index < 4)) {
+ val -= 3;
+ } else if ((val == 3 && index < 4)
+ || (val == 4 && index >= 4)
+ || val == 0) {
+ /* transform diode or thermistor into internal enable */
+ val = !!val;
+ } else {
+ return -EINVAL;
+ }
+
+ index = (index < 4) ? 0 : 1;
+ mutex_lock(&data->update_lock);
+ data->temp_mode[index] =
+ w83793_read_value(client, W83793_REG_TEMP_MODE[index]);
+ data->temp_mode[index] &= ~(mask << shift);
+ data->temp_mode[index] |= val << shift;
+ w83793_write_value(client, W83793_REG_TEMP_MODE[index],
+ data->temp_mode[index]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+#define SETUP_PWM_DEFAULT 0
+#define SETUP_PWM_UPTIME 1 /* Unit in 0.1s */
+#define SETUP_PWM_DOWNTIME 2 /* Unit in 0.1s */
+#define SETUP_TEMP_CRITICAL 3
+static ssize_t
+show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ struct w83793_data *data = w83793_update_device(dev);
+ u32 val = 0;
+
+ if (SETUP_PWM_DEFAULT == nr) {
+ val = (data->pwm_default & 0x3f) << 2;
+ } else if (SETUP_PWM_UPTIME == nr) {
+ val = TIME_FROM_REG(data->pwm_uptime);
+ } else if (SETUP_PWM_DOWNTIME == nr) {
+ val = TIME_FROM_REG(data->pwm_downtime);
+ } else if (SETUP_TEMP_CRITICAL == nr) {
+ val = TEMP_FROM_REG(data->temp_critical & 0x7f);
+ }
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_sf_setup(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+ if (SETUP_PWM_DEFAULT == nr) {
+ data->pwm_default =
+ w83793_read_value(client, W83793_REG_PWM_DEFAULT) & 0xc0;
+ data->pwm_default |= SENSORS_LIMIT(simple_strtoul(buf, NULL,
+ 10),
+ 0, 0xff) >> 2;
+ w83793_write_value(client, W83793_REG_PWM_DEFAULT,
+ data->pwm_default);
+ } else if (SETUP_PWM_UPTIME == nr) {
+ data->pwm_uptime = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+ data->pwm_uptime += data->pwm_uptime == 0 ? 1 : 0;
+ w83793_write_value(client, W83793_REG_PWM_UPTIME,
+ data->pwm_uptime);
+ } else if (SETUP_PWM_DOWNTIME == nr) {
+ data->pwm_downtime = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+ data->pwm_downtime += data->pwm_downtime == 0 ? 1 : 0;
+ w83793_write_value(client, W83793_REG_PWM_DOWNTIME,
+ data->pwm_downtime);
+ } else { /* SETUP_TEMP_CRITICAL */
+ data->temp_critical =
+ w83793_read_value(client, W83793_REG_TEMP_CRITICAL) & 0x80;
+ data->temp_critical |= TEMP_TO_REG(simple_strtol(buf, NULL, 10),
+ 0, 0x7f);
+ w83793_write_value(client, W83793_REG_TEMP_CRITICAL,
+ data->temp_critical);
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ Temp SmartFan control
+ TEMP_FAN_MAP
+ Temp channel control which pwm fan, bitfield, bit 0 indicate pwm1...
+ It's possible two or more temp channels control the same fan, w83793
+ always prefers to pick the most critical request and applies it to
+ the related Fan.
+ It's possible one fan is not in any mapping of 6 temp channels, this
+ means the fan is manual mode
+
+ TEMP_PWM_ENABLE
+ Each temp channel has its own SmartFan mode, and temp channel
+ control fans that are set by TEMP_FAN_MAP
+ 0: SmartFanII mode
+ 1: Thermal Cruise Mode
+
+ TEMP_CRUISE
+ Target temperature in thermal cruise mode, w83793 will try to turn
+ fan speed to keep the temperature of target device around this
+ temperature.
+
+ TEMP_TOLERANCE
+ If Temp higher or lower than target with this tolerance, w83793
+ will take actions to speed up or slow down the fan to keep the
+ temperature within the tolerance range.
+*/
+
+#define TEMP_FAN_MAP 0
+#define TEMP_PWM_ENABLE 1
+#define TEMP_CRUISE 2
+#define TEMP_TOLERANCE 3
+static ssize_t
+show_sf_ctrl(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+ u32 val;
+
+ if (TEMP_FAN_MAP == nr) {
+ val = data->temp_fan_map[index];
+ } else if (TEMP_PWM_ENABLE == nr) {
+ /* +2 to transfrom into 2 and 3 to conform with sysfs intf */
+ val = ((data->pwm_enable >> index) & 0x01) + 2;
+ } else if (TEMP_CRUISE == nr) {
+ val = TEMP_FROM_REG(data->temp_cruise[index] & 0x7f);
+ } else { /* TEMP_TOLERANCE */
+ val = data->tolerance[index >> 1] >> ((index & 0x01) ? 4 : 0);
+ val = TEMP_FROM_REG(val & 0x0f);
+ }
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_sf_ctrl(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ mutex_lock(&data->update_lock);
+ if (TEMP_FAN_MAP == nr) {
+ val = simple_strtoul(buf, NULL, 10) & 0xff;
+ w83793_write_value(client, W83793_REG_TEMP_FAN_MAP(index), val);
+ data->temp_fan_map[index] = val;
+ } else if (TEMP_PWM_ENABLE == nr) {
+ val = simple_strtoul(buf, NULL, 10);
+ if (2 == val || 3 == val) {
+ data->pwm_enable =
+ w83793_read_value(client, W83793_REG_PWM_ENABLE);
+ if (val - 2)
+ data->pwm_enable |= 1 << index;
+ else
+ data->pwm_enable &= ~(1 << index);
+ w83793_write_value(client, W83793_REG_PWM_ENABLE,
+ data->pwm_enable);
+ } else {
+ mutex_unlock(&data->update_lock);
+ return -EINVAL;
+ }
+ } else if (TEMP_CRUISE == nr) {
+ data->temp_cruise[index] =
+ w83793_read_value(client, W83793_REG_TEMP_CRUISE(index));
+ val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x7f);
+ data->temp_cruise[index] &= 0x80;
+ data->temp_cruise[index] |= val;
+
+ w83793_write_value(client, W83793_REG_TEMP_CRUISE(index),
+ data->temp_cruise[index]);
+ } else { /* TEMP_TOLERANCE */
+ int i = index >> 1;
+ u8 shift = (index & 0x01) ? 4 : 0;
+ data->tolerance[i] =
+ w83793_read_value(client, W83793_REG_TEMP_TOL(i));
+
+ val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x0f);
+ data->tolerance[i] &= ~(0x0f << shift);
+ data->tolerance[i] |= val << shift;
+ w83793_write_value(client, W83793_REG_TEMP_TOL(i),
+ data->tolerance[i]);
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t
+show_sf2_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+
+ return sprintf(buf, "%d\n", (data->sf2_pwm[index][nr] & 0x3f) << 2);
+}
+
+static ssize_t
+store_sf2_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff) >> 2;
+
+ mutex_lock(&data->update_lock);
+ data->sf2_pwm[index][nr] =
+ w83793_read_value(client, W83793_REG_SF2_PWM(index, nr)) & 0xc0;
+ data->sf2_pwm[index][nr] |= val;
+ w83793_write_value(client, W83793_REG_SF2_PWM(index, nr),
+ data->sf2_pwm[index][nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t
+show_sf2_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+
+ return sprintf(buf, "%ld\n",
+ TEMP_FROM_REG(data->sf2_temp[index][nr] & 0x7f));
+}
+
+static ssize_t
+store_sf2_temp(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ u8 val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x7f);
+
+ mutex_lock(&data->update_lock);
+ data->sf2_temp[index][nr] =
+ w83793_read_value(client, W83793_REG_SF2_TEMP(index, nr)) & 0x80;
+ data->sf2_temp[index][nr] |= val;
+ w83793_write_value(client, W83793_REG_SF2_TEMP(index, nr),
+ data->sf2_temp[index][nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/* only Vcore A/B and Vtt have additional 2 bits precision */
+static ssize_t
+show_in(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+ u16 val = data->in[index][nr];
+
+ if (index < 3) {
+ val <<= 2;
+ val += (data->in_low_bits[nr] >> (index * 2)) & 0x3;
+ }
+ return sprintf(buf, "%d\n", val * scale_in[index]);
+}
+
+static ssize_t
+store_in(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val =
+ (simple_strtoul(buf, NULL, 10) +
+ scale_in[index] / 2) / scale_in[index];
+ mutex_lock(&data->update_lock);
+ if (index > 2) {
+ val = SENSORS_LIMIT(val, 0, 255);
+ } else {
+ val = SENSORS_LIMIT(val, 0, 0x3FF);
+ data->in_low_bits[nr] =
+ w83793_read_value(client, W83793_REG_IN_LOW_BITS[nr]);
+ data->in_low_bits[nr] &= ~(0x03 << (2 * index));
+ data->in_low_bits[nr] |= (val & 0x03) << (2 * index);
+ w83793_write_value(client, W83793_REG_IN_LOW_BITS[nr],
+ data->in_low_bits[nr]);
+ val >>= 2;
+ }
+ data->in[index][nr] = val;
+ w83793_write_value(client, W83793_REG_IN[index][nr],
+ data->in[index][nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+#define NOT_USED -1
+
+#define SENSOR_ATTR_IN(index) \
+ SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \
+ IN_READ, index), \
+ SENSOR_ATTR_2(in##index##_max, S_IRUGO | S_IWUSR, show_in, \
+ store_in, IN_MAX, index), \
+ SENSOR_ATTR_2(in##index##_min, S_IRUGO | S_IWUSR, show_in, \
+ store_in, IN_LOW, index), \
+ SENSOR_ATTR_2(in##index##_alarm, S_IRUGO, show_alarm_beep, \
+ NULL, ALARM_STATUS, index + ((index > 2) ? 1 : 0)), \
+ SENSOR_ATTR_2(in##index##_beep, S_IWUSR | S_IRUGO, \
+ show_alarm_beep, store_beep, BEEP_ENABLE, \
+ index + ((index > 2) ? 1 : 0))
+
+#define SENSOR_ATTR_FAN(index) \
+ SENSOR_ATTR_2(fan##index##_alarm, S_IRUGO, show_alarm_beep, \
+ NULL, ALARM_STATUS, index + 17), \
+ SENSOR_ATTR_2(fan##index##_beep, S_IWUSR | S_IRUGO, \
+ show_alarm_beep, store_beep, BEEP_ENABLE, index + 17), \
+ SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan, \
+ NULL, FAN_INPUT, index - 1), \
+ SENSOR_ATTR_2(fan##index##_min, S_IWUSR | S_IRUGO, \
+ show_fan, store_fan_min, FAN_MIN, index - 1)
+
+#define SENSOR_ATTR_PWM(index) \
+ SENSOR_ATTR_2(pwm##index, S_IWUSR | S_IRUGO, show_pwm, \
+ store_pwm, PWM_DUTY, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_nonstop, S_IWUSR | S_IRUGO, \
+ show_pwm, store_pwm, PWM_NONSTOP, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_start, S_IWUSR | S_IRUGO, \
+ show_pwm, store_pwm, PWM_START, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_stop_time, S_IWUSR | S_IRUGO, \
+ show_pwm, store_pwm, PWM_STOP_TIME, index - 1)
+
+#define SENSOR_ATTR_TEMP(index) \
+ SENSOR_ATTR_2(temp##index##_type, S_IRUGO | S_IWUSR, \
+ show_temp_mode, store_temp_mode, NOT_USED, index - 1), \
+ SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \
+ NULL, TEMP_READ, index - 1), \
+ SENSOR_ATTR_2(temp##index##_max, S_IRUGO | S_IWUSR, show_temp, \
+ store_temp, TEMP_CRIT, index - 1), \
+ SENSOR_ATTR_2(temp##index##_max_hyst, S_IRUGO | S_IWUSR, \
+ show_temp, store_temp, TEMP_CRIT_HYST, index - 1), \
+ SENSOR_ATTR_2(temp##index##_warn, S_IRUGO | S_IWUSR, show_temp, \
+ store_temp, TEMP_WARN, index - 1), \
+ SENSOR_ATTR_2(temp##index##_warn_hyst, S_IRUGO | S_IWUSR, \
+ show_temp, store_temp, TEMP_WARN_HYST, index - 1), \
+ SENSOR_ATTR_2(temp##index##_alarm, S_IRUGO, \
+ show_alarm_beep, NULL, ALARM_STATUS, index + 11), \
+ SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \
+ show_alarm_beep, store_beep, BEEP_ENABLE, index + 11), \
+ SENSOR_ATTR_2(temp##index##_auto_channels_pwm, \
+ S_IRUGO | S_IWUSR, show_sf_ctrl, store_sf_ctrl, \
+ TEMP_FAN_MAP, index - 1), \
+ SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO, \
+ show_sf_ctrl, store_sf_ctrl, TEMP_PWM_ENABLE, \
+ index - 1), \
+ SENSOR_ATTR_2(thermal_cruise##index, S_IRUGO | S_IWUSR, \
+ show_sf_ctrl, store_sf_ctrl, TEMP_CRUISE, index - 1), \
+ SENSOR_ATTR_2(tolerance##index, S_IRUGO | S_IWUSR, show_sf_ctrl,\
+ store_sf_ctrl, TEMP_TOLERANCE, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point1_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 0, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point2_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 1, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point3_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 2, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point4_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 3, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point5_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 4, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point6_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 5, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point7_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 6, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point1_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 0, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point2_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 1, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point3_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 2, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point4_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 3, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point5_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 4, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point6_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 5, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point7_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 6, index - 1)
+
+static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = {
+ SENSOR_ATTR_IN(0),
+ SENSOR_ATTR_IN(1),
+ SENSOR_ATTR_IN(2),
+ SENSOR_ATTR_IN(3),
+ SENSOR_ATTR_IN(4),
+ SENSOR_ATTR_IN(5),
+ SENSOR_ATTR_IN(6),
+ SENSOR_ATTR_IN(7),
+ SENSOR_ATTR_IN(8),
+ SENSOR_ATTR_IN(9),
+ SENSOR_ATTR_TEMP(1),
+ SENSOR_ATTR_TEMP(2),
+ SENSOR_ATTR_TEMP(3),
+ SENSOR_ATTR_TEMP(4),
+ SENSOR_ATTR_TEMP(5),
+ SENSOR_ATTR_TEMP(6),
+ SENSOR_ATTR_FAN(1),
+ SENSOR_ATTR_FAN(2),
+ SENSOR_ATTR_FAN(3),
+ SENSOR_ATTR_FAN(4),
+ SENSOR_ATTR_FAN(5),
+ SENSOR_ATTR_PWM(1),
+ SENSOR_ATTR_PWM(2),
+ SENSOR_ATTR_PWM(3),
+};
+
+/* Fan6-Fan12 */
+static struct sensor_device_attribute_2 w83793_left_fan[] = {
+ SENSOR_ATTR_FAN(6),
+ SENSOR_ATTR_FAN(7),
+ SENSOR_ATTR_FAN(8),
+ SENSOR_ATTR_FAN(9),
+ SENSOR_ATTR_FAN(10),
+ SENSOR_ATTR_FAN(11),
+ SENSOR_ATTR_FAN(12),
+};
+
+/* Pwm4-Pwm8 */
+static struct sensor_device_attribute_2 w83793_left_pwm[] = {
+ SENSOR_ATTR_PWM(4),
+ SENSOR_ATTR_PWM(5),
+ SENSOR_ATTR_PWM(6),
+ SENSOR_ATTR_PWM(7),
+ SENSOR_ATTR_PWM(8),
+};
+
+static struct sensor_device_attribute_2 sda_single_files[] = {
+ SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0),
+ SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1),
+ SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm,
+ NOT_USED, NOT_USED),
+ SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
+ store_chassis_clear, ALARM_STATUS, 30),
+ SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable,
+ store_beep_enable, NOT_USED, NOT_USED),
+ SENSOR_ATTR_2(pwm_default, S_IWUSR | S_IRUGO, show_sf_setup,
+ store_sf_setup, SETUP_PWM_DEFAULT, NOT_USED),
+ SENSOR_ATTR_2(pwm_uptime, S_IWUSR | S_IRUGO, show_sf_setup,
+ store_sf_setup, SETUP_PWM_UPTIME, NOT_USED),
+ SENSOR_ATTR_2(pwm_downtime, S_IWUSR | S_IRUGO, show_sf_setup,
+ store_sf_setup, SETUP_PWM_DOWNTIME, NOT_USED),
+ SENSOR_ATTR_2(temp_critical, S_IWUSR | S_IRUGO, show_sf_setup,
+ store_sf_setup, SETUP_TEMP_CRITICAL, NOT_USED),
+};
+
+static void w83793_init_client(struct i2c_client *client)
+{
+ if (reset) {
+ w83793_write_value(client, W83793_REG_CONFIG, 0x80);
+ }
+
+ /* Start monitoring */
+ w83793_write_value(client, W83793_REG_CONFIG,
+ w83793_read_value(client, W83793_REG_CONFIG) | 0x01);
+
+}
+
+static int w83793_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_probe(adapter, &addr_data, w83793_detect);
+}
+
+static int w83793_detach_client(struct i2c_client *client)
+{
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct device *dev = &client->dev;
+ int err, i;
+
+ /* main client */
+ if (data) {
+ hwmon_device_unregister(data->class_dev);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
+ device_remove_file(dev,
+ &w83793_sensor_attr_2[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
+ device_remove_file(dev, &sda_single_files[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
+ device_remove_file(dev, &w83793_left_fan[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
+ device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+ }
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ /* main client */
+ if (data)
+ kfree(data);
+ /* subclient */
+ else
+ kfree(client);
+
+ return 0;
+}
+
+static int
+w83793_create_subclient(struct i2c_adapter *adapter,
+ struct i2c_client *client, int addr,
+ struct i2c_client **sub_cli)
+{
+ int err = 0;
+ struct i2c_client *sub_client;
+
+ (*sub_cli) = sub_client =
+ kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!(sub_client)) {
+ return -ENOMEM;
+ }
+ sub_client->addr = 0x48 + addr;
+ i2c_set_clientdata(sub_client, NULL);
+ sub_client->adapter = adapter;
+ sub_client->driver = &w83793_driver;
+ strlcpy(sub_client->name, "w83793 subclient", I2C_NAME_SIZE);
+ if ((err = i2c_attach_client(sub_client))) {
+ dev_err(&client->dev, "subclient registration "
+ "at address 0x%x failed\n", sub_client->addr);
+ kfree(sub_client);
+ }
+ return err;
+}
+
+static int
+w83793_detect_subclients(struct i2c_adapter *adapter, int address,
+ int kind, struct i2c_client *client)
+{
+ int i, id, err;
+ u8 tmp;
+ struct w83793_data *data = i2c_get_clientdata(client);
+
+ id = i2c_adapter_id(adapter);
+ if (force_subclients[0] == id && force_subclients[1] == address) {
+ for (i = 2; i <= 3; i++) {
+ if (force_subclients[i] < 0x48
+ || force_subclients[i] > 0x4f) {
+ dev_err(&client->dev,
+ "invalid subclient "
+ "address %d; must be 0x48-0x4f\n",
+ force_subclients[i]);
+ err = -EINVAL;
+ goto ERROR_SC_0;
+ }
+ }
+ w83793_write_value(client, W83793_REG_I2C_SUBADDR,
+ (force_subclients[2] & 0x07) |
+ ((force_subclients[3] & 0x07) << 4));
+ }
+
+ tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR);
+ if (!(tmp & 0x08)) {
+ err =
+ w83793_create_subclient(adapter, client, tmp & 0x7,
+ &data->lm75[0]);
+ if (err < 0)
+ goto ERROR_SC_0;
+ }
+ if (!(tmp & 0x80)) {
+ if ((data->lm75[0] != NULL)
+ && ((tmp & 0x7) == ((tmp >> 4) & 0x7))) {
+ dev_err(&client->dev,
+ "duplicate addresses 0x%x, "
+ "use force_subclients\n", data->lm75[0]->addr);
+ err = -ENODEV;
+ goto ERROR_SC_1;
+ }
+ err = w83793_create_subclient(adapter, client,
+ (tmp >> 4) & 0x7, &data->lm75[1]);
+ if (err < 0)
+ goto ERROR_SC_1;
+ }
+
+ return 0;
+
+ /* Undo inits in case of errors */
+
+ERROR_SC_1:
+ if (data->lm75[0] != NULL) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
+ERROR_SC_0:
+ return err;
+}
+
+static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ int i;
+ u8 tmp, val;
+ struct i2c_client *client;
+ struct device *dev;
+ struct w83793_data *data;
+ int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
+ int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5;
+ int err = 0;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ goto exit;
+ }
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access w83793_{read,write}_value. */
+
+ if (!(data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ client = &data->client;
+ dev = &client->dev;
+ i2c_set_clientdata(client, data);
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &w83793_driver;
+
+ data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
+
+ /* Now, we do the remaining detection. */
+ if (kind < 0) {
+ tmp = data->bank & 0x80 ? 0x5c : 0xa3;
+ /* Check Winbond vendor ID */
+ if (tmp != i2c_smbus_read_byte_data(client,
+ W83793_REG_VENDORID)) {
+ pr_debug("w83793: Detection failed at check "
+ "vendor id\n");
+ err = -ENODEV;
+ goto free_mem;
+ }
+
+ /* If Winbond chip, address of chip and W83793_REG_I2C_ADDR
+ should match */
+ if ((data->bank & 0x07) == 0
+ && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) !=
+ (address << 1)) {
+ pr_debug("w83793: Detection failed at check "
+ "i2c addr\n");
+ err = -ENODEV;
+ goto free_mem;
+ }
+
+ }
+
+ /* We have either had a force parameter, or we have already detected the
+ Winbond. Determine the chip type now */
+
+ if (kind <= 0) {
+ if (0x7b == w83793_read_value(client, W83793_REG_CHIPID)) {
+ kind = w83793;
+ } else {
+ if (kind == 0)
+ dev_warn(&adapter->dev, "w83793: Ignoring "
+ "'force' parameter for unknown chip "
+ "at address 0x%02x\n", address);
+ err = -ENODEV;
+ goto free_mem;
+ }
+ }
+
+ /* Fill in the remaining client fields and put into the global list */
+ strlcpy(client->name, "w83793", I2C_NAME_SIZE);
+
+ mutex_init(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(client)))
+ goto free_mem;
+
+ if ((err = w83793_detect_subclients(adapter, address, kind, client)))
+ goto detach_client;
+
+ /* Initialize the chip */
+ w83793_init_client(client);
+
+ data->vrm = vid_which_vrm();
+ /*
+ Only fan 1-5 has their own input pins,
+ Pwm 1-3 has their own pins
+ */
+ data->has_fan = 0x1f;
+ data->has_pwm = 0x07;
+ tmp = w83793_read_value(client, W83793_REG_MFC);
+ val = w83793_read_value(client, W83793_REG_FANIN_CTRL);
+
+ /* check the function of pins 49-56 */
+ if (!(tmp & 0x80)) {
+ data->has_pwm |= 0x18; /* pwm 4,5 */
+ if (val & 0x01) { /* fan 6 */
+ data->has_fan |= 0x20;
+ data->has_pwm |= 0x20;
+ }
+ if (val & 0x02) { /* fan 7 */
+ data->has_fan |= 0x40;
+ data->has_pwm |= 0x40;
+ }
+ if (!(tmp & 0x40) && (val & 0x04)) { /* fan 8 */
+ data->has_fan |= 0x80;
+ data->has_pwm |= 0x80;
+ }
+ }
+
+ if (0x08 == (tmp & 0x0c)) {
+ if (val & 0x08) /* fan 9 */
+ data->has_fan |= 0x100;
+ if (val & 0x10) /* fan 10 */
+ data->has_fan |= 0x200;
+ }
+
+ if (0x20 == (tmp & 0x30)) {
+ if (val & 0x20) /* fan 11 */
+ data->has_fan |= 0x400;
+ if (val & 0x40) /* fan 12 */
+ data->has_fan |= 0x800;
+ }
+
+ if ((tmp & 0x01) && (val & 0x04)) { /* fan 8, second location */
+ data->has_fan |= 0x80;
+ data->has_pwm |= 0x80;
+ }
+
+ /* Register sysfs hooks */
+ for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) {
+ err = device_create_file(dev,
+ &w83793_sensor_attr_2[i].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
+ err = device_create_file(dev, &sda_single_files[i].dev_attr);
+ if (err)
+ goto exit_remove;
+
+ }
+
+ for (i = 5; i < 12; i++) {
+ int j;
+ if (!(data->has_fan & (1 << i)))
+ continue;
+ for (j = 0; j < files_fan; j++) {
+ err = device_create_file(dev,
+ &w83793_left_fan[(i - 5) * files_fan
+ + j].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+ }
+
+ for (i = 3; i < 8; i++) {
+ int j;
+ if (!(data->has_pwm & (1 << i)))
+ continue;
+ for (j = 0; j < files_pwm; j++) {
+ err = device_create_file(dev,
+ &w83793_left_pwm[(i - 3) * files_pwm
+ + j].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+ }
+
+ data->class_dev = hwmon_device_register(dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_remove;
+ }
+
+ return 0;
+
+ /* Unregister sysfs hooks */
+
+exit_remove:
+ for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
+ device_remove_file(dev, &w83793_sensor_attr_2[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
+ device_remove_file(dev, &sda_single_files[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
+ device_remove_file(dev, &w83793_left_fan[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
+ device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+
+ if (data->lm75[0] != NULL) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
+ if (data->lm75[1] != NULL) {
+ i2c_detach_client(data->lm75[1]);
+ kfree(data->lm75[1]);
+ }
+detach_client:
+ i2c_detach_client(client);
+free_mem:
+ kfree(data);
+exit:
+ return err;
+}
+
+static void w83793_update_nonvolatile(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ int i, j;
+ /*
+ They are somewhat "stable" registers, and to update them everytime
+ takes so much time, it's just not worthy. Update them in a long
+ interval to avoid exception.
+ */
+ if (!(time_after(jiffies, data->last_nonvolatile + HZ * 300)
+ || !data->valid))
+ return;
+ /* update voltage limits */
+ for (i = 1; i < 3; i++) {
+ for (j = 0; j < ARRAY_SIZE(data->in); j++) {
+ data->in[j][i] =
+ w83793_read_value(client, W83793_REG_IN[j][i]);
+ }
+ data->in_low_bits[i] =
+ w83793_read_value(client, W83793_REG_IN_LOW_BITS[i]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
+ /* Update the Fan measured value and limits */
+ if (!(data->has_fan & (1 << i))) {
+ continue;
+ }
+ data->fan_min[i] =
+ w83793_read_value(client, W83793_REG_FAN_MIN(i)) << 8;
+ data->fan_min[i] |=
+ w83793_read_value(client, W83793_REG_FAN_MIN(i) + 1);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) {
+ data->temp_fan_map[i] =
+ w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i));
+ for (j = 1; j < 5; j++) {
+ data->temp[i][j] =
+ w83793_read_value(client, W83793_REG_TEMP[i][j]);
+ }
+ data->temp_cruise[i] =
+ w83793_read_value(client, W83793_REG_TEMP_CRUISE(i));
+ for (j = 0; j < 7; j++) {
+ data->sf2_pwm[i][j] =
+ w83793_read_value(client, W83793_REG_SF2_PWM(i, j));
+ data->sf2_temp[i][j] =
+ w83793_read_value(client,
+ W83793_REG_SF2_TEMP(i, j));
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->temp_mode); i++)
+ data->temp_mode[i] =
+ w83793_read_value(client, W83793_REG_TEMP_MODE[i]);
+
+ for (i = 0; i < ARRAY_SIZE(data->tolerance); i++) {
+ data->tolerance[i] =
+ w83793_read_value(client, W83793_REG_TEMP_TOL(i));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->pwm); i++) {
+ if (!(data->has_pwm & (1 << i)))
+ continue;
+ data->pwm[i][PWM_NONSTOP] =
+ w83793_read_value(client, W83793_REG_PWM(i, PWM_NONSTOP));
+ data->pwm[i][PWM_START] =
+ w83793_read_value(client, W83793_REG_PWM(i, PWM_START));
+ data->pwm_stop_time[i] =
+ w83793_read_value(client, W83793_REG_PWM_STOP_TIME(i));
+ }
+
+ data->pwm_default = w83793_read_value(client, W83793_REG_PWM_DEFAULT);
+ data->pwm_enable = w83793_read_value(client, W83793_REG_PWM_ENABLE);
+ data->pwm_uptime = w83793_read_value(client, W83793_REG_PWM_UPTIME);
+ data->pwm_downtime = w83793_read_value(client, W83793_REG_PWM_DOWNTIME);
+ data->temp_critical =
+ w83793_read_value(client, W83793_REG_TEMP_CRITICAL);
+ data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP);
+
+ for (i = 0; i < ARRAY_SIZE(data->beeps); i++) {
+ data->beeps[i] = w83793_read_value(client, W83793_REG_BEEP(i));
+ }
+
+ data->last_nonvolatile = jiffies;
+}
+
+static struct w83793_data *w83793_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ int i;
+
+ mutex_lock(&data->update_lock);
+
+ if (!(time_after(jiffies, data->last_updated + HZ * 2)
+ || !data->valid))
+ goto END;
+
+ /* Update the voltages measured value and limits */
+ for (i = 0; i < ARRAY_SIZE(data->in); i++)
+ data->in[i][IN_READ] =
+ w83793_read_value(client, W83793_REG_IN[i][IN_READ]);
+
+ data->in_low_bits[IN_READ] =
+ w83793_read_value(client, W83793_REG_IN_LOW_BITS[IN_READ]);
+
+ for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
+ if (!(data->has_fan & (1 << i))) {
+ continue;
+ }
+ data->fan[i] =
+ w83793_read_value(client, W83793_REG_FAN(i)) << 8;
+ data->fan[i] |=
+ w83793_read_value(client, W83793_REG_FAN(i) + 1);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->temp); i++)
+ data->temp[i][TEMP_READ] =
+ w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]);
+
+ data->temp_low_bits =
+ w83793_read_value(client, W83793_REG_TEMP_LOW_BITS);
+
+ for (i = 0; i < ARRAY_SIZE(data->pwm); i++) {
+ if (data->has_pwm & (1 << i))
+ data->pwm[i][PWM_DUTY] =
+ w83793_read_value(client,
+ W83793_REG_PWM(i, PWM_DUTY));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
+ data->alarms[i] =
+ w83793_read_value(client, W83793_REG_ALARM(i));
+ data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
+ data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
+ w83793_update_nonvolatile(dev);
+ data->last_updated = jiffies;
+ data->valid = 1;
+
+END:
+ mutex_unlock(&data->update_lock);
+ return data;
+}
+
+/* Ignore the possibility that somebody change bank outside the driver
+ Must be called with data->update_lock held, except during initialization */
+static u8 w83793_read_value(struct i2c_client *client, u16 reg)
+{
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u8 res = 0xff;
+ u8 new_bank = reg >> 8;
+
+ new_bank |= data->bank & 0xfc;
+ if (data->bank != new_bank) {
+ if (i2c_smbus_write_byte_data
+ (client, W83793_REG_BANKSEL, new_bank) >= 0)
+ data->bank = new_bank;
+ else {
+ dev_err(&client->dev,
+ "set bank to %d failed, fall back "
+ "to bank %d, read reg 0x%x error\n",
+ new_bank, data->bank, reg);
+ res = 0x0; /* read 0x0 from the chip */
+ goto END;
+ }
+ }
+ res = i2c_smbus_read_byte_data(client, reg & 0xff);
+END:
+ return res;
+}
+
+/* Must be called with data->update_lock held, except during initialization */
+static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value)
+{
+ struct w83793_data *data = i2c_get_clientdata(client);
+ int res;
+ u8 new_bank = reg >> 8;
+
+ new_bank |= data->bank & 0xfc;
+ if (data->bank != new_bank) {
+ if ((res = i2c_smbus_write_byte_data
+ (client, W83793_REG_BANKSEL, new_bank)) >= 0)
+ data->bank = new_bank;
+ else {
+ dev_err(&client->dev,
+ "set bank to %d failed, fall back "
+ "to bank %d, write reg 0x%x error\n",
+ new_bank, data->bank, reg);
+ goto END;
+ }
+ }
+
+ res = i2c_smbus_write_byte_data(client, reg & 0xff, value);
+END:
+ return res;
+}
+
+static int __init sensors_w83793_init(void)
+{
+ return i2c_add_driver(&w83793_driver);
+}
+
+static void __exit sensors_w83793_exit(void)
+{
+ i2c_del_driver(&w83793_driver);
+}
+
+MODULE_AUTHOR("Yuan Mu");
+MODULE_DESCRIPTION("w83793 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83793_init);
+module_exit(sensors_w83793_exit);
* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
*
* Copyright (C) 2004 Patrick Mochel
- * 2005 Rudolf Marek <r.marek@sh.cvut.cz>
+ * 2005 Rudolf Marek <r.marek@assembler.cz>
*
* The 1563 southbridge is deceptively similar to the 1533, with a
* few notable exceptions. One of those happens to be the fact they
struct i2c_client client;
struct mutex lock;
int irq;
- struct work_struct work;
+ struct delayed_work work;
struct dentry *file;
unsigned charging:1;
unsigned por:1;
{
u8 tmp = 0, mask, poll;
- /* IRQs won't trigger irqs for certain events, but we can get
+ /* IRQs won't trigger for certain events, but we can get
* others by polling (normally, with external power applied).
*/
poll = 0;
}
/* handle IRQs and polling using keventd for now */
-static void tps65010_work(void *_tps)
+static void tps65010_work(struct work_struct *work)
{
- struct tps65010 *tps = _tps;
+ struct tps65010 *tps;
+ tps = container_of(work, struct tps65010, work.work);
mutex_lock(&tps->lock);
tps65010_interrupt(tps);
disable_irq_nosync(irq);
set_bit(FLAG_IRQ_ENABLE, &tps->flags);
- (void) schedule_work(&tps->work);
+ (void) schedule_work(&tps->work.work);
return IRQ_HANDLED;
}
struct tps65010 *tps;
tps = container_of(client, struct tps65010, client);
+ free_irq(tps->irq, tps);
#ifdef CONFIG_ARM
if (machine_is_omap_h2())
omap_free_gpio(58);
if (machine_is_omap_osk())
omap_free_gpio(OMAP_MPUIO(1));
#endif
- free_irq(tps->irq, tps);
+ cancel_delayed_work(&tps->work);
+ flush_scheduled_work();
debugfs_remove(tps->file);
if (i2c_detach_client(client) == 0)
kfree(tps);
return 0;
mutex_init(&tps->lock);
- INIT_WORK(&tps->work, tps65010_work, tps);
+ INIT_DELAYED_WORK(&tps->work, tps65010_work);
tps->irq = -1;
tps->client.addr = address;
tps->client.adapter = bus;
(void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK3, 0x0f
| i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
- tps65010_work(tps);
+ tps65010_work(&tps->work.work);
tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
tps, DEBUG_FOPS);
&& test_and_set_bit(
FLAG_VBUS_CHANGED, &the_tps->flags)) {
/* gadget drivers call this in_irq() */
- (void) schedule_work(&the_tps->work);
+ (void) schedule_work(&the_tps->work.work);
}
local_irq_restore(flags);
printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
goto failed;
}
- if ((floppy = (idefloppy_floppy_t *) kzalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
+ if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
goto failed;
}
int pages = tape->pages_per_stage;
char *b_data = NULL;
- if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
+ if ((stage = kmalloc(sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
return NULL;
stage->next = NULL;
- bh = stage->bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
+ bh = stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
if (bh == NULL)
goto abort;
bh->b_reqnext = NULL;
continue;
}
prev_bh = bh;
- if ((bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
+ if ((bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
free_page((unsigned long) b_data);
goto abort;
}
printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
}
- tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL);
+ tape = kzalloc(sizeof (idetape_tape_t), GFP_KERNEL);
if (tape == NULL) {
printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
goto failed;
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
+ * Portions Copyright (C) 2005-2006 MontaVista Software, Inc.
*
* Thanks to HighPoint Technologies for their assistance, and hardware.
* Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
* development and support.
*
*
- * Highpoint have their own driver (source except for the raid part)
- * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz
- * This may be useful to anyone wanting to work on the mainstream hpt IDE.
+ * HighPoint has its own drivers (open source except for the RAID part)
+ * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/.
+ * This may be useful to anyone wanting to work on this driver, however do not
+ * trust them too much since the code tends to become less and less meaningful
+ * as the time passes... :-/
*
* Note that final HPT370 support was done by force extraction of GPL.
*
* keeping me sane.
* Alan Cox <alan@redhat.com>
*
+ * - fix the clock turnaround code: it was writing to the wrong ports when
+ * called for the secondary channel, caching the current clock mode per-
+ * channel caused the cached register value to get out of sync with the
+ * actual one, the channels weren't serialized, the turnaround shouldn't
+ * be done on 66 MHz PCI bus
+ * - avoid calibrating PLL twice as the second time results in a wrong PCI
+ * frequency and thus in the wrong timings for the secondary channel
+ * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not
+ * allow for this speed anyway)
+ * - add support for HPT302N and HPT371N clocking (the same as for HPT372N)
+ * - HPT371/N are single channel chips, so avoid touching the primary channel
+ * which exists only virtually (there's no pins for it)
+ * - fix/remove bad/unused timing tables and use one set of tables for the whole
+ * HPT37x chip family; save space by introducing the separate transfer mode
+ * table in which the mode lookup is done
+ * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives
+ * the wrong PCI frequency since DPLL has already been calibrated by BIOS
+ * - fix the hotswap code: it caused RESET- to glitch when tristating the bus,
+ * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
+ * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
+ * they tamper with its fields
+ * <source@mvista.com>
+ *
*/
/* various tuning parameters */
#define HPT_RESET_STATE_ENGINE
-#undef HPT_DELAY_INTERRUPT
-#undef HPT_SERIALIZE_IO
+#undef HPT_DELAY_INTERRUPT
+#define HPT_SERIALIZE_IO 0
static const char *quirk_drives[] = {
"QUANTUM FIREBALLlct08 08",
NULL
};
-struct chipset_bus_clock_list_entry {
- u8 xfer_speed;
- unsigned int chipset_settings;
+static u8 xfer_speeds[] = {
+ XFER_UDMA_6,
+ XFER_UDMA_5,
+ XFER_UDMA_4,
+ XFER_UDMA_3,
+ XFER_UDMA_2,
+ XFER_UDMA_1,
+ XFER_UDMA_0,
+
+ XFER_MW_DMA_2,
+ XFER_MW_DMA_1,
+ XFER_MW_DMA_0,
+
+ XFER_PIO_4,
+ XFER_PIO_3,
+ XFER_PIO_2,
+ XFER_PIO_1,
+ XFER_PIO_0
};
-/* key for bus clock timings
- * bit
- * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
- * DMA. cycles = value + 1
- * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW
- * DMA. cycles = value + 1
- * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file
- * register access.
- * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file
- * register access.
- * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer.
- * during task file register access.
- * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA
- * xfer.
- * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task
- * register access.
- * 28 UDMA enable
- * 29 DMA enable
- * 30 PIO_MST enable. if set, the chip is in bus master mode during
- * PIO.
- * 31 FIFO enable.
+/* Key for bus clock timings
+ * 36x 37x
+ * bits bits
+ * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
+ * cycles = value + 1
+ * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
+ * cycles = value + 1
+ * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
+ * register access.
+ * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file
+ * register access.
+ * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer.
+ * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock.
+ * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and
+ * MW DMA xfer.
+ * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for
+ * task file register access.
+ * 28 28 UDMA enable.
+ * 29 29 DMA enable.
+ * 30 30 PIO MST enable. If set, the chip is in bus master mode during
+ * PIO xfer.
+ * 31 31 FIFO enable.
*/
-static struct chipset_bus_clock_list_entry forty_base_hpt366[] = {
- { XFER_UDMA_4, 0x900fd943 },
- { XFER_UDMA_3, 0x900ad943 },
- { XFER_UDMA_2, 0x900bd943 },
- { XFER_UDMA_1, 0x9008d943 },
- { XFER_UDMA_0, 0x9008d943 },
-
- { XFER_MW_DMA_2, 0xa008d943 },
- { XFER_MW_DMA_1, 0xa010d955 },
- { XFER_MW_DMA_0, 0xa010d9fc },
-
- { XFER_PIO_4, 0xc008d963 },
- { XFER_PIO_3, 0xc010d974 },
- { XFER_PIO_2, 0xc010d997 },
- { XFER_PIO_1, 0xc010d9c7 },
- { XFER_PIO_0, 0xc018d9d9 },
- { 0, 0x0120d9d9 }
-};
-
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = {
- { XFER_UDMA_4, 0x90c9a731 },
- { XFER_UDMA_3, 0x90cfa731 },
- { XFER_UDMA_2, 0x90caa731 },
- { XFER_UDMA_1, 0x90cba731 },
- { XFER_UDMA_0, 0x90c8a731 },
-
- { XFER_MW_DMA_2, 0xa0c8a731 },
- { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */
- { XFER_MW_DMA_0, 0xa0c8a797 },
-
- { XFER_PIO_4, 0xc0c8a731 },
- { XFER_PIO_3, 0xc0c8a742 },
- { XFER_PIO_2, 0xc0d0a753 },
- { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */
- { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */
- { 0, 0x0120a7a7 }
-};
-
-static struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = {
- { XFER_UDMA_4, 0x90c98521 },
- { XFER_UDMA_3, 0x90cf8521 },
- { XFER_UDMA_2, 0x90cf8521 },
- { XFER_UDMA_1, 0x90cb8521 },
- { XFER_UDMA_0, 0x90cb8521 },
-
- { XFER_MW_DMA_2, 0xa0ca8521 },
- { XFER_MW_DMA_1, 0xa0ca8532 },
- { XFER_MW_DMA_0, 0xa0ca8575 },
-
- { XFER_PIO_4, 0xc0ca8521 },
- { XFER_PIO_3, 0xc0ca8532 },
- { XFER_PIO_2, 0xc0ca8542 },
- { XFER_PIO_1, 0xc0d08572 },
- { XFER_PIO_0, 0xc0d08585 },
- { 0, 0x01208585 }
-};
-
-/* from highpoint documentation. these are old values */
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = {
-/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */
- { XFER_UDMA_5, 0x16454e31 },
- { XFER_UDMA_4, 0x16454e31 },
- { XFER_UDMA_3, 0x166d4e31 },
- { XFER_UDMA_2, 0x16494e31 },
- { XFER_UDMA_1, 0x164d4e31 },
- { XFER_UDMA_0, 0x16514e31 },
-
- { XFER_MW_DMA_2, 0x26514e21 },
- { XFER_MW_DMA_1, 0x26514e33 },
- { XFER_MW_DMA_0, 0x26514e97 },
-
- { XFER_PIO_4, 0x06514e21 },
- { XFER_PIO_3, 0x06514e22 },
- { XFER_PIO_2, 0x06514e33 },
- { XFER_PIO_1, 0x06914e43 },
- { XFER_PIO_0, 0x06914e57 },
- { 0, 0x06514e57 }
-};
-
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = {
- { XFER_UDMA_5, 0x14846231 },
- { XFER_UDMA_4, 0x14886231 },
- { XFER_UDMA_3, 0x148c6231 },
- { XFER_UDMA_2, 0x148c6231 },
- { XFER_UDMA_1, 0x14906231 },
- { XFER_UDMA_0, 0x14986231 },
-
- { XFER_MW_DMA_2, 0x26514e21 },
- { XFER_MW_DMA_1, 0x26514e33 },
- { XFER_MW_DMA_0, 0x26514e97 },
-
- { XFER_PIO_4, 0x06514e21 },
- { XFER_PIO_3, 0x06514e22 },
- { XFER_PIO_2, 0x06514e33 },
- { XFER_PIO_1, 0x06914e43 },
- { XFER_PIO_0, 0x06914e57 },
- { 0, 0x06514e57 }
-};
-
-/* these are the current (4 sep 2001) timings from highpoint */
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = {
- { XFER_UDMA_5, 0x12446231 },
- { XFER_UDMA_4, 0x12446231 },
- { XFER_UDMA_3, 0x126c6231 },
- { XFER_UDMA_2, 0x12486231 },
- { XFER_UDMA_1, 0x124c6233 },
- { XFER_UDMA_0, 0x12506297 },
-
- { XFER_MW_DMA_2, 0x22406c31 },
- { XFER_MW_DMA_1, 0x22406c33 },
- { XFER_MW_DMA_0, 0x22406c97 },
-
- { XFER_PIO_4, 0x06414e31 },
- { XFER_PIO_3, 0x06414e42 },
- { XFER_PIO_2, 0x06414e53 },
- { XFER_PIO_1, 0x06814e93 },
- { XFER_PIO_0, 0x06814ea7 },
- { 0, 0x06814ea7 }
-};
-
-/* 2x 33MHz timings */
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = {
- { XFER_UDMA_5, 0x1488e673 },
- { XFER_UDMA_4, 0x1488e673 },
- { XFER_UDMA_3, 0x1498e673 },
- { XFER_UDMA_2, 0x1490e673 },
- { XFER_UDMA_1, 0x1498e677 },
- { XFER_UDMA_0, 0x14a0e73f },
-
- { XFER_MW_DMA_2, 0x2480fa73 },
- { XFER_MW_DMA_1, 0x2480fa77 },
- { XFER_MW_DMA_0, 0x2480fb3f },
-
- { XFER_PIO_4, 0x0c82be73 },
- { XFER_PIO_3, 0x0c82be95 },
- { XFER_PIO_2, 0x0c82beb7 },
- { XFER_PIO_1, 0x0d02bf37 },
- { XFER_PIO_0, 0x0d02bf5f },
- { 0, 0x0d02bf5f }
-};
-static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = {
- { XFER_UDMA_5, 0x12848242 },
- { XFER_UDMA_4, 0x12ac8242 },
- { XFER_UDMA_3, 0x128c8242 },
- { XFER_UDMA_2, 0x120c8242 },
- { XFER_UDMA_1, 0x12148254 },
- { XFER_UDMA_0, 0x121882ea },
-
- { XFER_MW_DMA_2, 0x22808242 },
- { XFER_MW_DMA_1, 0x22808254 },
- { XFER_MW_DMA_0, 0x228082ea },
-
- { XFER_PIO_4, 0x0a81f442 },
- { XFER_PIO_3, 0x0a81f443 },
- { XFER_PIO_2, 0x0a81f454 },
- { XFER_PIO_1, 0x0ac1f465 },
- { XFER_PIO_0, 0x0ac1f48a },
- { 0, 0x0ac1f48a }
+static u32 forty_base_hpt36x[] = {
+ /* XFER_UDMA_6 */ 0x900fd943,
+ /* XFER_UDMA_5 */ 0x900fd943,
+ /* XFER_UDMA_4 */ 0x900fd943,
+ /* XFER_UDMA_3 */ 0x900ad943,
+ /* XFER_UDMA_2 */ 0x900bd943,
+ /* XFER_UDMA_1 */ 0x9008d943,
+ /* XFER_UDMA_0 */ 0x9008d943,
+
+ /* XFER_MW_DMA_2 */ 0xa008d943,
+ /* XFER_MW_DMA_1 */ 0xa010d955,
+ /* XFER_MW_DMA_0 */ 0xa010d9fc,
+
+ /* XFER_PIO_4 */ 0xc008d963,
+ /* XFER_PIO_3 */ 0xc010d974,
+ /* XFER_PIO_2 */ 0xc010d997,
+ /* XFER_PIO_1 */ 0xc010d9c7,
+ /* XFER_PIO_0 */ 0xc018d9d9
};
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = {
- { XFER_UDMA_6, 0x1c81dc62 },
- { XFER_UDMA_5, 0x1c6ddc62 },
- { XFER_UDMA_4, 0x1c8ddc62 },
- { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */
- { XFER_UDMA_2, 0x1c91dc62 },
- { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */
- { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */
-
- { XFER_MW_DMA_2, 0x2c829262 },
- { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */
- { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */
-
- { XFER_PIO_4, 0x0c829c62 },
- { XFER_PIO_3, 0x0c829c84 },
- { XFER_PIO_2, 0x0c829ca6 },
- { XFER_PIO_1, 0x0d029d26 },
- { XFER_PIO_0, 0x0d029d5e },
- { 0, 0x0d029d5e }
+static u32 thirty_three_base_hpt36x[] = {
+ /* XFER_UDMA_6 */ 0x90c9a731,
+ /* XFER_UDMA_5 */ 0x90c9a731,
+ /* XFER_UDMA_4 */ 0x90c9a731,
+ /* XFER_UDMA_3 */ 0x90cfa731,
+ /* XFER_UDMA_2 */ 0x90caa731,
+ /* XFER_UDMA_1 */ 0x90cba731,
+ /* XFER_UDMA_0 */ 0x90c8a731,
+
+ /* XFER_MW_DMA_2 */ 0xa0c8a731,
+ /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */
+ /* XFER_MW_DMA_0 */ 0xa0c8a797,
+
+ /* XFER_PIO_4 */ 0xc0c8a731,
+ /* XFER_PIO_3 */ 0xc0c8a742,
+ /* XFER_PIO_2 */ 0xc0d0a753,
+ /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */
+ /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */
};
-static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = {
- { XFER_UDMA_5, 0x12848242 },
- { XFER_UDMA_4, 0x12ac8242 },
- { XFER_UDMA_3, 0x128c8242 },
- { XFER_UDMA_2, 0x120c8242 },
- { XFER_UDMA_1, 0x12148254 },
- { XFER_UDMA_0, 0x121882ea },
-
- { XFER_MW_DMA_2, 0x22808242 },
- { XFER_MW_DMA_1, 0x22808254 },
- { XFER_MW_DMA_0, 0x228082ea },
-
- { XFER_PIO_4, 0x0a81f442 },
- { XFER_PIO_3, 0x0a81f443 },
- { XFER_PIO_2, 0x0a81f454 },
- { XFER_PIO_1, 0x0ac1f465 },
- { XFER_PIO_0, 0x0ac1f48a },
- { 0, 0x0a81f443 }
+static u32 twenty_five_base_hpt36x[] = {
+ /* XFER_UDMA_6 */ 0x90c98521,
+ /* XFER_UDMA_5 */ 0x90c98521,
+ /* XFER_UDMA_4 */ 0x90c98521,
+ /* XFER_UDMA_3 */ 0x90cf8521,
+ /* XFER_UDMA_2 */ 0x90cf8521,
+ /* XFER_UDMA_1 */ 0x90cb8521,
+ /* XFER_UDMA_0 */ 0x90cb8521,
+
+ /* XFER_MW_DMA_2 */ 0xa0ca8521,
+ /* XFER_MW_DMA_1 */ 0xa0ca8532,
+ /* XFER_MW_DMA_0 */ 0xa0ca8575,
+
+ /* XFER_PIO_4 */ 0xc0ca8521,
+ /* XFER_PIO_3 */ 0xc0ca8532,
+ /* XFER_PIO_2 */ 0xc0ca8542,
+ /* XFER_PIO_1 */ 0xc0d08572,
+ /* XFER_PIO_0 */ 0xc0d08585
};
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = {
- { XFER_UDMA_6, 0x1c869c62 },
- { XFER_UDMA_5, 0x1cae9c62 },
- { XFER_UDMA_4, 0x1c8a9c62 },
- { XFER_UDMA_3, 0x1c8e9c62 },
- { XFER_UDMA_2, 0x1c929c62 },
- { XFER_UDMA_1, 0x1c9a9c62 },
- { XFER_UDMA_0, 0x1c829c62 },
-
- { XFER_MW_DMA_2, 0x2c829c62 },
- { XFER_MW_DMA_1, 0x2c829c66 },
- { XFER_MW_DMA_0, 0x2c829d2e },
-
- { XFER_PIO_4, 0x0c829c62 },
- { XFER_PIO_3, 0x0c829c84 },
- { XFER_PIO_2, 0x0c829ca6 },
- { XFER_PIO_1, 0x0d029d26 },
- { XFER_PIO_0, 0x0d029d5e },
- { 0, 0x0d029d26 }
+static u32 thirty_three_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */
+ /* XFER_UDMA_5 */ 0x12446231,
+ /* XFER_UDMA_4 */ 0x12446231,
+ /* XFER_UDMA_3 */ 0x126c6231,
+ /* XFER_UDMA_2 */ 0x12486231,
+ /* XFER_UDMA_1 */ 0x124c6233,
+ /* XFER_UDMA_0 */ 0x12506297,
+
+ /* XFER_MW_DMA_2 */ 0x22406c31,
+ /* XFER_MW_DMA_1 */ 0x22406c33,
+ /* XFER_MW_DMA_0 */ 0x22406c97,
+
+ /* XFER_PIO_4 */ 0x06414e31,
+ /* XFER_PIO_3 */ 0x06414e42,
+ /* XFER_PIO_2 */ 0x06414e53,
+ /* XFER_PIO_1 */ 0x06814e93,
+ /* XFER_PIO_0 */ 0x06814ea7
};
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = {
- { XFER_UDMA_6, 0x12808242 },
- { XFER_UDMA_5, 0x12848242 },
- { XFER_UDMA_4, 0x12ac8242 },
- { XFER_UDMA_3, 0x128c8242 },
- { XFER_UDMA_2, 0x120c8242 },
- { XFER_UDMA_1, 0x12148254 },
- { XFER_UDMA_0, 0x121882ea },
-
- { XFER_MW_DMA_2, 0x22808242 },
- { XFER_MW_DMA_1, 0x22808254 },
- { XFER_MW_DMA_0, 0x228082ea },
-
- { XFER_PIO_4, 0x0a81f442 },
- { XFER_PIO_3, 0x0a81f443 },
- { XFER_PIO_2, 0x0a81f454 },
- { XFER_PIO_1, 0x0ac1f465 },
- { XFER_PIO_0, 0x0ac1f48a },
- { 0, 0x06814e93 }
+static u32 fifty_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x12848242,
+ /* XFER_UDMA_5 */ 0x12848242,
+ /* XFER_UDMA_4 */ 0x12ac8242,
+ /* XFER_UDMA_3 */ 0x128c8242,
+ /* XFER_UDMA_2 */ 0x120c8242,
+ /* XFER_UDMA_1 */ 0x12148254,
+ /* XFER_UDMA_0 */ 0x121882ea,
+
+ /* XFER_MW_DMA_2 */ 0x22808242,
+ /* XFER_MW_DMA_1 */ 0x22808254,
+ /* XFER_MW_DMA_0 */ 0x228082ea,
+
+ /* XFER_PIO_4 */ 0x0a81f442,
+ /* XFER_PIO_3 */ 0x0a81f443,
+ /* XFER_PIO_2 */ 0x0a81f454,
+ /* XFER_PIO_1 */ 0x0ac1f465,
+ /* XFER_PIO_0 */ 0x0ac1f48a
};
-/* FIXME: 50MHz timings for HPT374 */
-
-#if 0
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = {
- { XFER_UDMA_6, 0x12406231 }, /* checkme */
- { XFER_UDMA_5, 0x12446231 }, /* 0x14846231 */
- { XFER_UDMA_4, 0x16814ea7 }, /* 0x14886231 */
- { XFER_UDMA_3, 0x16814ea7 }, /* 0x148c6231 */
- { XFER_UDMA_2, 0x16814ea7 }, /* 0x148c6231 */
- { XFER_UDMA_1, 0x16814ea7 }, /* 0x14906231 */
- { XFER_UDMA_0, 0x16814ea7 }, /* 0x14986231 */
- { XFER_MW_DMA_2, 0x16814ea7 }, /* 0x26514e21 */
- { XFER_MW_DMA_1, 0x16814ea7 }, /* 0x26514e97 */
- { XFER_MW_DMA_0, 0x16814ea7 }, /* 0x26514e97 */
- { XFER_PIO_4, 0x06814ea7 }, /* 0x06514e21 */
- { XFER_PIO_3, 0x06814ea7 }, /* 0x06514e22 */
- { XFER_PIO_2, 0x06814ea7 }, /* 0x06514e33 */
- { XFER_PIO_1, 0x06814ea7 }, /* 0x06914e43 */
- { XFER_PIO_0, 0x06814ea7 }, /* 0x06914e57 */
- { 0, 0x06814ea7 }
+static u32 sixty_six_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x1c869c62,
+ /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */
+ /* XFER_UDMA_4 */ 0x1c8a9c62,
+ /* XFER_UDMA_3 */ 0x1c8e9c62,
+ /* XFER_UDMA_2 */ 0x1c929c62,
+ /* XFER_UDMA_1 */ 0x1c9a9c62,
+ /* XFER_UDMA_0 */ 0x1c829c62,
+
+ /* XFER_MW_DMA_2 */ 0x2c829c62,
+ /* XFER_MW_DMA_1 */ 0x2c829c66,
+ /* XFER_MW_DMA_0 */ 0x2c829d2e,
+
+ /* XFER_PIO_4 */ 0x0c829c62,
+ /* XFER_PIO_3 */ 0x0c829c84,
+ /* XFER_PIO_2 */ 0x0c829ca6,
+ /* XFER_PIO_1 */ 0x0d029d26,
+ /* XFER_PIO_0 */ 0x0d029d5e
};
-#endif
#define HPT366_DEBUG_DRIVE_INFO 0
#define HPT374_ALLOW_ATA133_6 0
#define HPT371_ALLOW_ATA133_6 0
#define HPT302_ALLOW_ATA133_6 0
-#define HPT372_ALLOW_ATA133_6 1
+#define HPT372_ALLOW_ATA133_6 0
#define HPT370_ALLOW_ATA100_5 1
#define HPT366_ALLOW_ATA66_4 1
#define HPT366_ALLOW_ATA66_3 1
int revision; /* Chipset revision */
int flags; /* Chipset properties */
#define PLL_MODE 1
-#define IS_372N 2
+#define IS_3xxN 2
+#define PCI_66MHZ 4
/* Speed table */
- struct chipset_bus_clock_list_entry *speed;
+ u32 *speed;
};
/*
return 0;
}
-static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table)
+static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table)
{
- for ( ; chipset_table->xfer_speed ; chipset_table++)
- if (chipset_table->xfer_speed == speed)
- return chipset_table->chipset_settings;
- return chipset_table->chipset_settings;
+ int i;
+
+ /*
+ * Lookup the transfer mode table to get the index into
+ * the timing table.
+ *
+ * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
+ */
+ for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
+ if (xfer_speeds[i] == speed)
+ break;
+ return chipset_table[i];
}
static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
}
/**
- * hpt372n_set_clock - perform clock switching dance
- * @drive: Drive to switch
- * @mode: Switching mode (0x21 for write, 0x23 otherwise)
+ * hpt3xxn_set_clock - perform clock switching dance
+ * @hwif: hwif to switch
+ * @mode: clocking mode (0x21 for write, 0x23 otherwise)
*
- * Switch the DPLL clock on the HPT372N devices. This is a
- * right mess.
+ * Switch the DPLL clock on the HPT3xxN devices. This is a right mess.
+ * NOTE: avoid touching the disabled primary channel on HPT371N -- it
+ * doesn't physically exist anyway...
*/
-
-static void hpt372n_set_clock(ide_drive_t *drive, int mode)
+
+static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
{
- ide_hwif_t *hwif = HWIF(drive);
-
- /* FIXME: should we check for DMA active and BUG() */
+ u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b);
+
+ if ((scr2 & 0x7f) == mode)
+ return;
+
+ /* MISC. control register 1 has the channel enable bit... */
+ mcr1 = hwif->INB(hwif->dma_master + 0x70);
+
/* Tristate the bus */
- outb(0x80, hwif->dma_base+0x73);
- outb(0x80, hwif->dma_base+0x77);
-
+ if (mcr1 & 0x04)
+ hwif->OUTB(0x80, hwif->dma_master + 0x73);
+ hwif->OUTB(0x80, hwif->dma_master + 0x77);
+
/* Switch clock and reset channels */
- outb(mode, hwif->dma_base+0x7B);
- outb(0xC0, hwif->dma_base+0x79);
-
+ hwif->OUTB(mode, hwif->dma_master + 0x7b);
+ hwif->OUTB(0xc0, hwif->dma_master + 0x79);
+
/* Reset state machines */
- outb(0x37, hwif->dma_base+0x70);
- outb(0x37, hwif->dma_base+0x74);
-
+ if (mcr1 & 0x04)
+ hwif->OUTB(0x37, hwif->dma_master + 0x70);
+ hwif->OUTB(0x37, hwif->dma_master + 0x74);
+
/* Complete reset */
- outb(0x00, hwif->dma_base+0x79);
-
+ hwif->OUTB(0x00, hwif->dma_master + 0x79);
+
/* Reconnect channels to bus */
- outb(0x00, hwif->dma_base+0x73);
- outb(0x00, hwif->dma_base+0x77);
+ if (mcr1 & 0x04)
+ hwif->OUTB(0x00, hwif->dma_master + 0x73);
+ hwif->OUTB(0x00, hwif->dma_master + 0x77);
}
/**
- * hpt372n_rw_disk - prepare for I/O
+ * hpt3xxn_rw_disk - prepare for I/O
* @drive: drive for command
* @rq: block request structure
*
- * This is called when a disk I/O is issued to the 372N.
+ * This is called when a disk I/O is issued to HPT3xxN.
* We need it because of the clock switching.
*/
-static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq)
-{
- ide_hwif_t *hwif = drive->hwif;
- int wantclock;
-
- wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
-
- if (hwif->config_data != wantclock) {
- hpt372n_set_clock(drive, wantclock);
- hwif->config_data = wantclock;
- }
-}
-
-/*
- * Since SUN Cobalt is attempting to do this operation, I should disclose
- * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
- * HOTSWAP ATA Infrastructure.
- */
-
-static void hpt3xx_reset (ide_drive_t *drive)
-{
-}
-
-static int hpt3xx_tristate (ide_drive_t * drive, int state)
+static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40;
- u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;
-
- pci_read_config_byte(dev, 0x59, ®59h);
- pci_read_config_byte(dev, state_reg, ®XXh);
+ u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
- if (state) {
- (void) ide_do_reset(drive);
- pci_write_config_byte(dev, state_reg, regXXh|0x80);
- pci_write_config_byte(dev, 0x59, reg59h|reset);
- } else {
- pci_write_config_byte(dev, 0x59, reg59h & ~(reset));
- pci_write_config_byte(dev, state_reg, regXXh & ~(0x80));
- (void) ide_do_reset(drive);
- }
- return 0;
+ hpt3xxn_set_clock(hwif, wantclock);
}
/*
- * set/get power state for a drive.
- * turning the power off does the following things:
- * 1) soft-reset the drive
- * 2) tri-states the ide bus
+ * Set/get power state for a drive.
*
- * when we turn things back on, we need to re-initialize things.
+ * When we turn the power back on, we need to re-initialize things.
*/
#define TRISTATE_BIT 0x8000
-static int hpt370_busproc(ide_drive_t * drive, int state)
+
+static int hpt3xx_busproc(ide_drive_t *drive, int state)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = hwif->pci_dev;
- u8 tristate = 0, resetmask = 0, bus_reg = 0;
- u16 tri_reg;
+ u8 tristate, resetmask, bus_reg = 0;
+ u16 tri_reg = 0;
hwif->bus_state = state;
if (hwif->channel) {
/* secondary channel */
- tristate = 0x56;
- resetmask = 0x80;
+ tristate = 0x56;
+ resetmask = 0x80;
} else {
/* primary channel */
- tristate = 0x52;
+ tristate = 0x52;
resetmask = 0x40;
}
- /* grab status */
+ /* Grab the status. */
pci_read_config_word(dev, tristate, &tri_reg);
pci_read_config_byte(dev, 0x59, &bus_reg);
- /* set the state. we don't set it if we don't need to do so.
- * make sure that the drive knows that it has failed if it's off */
+ /*
+ * Set the state. We don't set it if we don't need to do so.
+ * Make sure that the drive knows that it has failed if it's off.
+ */
switch (state) {
case BUSSTATE_ON:
- hwif->drives[0].failures = 0;
- hwif->drives[1].failures = 0;
- if ((bus_reg & resetmask) == 0)
+ if (!(bus_reg & resetmask))
return 0;
- tri_reg &= ~TRISTATE_BIT;
- bus_reg &= ~resetmask;
- break;
+ hwif->drives[0].failures = hwif->drives[1].failures = 0;
+
+ pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask);
+ pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT);
+ return 0;
case BUSSTATE_OFF:
- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
- if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask))
+ if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT))
return 0;
tri_reg &= ~TRISTATE_BIT;
- bus_reg |= resetmask;
break;
case BUSSTATE_TRISTATE:
- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
- if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask))
+ if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT))
return 0;
tri_reg |= TRISTATE_BIT;
- bus_reg |= resetmask;
break;
+ default:
+ return -EINVAL;
}
- pci_write_config_byte(dev, 0x59, bus_reg);
- pci_write_config_word(dev, tristate, tri_reg);
+ hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+ hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+
+ pci_write_config_word(dev, tristate, tri_reg);
+ pci_write_config_byte(dev, 0x59, bus_reg | resetmask);
return 0;
}
/* detect bus speed by looking at control reg timing: */
switch((reg1 >> 8) & 7) {
case 5:
- info->speed = forty_base_hpt366;
+ info->speed = forty_base_hpt36x;
break;
case 9:
- info->speed = twenty_five_base_hpt366;
+ info->speed = twenty_five_base_hpt36x;
break;
case 7:
default:
- info->speed = thirty_three_base_hpt366;
+ info->speed = thirty_three_base_hpt36x;
break;
}
}
struct hpt_info *info = ide_get_hwifdata(hwif);
struct pci_dev *dev = hwif->pci_dev;
int adjust, i;
- u16 freq;
- u32 pll;
- u8 reg5bh;
+ u16 freq = 0;
+ u32 pll, temp = 0;
+ u8 reg5bh = 0, mcr1 = 0;
/*
* default to pci clock. make sure MA15/16 are set to output
pci_write_config_byte(dev, 0x5b, 0x23);
/*
- * set up the PLL. we need to adjust it so that it's stable.
- * freq = Tpll * 192 / Tpci
+ * We'll have to read f_CNT value in order to determine
+ * the PCI clock frequency according to the following ratio:
+ *
+ * f_CNT = Fpci * 192 / Fdpll
+ *
+ * First try reading the register in which the HighPoint BIOS
+ * saves f_CNT value before reprogramming the DPLL from its
+ * default setting (which differs for the various chips).
+ * NOTE: This register is only accessible via I/O space.
*
- * Todo. For non x86 should probably check the dword is
- * set to 0xABCDExxx indicating the BIOS saved f_CNT
+ * In case the signature check fails, we'll have to resort to
+ * reading the f_CNT register itself in hopes that nobody has
+ * touched the DPLL yet...
*/
- pci_read_config_word(dev, 0x78, &freq);
- freq &= 0x1FF;
-
+ temp = inl(pci_resource_start(dev, 4) + 0x90);
+ if ((temp & 0xFFFFF000) != 0xABCDE000) {
+ printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n");
+
+ /* Calculate the average value of f_CNT */
+ for (temp = i = 0; i < 128; i++) {
+ pci_read_config_word(dev, 0x78, &freq);
+ temp += freq & 0x1ff;
+ mdelay(1);
+ }
+ freq = temp / 128;
+ } else
+ freq = temp & 0x1ff;
+
/*
- * The 372N uses different PCI clock information and has
- * some other complications
- * On PCI33 timing we must clock switch
- * On PCI66 timing we must NOT use the PCI clock
- *
- * Currently we always set up the PLL for the 372N
+ * HPT3xxN chips use different PCI clock information.
+ * Currently we always set up the PLL for them.
*/
-
- if(info->flags & IS_372N)
- {
- printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");
+
+ if (info->flags & IS_3xxN) {
if(freq < 0x55)
pll = F_LOW_PCI_33;
else if(freq < 0x70)
pll = F_LOW_PCI_50;
else
pll = F_LOW_PCI_66;
-
- printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll);
-
- /* We always use the pll not the PCI clock on 372N */
+
+ printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll);
}
else
{
pll = F_LOW_PCI_66;
if (pll == F_LOW_PCI_33) {
- if (info->revision >= 8)
- info->speed = thirty_three_base_hpt374;
- else if (info->revision >= 5)
- info->speed = thirty_three_base_hpt372;
- else if (info->revision >= 4)
- info->speed = thirty_three_base_hpt370a;
- else
- info->speed = thirty_three_base_hpt370;
+ info->speed = thirty_three_base_hpt37x;
printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
} else if (pll == F_LOW_PCI_40) {
/* Unsupported */
} else if (pll == F_LOW_PCI_50) {
- if (info->revision >= 8)
- info->speed = fifty_base_hpt370a;
- else if (info->revision >= 5)
- info->speed = fifty_base_hpt372;
- else if (info->revision >= 4)
- info->speed = fifty_base_hpt370a;
- else
- info->speed = fifty_base_hpt370a;
+ info->speed = fifty_base_hpt37x;
printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
} else {
- if (info->revision >= 8) {
- printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
- }
- else if (info->revision >= 5)
- info->speed = sixty_six_base_hpt372;
- else if (info->revision >= 4)
- info->speed = sixty_six_base_hpt370a;
- else
- info->speed = sixty_six_base_hpt370;
+ info->speed = sixty_six_base_hpt37x;
printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
}
}
-
+
+ if (pll == F_LOW_PCI_66)
+ info->flags |= PCI_66MHZ;
+
/*
* only try the pll if we don't have a table for the clock
* speed that we're running at. NOTE: the internal PLL will
info->flags |= PLL_MODE;
/*
- * FIXME: make this work correctly, esp with 372N as per
- * reference driver code.
- *
- * adjust PLL based upon PCI clock, enable it, and wait for
- * stabilization.
+ * Adjust the PLL based upon the PCI clock, enable it, and
+ * wait for stabilization...
*/
adjust = 0;
freq = (pll < F_LOW_PCI_50) ? 2 : 4;
pci_write_config_dword(dev, 0x5c,
pll & ~0x100);
pci_write_config_byte(dev, 0x5b, 0x21);
- if (info->revision >= 8)
- info->speed = fifty_base_hpt370a;
- else if (info->revision >= 5)
- info->speed = fifty_base_hpt372;
- else if (info->revision >= 4)
- info->speed = fifty_base_hpt370a;
- else
- info->speed = fifty_base_hpt370a;
+
+ info->speed = fifty_base_hpt37x;
printk("HPT37X: using 50MHz internal PLL\n");
goto init_hpt37X_done;
}
}
- if (!pci_get_drvdata(dev)) {
- printk("No Clock Stabilization!!!\n");
- return;
- }
pll_recal:
if (adjust & 1)
pll -= (adjust >> 1);
init_hpt37X_done:
if (!info->speed)
- printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n",
- (info->flags & IS_372N)?"N":"", pll, freq);
- /* reset state engine */
- pci_write_config_byte(dev, 0x50, 0x37);
- pci_write_config_byte(dev, 0x54, 0x37);
+ printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n",
+ (info->flags & IS_3xxN) ? "N" : "", pll, freq);
+ /*
+ * Reset the state engines.
+ * NOTE: avoid accidentally enabling the primary channel on HPT371N.
+ */
+ pci_read_config_byte(dev, 0x50, &mcr1);
+ if (mcr1 & 0x04)
+ pci_write_config_byte(dev, 0x50, 0x37);
+ pci_write_config_byte(dev, 0x54, 0x37);
udelay(100);
}
struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = ide_get_hwifdata(hwif);
u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
+ int serialize = HPT_SERIALIZE_IO;
hwif->tuneproc = &hpt3xx_tune_drive;
hwif->speedproc = &hpt3xx_tune_chipset;
hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
- if(info->flags & IS_372N)
- hwif->rw_disk = &hpt372n_rw_disk;
+ /*
+ * HPT3xxN chips have some complications:
+ *
+ * - on 33 MHz PCI we must clock switch
+ * - on 66 MHz PCI we must NOT use the PCI clock
+ */
+ if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) {
+ /*
+ * Clock is shared between the channels,
+ * so we'll have to serialize them... :-(
+ */
+ serialize = 1;
+ hwif->rw_disk = &hpt3xxn_rw_disk;
+ }
/*
* The HPT37x uses the CBLID pins as outputs for MA15/MA16
PCI_FUNC(hwif->pci_dev->devfn));
#endif /* DEBUG */
-#ifdef HPT_SERIALIZE_IO
- /* serialize access to this device */
- if (hwif->mate)
+ /* Serialize access to this device */
+ if (serialize && hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
-#endif
- if (info->revision >= 3) {
- u8 reg5ah = 0;
- pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
- /*
- * set up ioctl for power status.
- * note: power affects both
- * drives on each channel
- */
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt370_busproc;
- } else if (info->revision >= 2) {
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt3xx_tristate;
- } else {
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt3xx_tristate;
- }
+ /*
+ * Set up ioctl for power status.
+ * NOTE: power affects both drives on each channel.
+ */
+ hwif->busproc = &hpt3xx_busproc;
if (!hwif->dma_base) {
hwif->drives[0].autotune = 1;
return;
if(info->speed == NULL) {
- printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n");
+ printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n");
return;
}
static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
{
- struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
- unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4);
- u8 did, rid;
+ struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
+ struct pci_dev *dev = hwif->pci_dev;
+ u16 did = dev->device;
+ u8 rid = 0;
if(info == NULL) {
printk(KERN_WARNING "hpt366: out of memory.\n");
}
ide_set_hwifdata(hwif, info);
- if(dmabase) {
- did = inb(dmabase + 0x22);
- rid = inb(dmabase + 0x28);
-
- if((did == 4 && rid == 6) || (did == 5 && rid > 1))
- info->flags |= IS_372N;
+ /* Avoid doing the same thing twice. */
+ if (hwif->channel && hwif->mate) {
+ memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info));
+ return;
}
- info->revision = hpt_revision(hwif->pci_dev);
+ pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid);
+
+ if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) ||
+ ((did == PCI_DEVICE_ID_TTI_HPT372 ||
+ did == PCI_DEVICE_ID_TTI_HPT302 ||
+ did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) ||
+ did == PCI_DEVICE_ID_TTI_HPT372N)
+ info->flags |= IS_3xxN;
+
+ info->revision = hpt_revision(dev);
if (info->revision >= 3)
hpt37x_clocking(hwif);
return ide_setup_pci_device(dev, d);
}
+static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
+{
+ u8 mcr1 = 0;
+
+ /*
+ * HPT371 chips physically have only one channel, the secondary one,
+ * but the primary channel registers do exist! Go figure...
+ * So, we manually disable the non-existing channel here
+ * (if the BIOS hasn't done this already).
+ */
+ pci_read_config_byte(dev, 0x50, &mcr1);
+ if (mcr1 & 0x04)
+ pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04));
+
+ return ide_setup_pci_device(dev, d);
+}
+
static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
{
struct pci_dev *findev = NULL;
.bootable = OFF_BOARD,
},{ /* 3 */
.name = "HPT371",
- .init_setup = init_setup_hpt37x,
+ .init_setup = init_setup_hpt371,
.init_chipset = init_chipset_hpt366,
.init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
.channels = 2,
.autodma = AUTODMA,
+ .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.bootable = OFF_BOARD,
},{ /* 4 */
.name = "HPT374",
*
* Called when the PCI registration layer (or the IDE initialization)
* finds a device matching our IDE device tables.
+ *
+ * NOTE: since we'll have to modify some fields of the ide_pci_device_t
+ * structure depending on the chip's revision, we'd better pass a local
+ * copy down the call chain...
*/
-
static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &hpt366_chipsets[id->driver_data];
+ ide_pci_device_t d = hpt366_chipsets[id->driver_data];
- return d->init_setup(dev, d);
+ return d.init_setup(dev, &d);
}
static struct pci_device_id hpt366_pci_tbl[] = {
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/hil.h>
+#include <linux/io.h>
#include <linux/spinlock.h>
+#include <asm/irq.h>
+#ifdef CONFIG_HP300
+#include <asm/hwtest.h>
+#endif
MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
p = cblock.buffer;
if (!access_ok(VERIFY_READ, p, length))
return -EFAULT;
- buf = (u_char *) kmalloc(1024, GFP_KERNEL);
+ buf = kmalloc(1024, GFP_KERNEL);
if (!buf)
return -ENOMEM;
timeout = 0;
strcpy(card->name, id);
card->contrnr = contr;
card->nbchan = profp->nbchannel;
- card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
+ card->bchans = kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
if (!card->bchans) {
printk(KERN_WARNING
"capidrv: (%s) Could not allocate bchan-structs.\n", id);
return;
if (!*cp)
return;
- if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
+ if (!(ib = kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
return; /* no memory */
strcpy(ib->info_start, cp); /* set output string */
ib->next = NULL;
*ielenp = p - ielenp - 1; /* set total IE length */
/* allocate mem for information struct */
- if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
+ if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
return(-ENOMEM); /* no memory */
init_timer(&cs->timer);
cs->info[0] = '\0';
{ struct deflect_struc *ds,*ds1=NULL;
unsigned long flags;
- if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc),
+ if (!(ds = kmalloc(sizeof(struct deflect_struc),
GFP_KERNEL)))
return(-ENOMEM); /* no memory */
if (dv->rule.action == DEFLECT_PROCEED)
if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
return(0); /* no external deflection needed */
- if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
+ if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
return(0); /* no memory */
init_timer(&cs->timer);
cs->info[0] = '\0';
{
struct cmdbuf_t *cb;
unsigned long flags;
- int status;
+ int rc;
gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
"CMD Transmit", len, buf);
- if (len <= 0)
- return 0; /* nothing to do */
+ if (len <= 0) {
+ /* nothing to do */
+ rc = 0;
+ goto notqueued;
+ }
if (len > IF_WRITEBUF)
len = IF_WRITEBUF;
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto notqueued;
}
memcpy(cb->buf, buf, len);
if (unlikely(!cs->connected)) {
spin_unlock_irqrestore(&cs->lock, flags);
gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+ /* flush command queue */
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ while (cs->cmdbuf != NULL)
+ complete_cb(cs);
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
return -ENODEV;
}
- status = start_cbsend(cs);
+ rc = start_cbsend(cs);
spin_unlock_irqrestore(&cs->lock, flags);
- return status < 0 ? status : len;
+ return rc < 0 ? rc : len;
+
+notqueued: /* request handled without queuing */
+ if (wake_tasklet)
+ tasklet_schedule(wake_tasklet);
+ return rc;
}
/* gigaset_write_room
/* kill URBs and tasklets before freeing - better safe than sorry */
atomic_set(&ubc->running, 0);
- for (i = 0; i < BAS_OUTURBS; ++i)
- if (ubc->isoouturbs[i].urb) {
- gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d",
- __func__, i);
- usb_kill_urb(ubc->isoouturbs[i].urb);
- usb_free_urb(ubc->isoouturbs[i].urb);
- }
- for (i = 0; i < BAS_INURBS; ++i)
- if (ubc->isoinurbs[i]) {
- gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d",
- __func__, i);
- usb_kill_urb(ubc->isoinurbs[i]);
- usb_free_urb(ubc->isoinurbs[i]);
- }
+ gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__);
+ for (i = 0; i < BAS_OUTURBS; ++i) {
+ usb_kill_urb(ubc->isoouturbs[i].urb);
+ usb_free_urb(ubc->isoouturbs[i].urb);
+ }
+ for (i = 0; i < BAS_INURBS; ++i) {
+ usb_kill_urb(ubc->isoinurbs[i]);
+ usb_free_urb(ubc->isoinurbs[i]);
+ }
tasklet_kill(&ubc->sent_tasklet);
tasklet_kill(&ubc->rcvd_tasklet);
kfree(ubc->isooutbuf);
struct bas_bc_state *ubc;
int i, j;
+ gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__);
for (j = 0; j < 2; ++j) {
ubc = cs->bcs[j].hw.bas;
- for (i = 0; i < BAS_OUTURBS; ++i)
- if (ubc->isoouturbs[i].urb) {
- usb_kill_urb(ubc->isoouturbs[i].urb);
- gig_dbg(DEBUG_INIT,
- "%s: isoc output URB %d/%d unlinked",
- __func__, j, i);
- usb_free_urb(ubc->isoouturbs[i].urb);
- ubc->isoouturbs[i].urb = NULL;
- }
- for (i = 0; i < BAS_INURBS; ++i)
- if (ubc->isoinurbs[i]) {
- usb_kill_urb(ubc->isoinurbs[i]);
- gig_dbg(DEBUG_INIT,
- "%s: isoc input URB %d/%d unlinked",
- __func__, j, i);
- usb_free_urb(ubc->isoinurbs[i]);
- ubc->isoinurbs[i] = NULL;
- }
- }
- if (ucs->urb_int_in) {
- usb_kill_urb(ucs->urb_int_in);
- gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked",
- __func__);
- usb_free_urb(ucs->urb_int_in);
- ucs->urb_int_in = NULL;
- }
- if (ucs->urb_cmd_out) {
- usb_kill_urb(ucs->urb_cmd_out);
- gig_dbg(DEBUG_INIT, "%s: command output URB unlinked",
- __func__);
- usb_free_urb(ucs->urb_cmd_out);
- ucs->urb_cmd_out = NULL;
- }
- if (ucs->urb_cmd_in) {
- usb_kill_urb(ucs->urb_cmd_in);
- gig_dbg(DEBUG_INIT, "%s: command input URB unlinked",
- __func__);
- usb_free_urb(ucs->urb_cmd_in);
- ucs->urb_cmd_in = NULL;
- }
- if (ucs->urb_ctrl) {
- usb_kill_urb(ucs->urb_ctrl);
- gig_dbg(DEBUG_INIT, "%s: control output URB unlinked",
- __func__);
- usb_free_urb(ucs->urb_ctrl);
- ucs->urb_ctrl = NULL;
+ for (i = 0; i < BAS_OUTURBS; ++i) {
+ usb_kill_urb(ubc->isoouturbs[i].urb);
+ usb_free_urb(ubc->isoouturbs[i].urb);
+ ubc->isoouturbs[i].urb = NULL;
+ }
+ for (i = 0; i < BAS_INURBS; ++i) {
+ usb_kill_urb(ubc->isoinurbs[i]);
+ usb_free_urb(ubc->isoinurbs[i]);
+ ubc->isoinurbs[i] = NULL;
+ }
}
+ usb_kill_urb(ucs->urb_int_in);
+ usb_free_urb(ucs->urb_int_in);
+ ucs->urb_int_in = NULL;
+ usb_kill_urb(ucs->urb_cmd_out);
+ usb_free_urb(ucs->urb_cmd_out);
+ ucs->urb_cmd_out = NULL;
+ usb_kill_urb(ucs->urb_cmd_in);
+ usb_free_urb(ucs->urb_cmd_in);
+ ucs->urb_cmd_in = NULL;
+ usb_kill_urb(ucs->urb_ctrl);
+ usb_free_urb(ucs->urb_ctrl);
+ ucs->urb_ctrl = NULL;
}
/* gigaset_probe
} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
/* read access -> output card info data */
- if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
+ if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
unlock_kernel();
return (-EFAULT); /* out of memory */
}
if (pd->if_used <= 0)
return; /* no open file for read */
- if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
+ if (!(ib = kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
return; /* no memory */
strcpy(ib->log_start, cp); /* set output string */
ib->next = NULL;
isdn_audio_adpcm_init(adpcm_state * s, int nbits)
{
if (!s)
- s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
+ s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
if (s) {
s->a = 0;
s->d = 5;
isdn_audio_dtmf_init(dtmf_state * s)
{
if (!s)
- s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
+ s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
if (s) {
s->idx = 0;
s->last = ' ';
isdn_audio_silence_init(silence_state * s)
{
if (!s)
- s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
+ s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
if (s) {
s->idx = 0;
s->state = 0;
isdn_net_phone *n;
if (p) {
- if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
+ if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
return -ENOMEM;
strcpy(n->num, phone->phone);
n->next = p->local->phone[phone->outgoing & 1];
printk(KERN_DEBUG "ippp: device not activated.\n");
return 0;
}
- nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
+ nbuf = kmalloc(len + 4, GFP_ATOMIC);
if (!nbuf) {
printk(KERN_WARNING "ippp: Can't alloc buf\n");
return 0;
dev_kfree_skb(skb);
return -1;
}
- if ((frame = (struct frame_buf *) kmalloc(sizeof(struct frame_buf),
+ if ((frame = kmalloc(sizeof(struct frame_buf),
GFP_ATOMIC)) == NULL) {
printk(KERN_WARNING "pcbit_2_write: kmalloc failed\n");
dev_kfree_skb(skb);
#
# KVM configuration
#
+menu "Virtualization"
+
config KVM
tristate "Kernel-based Virtual Machine (KVM) support"
depends on X86 && EXPERIMENTAL
---help---
Provides support for KVM on AMD processors equipped with the AMD-V
(SVM) extensions.
+
+endmenu
VCPU_REGS_RBP = 5,
VCPU_REGS_RSI = 6,
VCPU_REGS_RDI = 7,
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
VCPU_REGS_R8 = 8,
VCPU_REGS_R9 = 9,
VCPU_REGS_R10 = 10,
void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0);
void lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
void set_efer(struct kvm_vcpu *vcpu, u64 efer);
#endif
return segment_base(tr);
}
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
static inline unsigned long read_msr(unsigned long msr)
{
u64 value;
#define TSS_REDIRECTION_SIZE (256 / 8)
#define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
/*
* When emulating 32-bit mode, cr3 is only 32 bits even on x86_64. Therefore
#define CR8_RESEVED_BITS (~0x0fULL)
#define EFER_RESERVED_BITS 0xfffffffffffff2fe
-struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
-{
- int i;
-
- for (i = 0; i < vcpu->nmsrs; ++i)
- if (vcpu->guest_msrs[i].index == msr)
- return &vcpu->guest_msrs[i];
- return 0;
-}
-EXPORT_SYMBOL_GPL(find_msr_entry);
-
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
// LDT or TSS descriptor in the GDT. 16 bytes.
struct segment_descriptor_64 {
struct segment_descriptor s;
}
d = (struct segment_descriptor *)(table_base + (selector & ~7));
v = d->base_low | ((ul)d->base_mid << 16) | ((ul)d->base_high << 24);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
if (d->system == 0
&& (d->type == 2 || d->type == 9 || d->type == 11))
v |= ((ul)((struct segment_descriptor_64 *)d)->base_higher) << 32;
static void vcpu_put(struct kvm_vcpu *vcpu)
{
kvm_arch_ops->vcpu_put(vcpu);
- put_cpu();
mutex_unlock(&vcpu->mutex);
}
}
if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
if ((vcpu->shadow_efer & EFER_LME)) {
int cs_db, cs_l;
return kvm_arch_ops->get_msr(vcpu, msr_index, pdata);
}
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
void set_efer(struct kvm_vcpu *vcpu, u64 efer)
{
- struct vmx_msr_entry *msr;
-
if (efer & EFER_RESERVED_BITS) {
printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
efer);
return;
}
+ kvm_arch_ops->set_efer(vcpu, efer);
+
efer &= ~EFER_LMA;
efer |= vcpu->shadow_efer & EFER_LMA;
vcpu->shadow_efer = efer;
-
- msr = find_msr_entry(vcpu, MSR_EFER);
-
- if (!(efer & EFER_LMA))
- efer &= ~EFER_LME;
- msr->data = efer;
}
EXPORT_SYMBOL_GPL(set_efer);
regs->rdi = vcpu->regs[VCPU_REGS_RDI];
regs->rsp = vcpu->regs[VCPU_REGS_RSP];
regs->rbp = vcpu->regs[VCPU_REGS_RBP];
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
regs->r8 = vcpu->regs[VCPU_REGS_R8];
regs->r9 = vcpu->regs[VCPU_REGS_R9];
regs->r10 = vcpu->regs[VCPU_REGS_R10];
vcpu->regs[VCPU_REGS_RDI] = regs->rdi;
vcpu->regs[VCPU_REGS_RSP] = regs->rsp;
vcpu->regs[VCPU_REGS_RBP] = regs->rbp;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
vcpu->regs[VCPU_REGS_R8] = regs->r8;
vcpu->regs[VCPU_REGS_R9] = regs->r9;
vcpu->regs[VCPU_REGS_R10] = regs->r10;
vcpu->cr8 = sregs->cr8;
mmu_reset_needed |= vcpu->shadow_efer != sregs->efer;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
kvm_arch_ops->set_efer(vcpu, sregs->efer);
#endif
vcpu->apic_base = sregs->apic_base;
static u32 msrs_to_save[] = {
MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
MSR_K6_STAR,
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
#endif
MSR_IA32_TIME_STAMP_COUNTER,
#include "kvm.h"
static const u32 host_save_msrs[] = {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
MSR_FS_BASE, MSR_GS_BASE,
#endif
#ifndef __KVM_VMX_H
#define __KVM_VMX_H
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
/*
* avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt
* mechanism (cpu bug AA24)
#define PT32_PTE_COPY_MASK \
- (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \
- PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_PAT_MASK | \
- PT_GLOBAL_MASK )
-
-#define PT32_NON_PTE_COPY_MASK \
- (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \
- PT_ACCESSED_MASK | PT_DIRTY_MASK)
-
-
-#define PT64_PTE_COPY_MASK \
- (PT64_NX_MASK | PT32_PTE_COPY_MASK)
-
-#define PT64_NON_PTE_COPY_MASK \
- (PT64_NX_MASK | PT32_NON_PTE_COPY_MASK)
-
+ (PT_PRESENT_MASK | PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_GLOBAL_MASK)
+#define PT64_PTE_COPY_MASK (PT64_NX_MASK | PT32_PTE_COPY_MASK)
#define PT_FIRST_AVAIL_BITS_SHIFT 9
#define PT64_SECOND_AVAIL_BITS_SHIFT 52
#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
#define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
#define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK
- #define PT_NON_PTE_COPY_MASK PT64_NON_PTE_COPY_MASK
#elif PTTYPE == 32
#define pt_element_t u32
#define guest_walker guest_walker32
#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
#define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
#define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK
- #define PT_NON_PTE_COPY_MASK PT32_NON_PTE_COPY_MASK
#else
#error Invalid PTTYPE value
#endif
if (PTTYPE == 32 && is_cpuid_PSE36())
gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) <<
(32 - PT32_DIR_PSE36_SHIFT);
- *shadow_pte = (guest_pde & (PT_NON_PTE_COPY_MASK | PT_GLOBAL_MASK)) |
- ((guest_pde & PT_DIR_PAT_MASK) >>
- (PT_DIR_PAT_SHIFT - PT_PAT_SHIFT));
+ *shadow_pte = guest_pde & PT_PTE_COPY_MASK;
set_pte_common(vcpu, shadow_pte, gaddr,
guest_pde & PT_DIRTY_MASK, access_bits);
}
u32 index = SHADOW_PT_INDEX(addr, level);
u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index;
pt_element_t *guest_ent;
+ u64 shadow_pte;
if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) {
if (level == PT_PAGE_TABLE_LEVEL)
shadow_addr = kvm_mmu_alloc_page(vcpu, shadow_ent);
if (!VALID_PAGE(shadow_addr))
return ERR_PTR(-ENOMEM);
- if (!kvm_arch_ops->is_long_mode(vcpu) && level == 3)
- *shadow_ent = shadow_addr |
- (*guest_ent & (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK));
- else {
- *shadow_ent = shadow_addr |
- (*guest_ent & PT_NON_PTE_COPY_MASK);
- *shadow_ent |= (PT_WRITABLE_MASK | PT_USER_MASK);
- }
+ shadow_pte = shadow_addr | PT_PRESENT_MASK;
+ if (vcpu->mmu.root_level > 3 || level != 3)
+ shadow_pte |= PT_ACCESSED_MASK
+ | PT_WRITABLE_MASK | PT_USER_MASK;
+ *shadow_ent = shadow_pte;
prev_shadow_ent = shadow_ent;
}
}
struct svm_cpu_data *svm_data;
uint64_t efer;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
struct desc_ptr gdt_descr;
#else
struct Xgt_desc_struct gdt_descr;
void *msrpm_va;
int r;
+ kvm_emulator_want_group7_invlpg();
iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER);
memset(msrpm_va, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
msrpm_base = page_to_pfn(msrpm_pages) << PAGE_SHIFT;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
set_msr_interception(msrpm_va, MSR_GS_BASE, 1, 1);
set_msr_interception(msrpm_va, MSR_FS_BASE, 1, 1);
set_msr_interception(msrpm_va, MSR_KERNEL_GS_BASE, 1, 1);
static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
{
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
if (vcpu->shadow_efer & KVM_EFER_LME) {
if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) {
vcpu->shadow_efer |= KVM_EFER_LMA;
case MSR_IA32_APICBASE:
*data = vcpu->apic_base;
break;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
case MSR_STAR:
*data = vcpu->svm->vmcb->save.star;
break;
static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
{
switch (ecx) {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
case MSR_EFER:
set_efer(vcpu, data);
break;
case MSR_IA32_APICBASE:
vcpu->apic_base = data;
break;
-#ifdef __x86_64___
+#ifdef CONFIG_X86_64_
case MSR_STAR:
vcpu->svm->vmcb->save.star = data;
break;
static void save_db_regs(unsigned long *db_regs)
{
-#ifdef __x86_64__
- asm ("mov %%dr0, %%rax \n\t"
- "mov %%rax, %[dr0] \n\t"
- "mov %%dr1, %%rax \n\t"
- "mov %%rax, %[dr1] \n\t"
- "mov %%dr2, %%rax \n\t"
- "mov %%rax, %[dr2] \n\t"
- "mov %%dr3, %%rax \n\t"
- "mov %%rax, %[dr3] \n\t"
- : [dr0] "=m"(db_regs[0]),
- [dr1] "=m"(db_regs[1]),
- [dr2] "=m"(db_regs[2]),
- [dr3] "=m"(db_regs[3])
- : : "rax");
-#else
- asm ("mov %%dr0, %%eax \n\t"
- "mov %%eax, %[dr0] \n\t"
- "mov %%dr1, %%eax \n\t"
- "mov %%eax, %[dr1] \n\t"
- "mov %%dr2, %%eax \n\t"
- "mov %%eax, %[dr2] \n\t"
- "mov %%dr3, %%eax \n\t"
- "mov %%eax, %[dr3] \n\t"
- : [dr0] "=m"(db_regs[0]),
- [dr1] "=m"(db_regs[1]),
- [dr2] "=m"(db_regs[2]),
- [dr3] "=m"(db_regs[3])
- : : "eax");
-#endif
+ asm volatile ("mov %%dr0, %0" : "=r"(db_regs[0]));
+ asm volatile ("mov %%dr1, %0" : "=r"(db_regs[1]));
+ asm volatile ("mov %%dr2, %0" : "=r"(db_regs[2]));
+ asm volatile ("mov %%dr3, %0" : "=r"(db_regs[3]));
}
static void load_db_regs(unsigned long *db_regs)
{
- asm volatile ("mov %[dr0], %%dr0 \n\t"
- "mov %[dr1], %%dr1 \n\t"
- "mov %[dr2], %%dr2 \n\t"
- "mov %[dr3], %%dr3 \n\t"
- :
- : [dr0] "r"(db_regs[0]),
- [dr1] "r"(db_regs[1]),
- [dr2] "r"(db_regs[2]),
- [dr3] "r"(db_regs[3])
-#ifdef __x86_64__
- : "rax");
-#else
- : "eax");
-#endif
+ asm volatile ("mov %0, %%dr0" : : "r"(db_regs[0]));
+ asm volatile ("mov %0, %%dr1" : : "r"(db_regs[1]));
+ asm volatile ("mov %0, %%dr2" : : "r"(db_regs[2]));
+ asm volatile ("mov %0, %%dr3" : : "r"(db_regs[3]));
}
static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
load_db_regs(vcpu->svm->db_regs);
}
asm volatile (
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
"push %%rbx; push %%rcx; push %%rdx;"
"push %%rsi; push %%rdi; push %%rbp;"
"push %%r8; push %%r9; push %%r10; push %%r11;"
"push %%esi; push %%edi; push %%ebp;"
#endif
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
"mov %c[rbx](%[vcpu]), %%rbx \n\t"
"mov %c[rcx](%[vcpu]), %%rcx \n\t"
"mov %c[rdx](%[vcpu]), %%rdx \n\t"
"mov %c[rbp](%[vcpu]), %%ebp \n\t"
#endif
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
/* Enter guest mode */
"push %%rax \n\t"
"mov %c[svm](%[vcpu]), %%rax \n\t"
#endif
/* Save guest registers, load host registers */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
"mov %%rbx, %c[rbx](%[vcpu]) \n\t"
"mov %%rcx, %c[rcx](%[vcpu]) \n\t"
"mov %%rdx, %c[rdx](%[vcpu]) \n\t"
[rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])),
[rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])),
[rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP]))
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
,[r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])),
[r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])),
[r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])),
static int __init svm_init(void)
{
- kvm_emulator_want_group7_invlpg();
- kvm_init_arch(&svm_arch_ops, THIS_MODULE);
- return 0;
+ return kvm_init_arch(&svm_arch_ops, THIS_MODULE);
}
static void __exit svm_exit(void)
#include <linux/mm.h>
#include <linux/highmem.h>
#include <asm/io.h>
+#include <asm/desc.h>
#include "segment_descriptor.h"
static DEFINE_PER_CPU(struct vmcs *, vmxarea);
static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
#define HOST_IS_64 1
#else
#define HOST_IS_64 0
};
static const u32 vmx_msr_index[] = {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE,
#endif
MSR_EFER, MSR_K6_STAR,
};
#define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index))
-struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr);
-
static inline int is_page_fault(u32 intr_info)
{
return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
== (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
}
+static struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
+{
+ int i;
+
+ for (i = 0; i < vcpu->nmsrs; ++i)
+ if (vcpu->guest_msrs[i].index == msr)
+ return &vcpu->guest_msrs[i];
+ return 0;
+}
+
static void vmcs_clear(struct vmcs *vmcs)
{
u64 phys_addr = __pa(vmcs);
static u64 vmcs_read64(unsigned long field)
{
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
return vmcs_readl(field);
#else
return vmcs_readl(field) | ((u64)vmcs_readl(field+1) << 32);
static void vmcs_write64(unsigned long field, u64 value)
{
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
vmcs_writel(field, value);
#else
vmcs_writel(field, value);
static void reload_tss(void)
{
-#ifndef __x86_64__
+#ifndef CONFIG_X86_64
/*
* VT restores TR but not its size. Useless.
}
switch (msr_index) {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
case MSR_FS_BASE:
data = vmcs_readl(GUEST_FS_BASE);
break;
{
struct vmx_msr_entry *msr;
switch (msr_index) {
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
case MSR_FS_BASE:
vmcs_writel(GUEST_FS_BASE, data);
break;
u64 old;
rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
- if ((old & 5) == 0)
+ if ((old & 5) != 5)
/* enable and lock */
wrmsrl(MSR_IA32_FEATURE_CONTROL, old | 5);
write_cr4(read_cr4() | CR4_VMXE); /* FIXME: not cpu hotplug safe */
fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);
}
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
static void enter_lmode(struct kvm_vcpu *vcpu)
{
if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK))
enter_rmode(vcpu);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
if (vcpu->shadow_efer & EFER_LME) {
if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK))
enter_lmode(vcpu);
vcpu->cr4 = cr4;
}
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
{
ar |= (var->db & 1) << 14;
ar |= (var->g & 1) << 15;
}
+ if (ar == 0) /* a 0 value means unusable */
+ ar = AR_UNUSABLE_MASK;
vmcs_write32(sf->ar_bytes, ar);
}
vmcs_write16(HOST_FS_SELECTOR, read_fs()); /* 22.2.4 */
vmcs_write16(HOST_GS_SELECTOR, read_gs()); /* 22.2.4 */
vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
rdmsrl(MSR_FS_BASE, a);
vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */
rdmsrl(MSR_GS_BASE, a);
VM_ENTRY_CONTROLS, 0);
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */
+#ifdef CONFIG_X86_64
vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, 0);
vmcs_writel(TPR_THRESHOLD, 0);
+#endif
vmcs_writel(CR0_GUEST_HOST_MASK, KVM_GUEST_CR0_MASK);
vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
vcpu->cr0 = 0x60000010;
vmx_set_cr0(vcpu, vcpu->cr0); // enter rmode
vmx_set_cr4(vcpu, 0);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
vmx_set_efer(vcpu, 0);
#endif
vmcs_write16(HOST_GS_SELECTOR, 0);
}
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
vmcs_writel(HOST_FS_BASE, read_msr(MSR_FS_BASE));
vmcs_writel(HOST_GS_BASE, read_msr(MSR_GS_BASE));
#else
asm (
/* Store host registers */
"pushf \n\t"
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
"push %%rax; push %%rbx; push %%rdx;"
"push %%rsi; push %%rdi; push %%rbp;"
"push %%r8; push %%r9; push %%r10; push %%r11;"
/* Check if vmlaunch of vmresume is needed */
"cmp $0, %1 \n\t"
/* Load guest registers. Don't clobber flags. */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
"mov %c[cr2](%3), %%rax \n\t"
"mov %%rax, %%cr2 \n\t"
"mov %c[rax](%3), %%rax \n\t"
".globl kvm_vmx_return \n\t"
"kvm_vmx_return: "
/* Save guest registers, load host registers, keep flags */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
"xchg %3, 0(%%rsp) \n\t"
"mov %%rax, %c[rax](%3) \n\t"
"mov %%rbx, %c[rbx](%3) \n\t"
[rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])),
[rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])),
[rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP])),
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
[r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])),
[r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])),
[r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])),
fx_save(vcpu->guest_fx_image);
fx_restore(vcpu->host_fx_image);
-#ifndef __x86_64__
+#ifndef CONFIG_X86_64
asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
#endif
*/
local_irq_disable();
load_gs(gs_sel);
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
#endif
local_irq_enable();
.set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch,
.set_cr3 = vmx_set_cr3,
.set_cr4 = vmx_set_cr4,
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
.set_efer = vmx_set_efer,
#endif
.get_idt = vmx_get_idt,
static int __init vmx_init(void)
{
- kvm_init_arch(&vmx_arch_ops, THIS_MODULE);
- return 0;
+ return kvm_init_arch(&vmx_arch_ops, THIS_MODULE);
}
static void __exit vmx_exit(void)
* any modified flags.
*/
-#if defined(__x86_64__)
+#if defined(CONFIG_X86_64)
#define _LO32 "k" /* force 32-bit operand */
#define _STK "%%rsp" /* stack pointer */
#elif defined(__i386__)
} while (0)
/* Emulate an instruction with quadword operands (x86/64 only). */
-#if defined(__x86_64__)
+#if defined(CONFIG_X86_64)
#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) \
do { \
__asm__ __volatile__ ( \
case X86EMUL_MODE_PROT32:
op_bytes = ad_bytes = 4;
break;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
case X86EMUL_MODE_PROT64:
op_bytes = 4;
ad_bytes = 8;
}
break;
}
-#elif defined(__x86_64__)
+#elif defined(CONFIG_X86_64)
{
unsigned long old, new;
if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0)
/* Host execution mode. */
#if defined(__i386__)
#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32
-#elif defined(__x86_64__)
+#elif defined(CONFIG_X86_64)
#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64
#endif
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
- req = (struct adb_request *) kmalloc(sizeof(struct adb_request),
+ req = kmalloc(sizeof(struct adb_request),
GFP_KERNEL);
if (req == NULL)
return -ENOMEM;
{
struct apm_user * as;
- as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+ as = kmalloc(sizeof(*as), GFP_KERNEL);
if (as == NULL) {
printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
sizeof(*as));
*/
tlen = sizeof(struct property) + len + 18;
- prop = kcalloc(tlen, 1, GFP_KERNEL);
+ prop = kzalloc(tlen, GFP_KERNEL);
if (prop == NULL)
return NULL;
hdr = (struct smu_sdbp_header *)(prop + 1);
n_pbook_pci_saves = npci;
if (npci == 0)
return;
- ps = (struct pci_save *) kmalloc(npci * sizeof(*ps), GFP_KERNEL);
+ ps = kmalloc(npci * sizeof(*ps), GFP_KERNEL);
pbook_pci_saves = ps;
if (ps == NULL)
return;
conf_t *conf = (conf_t*)mddev->private;
int failit = 0;
- if (bio->bi_rw & 1) {
+ if (bio_data_dir(bio) == WRITE) {
/* write request */
if (atomic_read(&conf->counters[WriteAll])) {
/* special case - don't decrement, don't generic_make_request,
/* take from bio_init */
bio->bi_next = NULL;
bio->bi_flags |= 1 << BIO_UPTODATE;
- bio->bi_rw = 0;
+ bio->bi_rw = READ;
bio->bi_vcnt = 0;
bio->bi_idx = 0;
bio->bi_phys_segments = 0;
biolist = bio;
bio->bi_private = r10_bio;
bio->bi_end_io = end_sync_read;
- bio->bi_rw = 0;
+ bio->bi_rw = READ;
bio->bi_sector = r10_bio->devs[j].addr +
conf->mirrors[d].rdev->data_offset;
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
biolist = bio;
bio->bi_private = r10_bio;
bio->bi_end_io = end_sync_write;
- bio->bi_rw = 1;
+ bio->bi_rw = WRITE;
bio->bi_sector = r10_bio->devs[k].addr +
conf->mirrors[i].rdev->data_offset;
bio->bi_bdev = conf->mirrors[i].rdev->bdev;
biolist = bio;
bio->bi_private = r10_bio;
bio->bi_end_io = end_sync_read;
- bio->bi_rw = 0;
+ bio->bi_rw = READ;
bio->bi_sector = r10_bio->devs[i].addr +
conf->mirrors[d].rdev->data_offset;
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
struct bio *bi;
mdk_rdev_t *rdev;
if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
- rw = 1;
+ rw = WRITE;
else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
- rw = 0;
+ rw = READ;
else
continue;
bi = &sh->dev[i].req;
bi->bi_rw = rw;
- if (rw)
+ if (rw == WRITE)
bi->bi_end_io = raid5_end_write_request;
else
bi->bi_end_io = raid5_end_read_request;
atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
generic_make_request(bi);
} else {
- if (rw == 1)
+ if (rw == WRITE)
set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
struct bio *bi;
mdk_rdev_t *rdev;
if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
- rw = 1;
+ rw = WRITE;
else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
- rw = 0;
+ rw = READ;
else
continue;
bi = &sh->dev[i].req;
bi->bi_rw = rw;
- if (rw)
+ if (rw == WRITE)
bi->bi_end_io = raid5_end_write_request;
else
bi->bi_end_io = raid5_end_read_request;
atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
generic_make_request(bi);
} else {
- if (rw == 1)
+ if (rw == WRITE)
set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
unsigned int chunk_sectors = mddev->chunk_size >> 9;
unsigned int bio_sectors = bio->bi_size >> 9;
- if (bio_data_dir(bio))
+ if (bio_data_dir(bio) == WRITE)
return biovec->bv_len; /* always allow writes to be mergeable */
max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
disk_stat_inc(mddev->gendisk, ios[rw]);
disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi));
- if (bio_data_dir(bi) == READ &&
+ if (rw == READ &&
mddev->reshape_position == MaxSector &&
chunk_aligned_read(q,bi))
return 0;
struct ca_msg *hw_buffer;
int result = 0;
- if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
+ if ((hw_buffer = kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
case BTTV_BOARD_TWINHAN_DST:
/* DST is not a frontend driver !!! */
- state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL);
+ state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);
if (!state) {
printk("dvb_bt8xx: No memory\n");
break;
struct ttusbdecfe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
if (state == NULL)
return NULL;
struct ttusbdecfe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
if (state == NULL)
return NULL;
pipesize, packets, transfer_buffer_length);
while (buffers < (s->total_buffer_size << 10)) {
- b = (pbuff_t) kzalloc (sizeof (buff_t), GFP_KERNEL);
+ b = kzalloc(sizeof (buff_t), GFP_KERNEL);
if (!b) {
err("kzalloc(sizeof(buff_t))==NULL");
goto err;
switch (cmd) {
case IOCTL_DAB_BULK:
- pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
+ pbulk = kmalloc(sizeof (bulk_transfer_t), GFP_KERNEL);
if (!pbulk) {
ret = -ENOMEM;
+ MAX_LNUM
#endif /* PLANB_GSCANLINE */
);
- if ((pb->rawbuf = (unsigned char**) kmalloc (npage
+ if ((pb->rawbuf = kmalloc(npage
* sizeof(unsigned long), GFP_KERNEL)) == 0)
return -ENOMEM;
for (i = 0; i < npage; i++) {
}
base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo);
- cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL);
+ cams = kzalloc(base_size, GFP_KERNEL);
if (cams == NULL) {
err("Failed to allocate %d. bytes for usbvideo struct", base_size);
return -ENOMEM;
size);
kfree(videocodec_buf);
- videocodec_buf = (char *) kmalloc(size, GFP_KERNEL);
+ videocodec_buf = kmalloc(size, GFP_KERNEL);
i = 0;
i += scnprintf(videocodec_buf + i, size - 1,
extern int i2o_exec_lct_get(struct i2o_controller *);
extern int __init i2o_exec_init(void);
-extern void __exit i2o_exec_exit(void);
+extern void i2o_exec_exit(void);
/* driver */
extern struct bus_type i2o_bus_type;
extern int i2o_driver_dispatch(struct i2o_controller *, u32);
extern int __init i2o_driver_init(void);
-extern void __exit i2o_driver_exit(void);
+extern void i2o_driver_exit(void);
/* PCI */
extern int __init i2o_pci_init(void);
*
* Unregisters the I2O bus and frees driver array.
*/
-void __exit i2o_driver_exit(void)
+void i2o_driver_exit(void)
{
bus_unregister(&i2o_bus_type);
kfree(i2o_drivers);
*
* Unregisters the Exec OSM from the I2O core.
*/
-void __exit i2o_exec_exit(void)
+void i2o_exec_exit(void)
{
i2o_driver_unregister(&i2o_exec_driver);
};
if (!dev)
return -ENXIO;
- ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL);
+ ops = kmalloc(kcmd.oplen, GFP_KERNEL);
if (!ops)
return -ENOMEM;
* It's possible to have a _very_ large table
* and that the user asks for all of it at once...
*/
- res = (u8 *) kmalloc(65536, GFP_KERNEL);
+ res = kmalloc(65536, GFP_KERNEL);
if (!res) {
kfree(ops);
return -ENOMEM;
struct mtd_info *device;
struct flash_platform_data *pdata = spi->dev.platform_data;
- priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL);
+ priv = kzalloc(sizeof *priv, GFP_KERNEL);
if (!priv)
return -ENOMEM;
if (mtd->type != MTD_NORFLASH)
return;
- part = kcalloc(1, sizeof(struct partition), GFP_KERNEL);
+ part = kzalloc(sizeof(struct partition), GFP_KERNEL);
if (!part)
return;
*/
static int ipddp_create(struct ipddp_route *new_rt)
{
- struct ipddp_route *rt =(struct ipddp_route*) kmalloc(sizeof(*rt), GFP_KERNEL);
+ struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL);
if (rt == NULL)
return -ENOMEM;
* Allocate the main control structure for this instance.
*/
maxmaxcode = MAXCODE(bits);
- db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),
+ db = kmalloc(sizeof (struct bsd_db),
GFP_KERNEL);
if (!db)
{
irda_qos_bits_to_value (&self->qos);
/* Allocate twice the size to guarantee alignment */
- self->ringbuf = (void *) kmalloc (OBOE_RING_LEN << 1, GFP_KERNEL);
+ self->ringbuf = kmalloc(OBOE_RING_LEN << 1, GFP_KERNEL);
if (!self->ringbuf)
{
printk (KERN_ERR DRIVER_NAME ": can't allocate DMA buffers\n");
/* Don't change this buffer size and allocation without doing
* some heavy and complete testing. Don't ask why :-(
* Jean II */
- self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);
+ self->speed_buff = kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);
if (self->speed_buff == NULL)
goto err_out_3;
/* Allocate memory if needed */
if (self->tx_buff.truesize > 0) {
- self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
+ self->tx_buff.head = kmalloc(self->tx_buff.truesize,
GFP_KERNEL);
if (self->tx_buff.head == NULL) {
IRDA_ERROR("%s(), can't allocate memory for "
dev->trans_start = jiffies;
- tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
+ tx_cmd = kmalloc((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
if (tx_cmd == NULL) {
printk(KERN_WARNING "%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
lp->stats.tx_dropped++;
if (dev->mc_count > 0) {
struct dev_mc_list *dmi;
char *cp;
- cmd = (struct i596_cmd *)kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
+ cmd = kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
if (cmd == NULL) {
printk (KERN_ERR "%s: set_multicast Memory squeeze.\n", dev->name);
return;
struct phy_device *dev;
/* We allocate the device, and initialize the
* default values */
- dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (NULL == dev)
return (struct phy_device*) PTR_ERR((void*)-ENOMEM);
if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
return NULL;
- state = (struct ppp_deflate_state *) kmalloc(sizeof(*state),
+ state = kmalloc(sizeof(*state),
GFP_KERNEL);
if (state == NULL)
return NULL;
if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
return NULL;
- state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+ state = kmalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
return NULL;
|| options[0] != CI_MPPE || options[1] != CILEN_MPPE)
goto out;
- state = (struct ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+ state = kmalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
goto out;
struct skge_element *e;
int i;
- ring->start = kcalloc(sizeof(*e), ring->count, GFP_KERNEL);
+ ring->start = kcalloc(ring->count, sizeof(*e), GFP_KERNEL);
if (!ring->start)
return -ENOMEM;
if (len < 576 * 2)
len = 576 * 2;
- xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
- rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+ xbuff = kmalloc(len + 4, GFP_ATOMIC);
+ rbuff = kmalloc(len + 4, GFP_ATOMIC);
#ifdef SL_INCLUDE_CSLIP
- cbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+ cbuff = kmalloc(len + 4, GFP_ATOMIC);
#endif
return NULL;
}
- sv=(struct sv11_device *)kmalloc(sizeof(struct sv11_device), GFP_KERNEL);
+ sv = kmalloc(sizeof(struct sv11_device), GFP_KERNEL);
if(!sv)
goto fail3;
if ((err = pci_enable_device(pdev)) < 0)
return err;
- card = (pc300_t *) kmalloc(sizeof(pc300_t), GFP_KERNEL);
+ card = kmalloc(sizeof(pc300_t), GFP_KERNEL);
if (card == NULL) {
printk("PC300 found at RAM 0x%016llx, "
"but could not allocate card structure.\n",
continue;
}
- new = (st_cpc_rx_buf *)kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
+ new = kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
if (new == 0) {
cpc_tty_rx_disc_frame(pc300chan);
continue;
unsigned char *xbuff, *rbuff;
int len = 2* newmtu;
- xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
- rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+ xbuff = kmalloc(len + 4, GFP_ATOMIC);
+ rbuff = kmalloc(len + 4, GFP_ATOMIC);
if (xbuff == NULL || rbuff == NULL)
{
len = dev->mtu * 2;
- sl->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+ sl->rbuff = kmalloc(len + 4, GFP_KERNEL);
if (sl->rbuff == NULL) {
goto norbuff;
}
- sl->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+ sl->xbuff = kmalloc(len + 4, GFP_KERNEL);
if (sl->xbuff == NULL) {
goto noxbuff;
}
return NULL;
}
- tmpbuf = (char *) kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);
+ tmpbuf = kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);
if (tmpbuf == NULL) {
PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n");
return NULL;
0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
};
- buf = (u8 *) kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
+ buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
if (buf == NULL)
return NULL;
if (txdesc->sw_support) {
len = le16_to_cpu(txdesc->data_len);
if (len < PRISM2_DATA_MAXLEN) {
- *payload = (char *) kmalloc(len, GFP_ATOMIC);
+ *payload = kmalloc(len, GFP_ATOMIC);
if (*payload == NULL ||
hfa384x_from_bap(dev, BAP0, *payload, len)) {
PDEBUG(DEBUG_EXTRA, "%s: could not read TX "
p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
return -EINVAL;
- param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+ param = kmalloc(p->length, GFP_KERNEL);
if (param == NULL)
return -ENOMEM;
unsigned long flags;
struct hostap_tx_callback_info *entry;
- entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry),
+ entry = kmalloc(sizeof(*entry),
GFP_ATOMIC);
if (entry == NULL)
return 0;
if (priv->snapshot[0])
return 1;
for (i = 0; i < 0x30; i++) {
- priv->snapshot[i] = (u8 *) kmalloc(0x1000, GFP_ATOMIC);
+ priv->snapshot[i] = kmalloc(0x1000, GFP_ATOMIC);
if (!priv->snapshot[i]) {
IPW_DEBUG_INFO("%s: Error allocating snapshot "
"buffer %d\n", priv->net_dev->name, i);
p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
return -EINVAL;
- param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+ param = kmalloc(p->length, GFP_KERNEL);
if (param == NULL)
return -ENOMEM;
if(lp->wavepoint_table.num_wavepoints==MAX_WAVEPOINTS)
return NULL;
- new_wavepoint=(wavepoint_history *) kmalloc(sizeof(wavepoint_history),GFP_ATOMIC);
+ new_wavepoint = kmalloc(sizeof(wavepoint_history),GFP_ATOMIC);
if(new_wavepoint==NULL)
return NULL;
/* Allocate a single memory block for values and addresses. */
count16 = 2*count;
- a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
+ a16 = kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
GFP_NOFS);
if (!a16) {
dev_dbg_f(zd_chip_dev(chip),
return NULL;
}
- isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+ isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
if (!isi) {
BUG();
return NULL;
return 2;
while (nummem--) {
- mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
if (!mem_node)
break;
}
while (numpmem--) {
- p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
if (!p_mem_node)
break;
}
while (numio--) {
- io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
if (!io_node)
break;
}
while (numbus--) {
- bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
if (!bus_node)
break;
DBG_ENTER_ROUTINE
spin_lock_init(&list_lock);
- php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
+ php_ctlr = kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
if (!php_ctlr) { /* allocate controller state data */
err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
{
struct aer_rpc *rpc;
- if (!(rpc = (struct aer_rpc *)kmalloc(sizeof(struct aer_rpc),
+ if (!(rpc = kmalloc(sizeof(struct aer_rpc),
GFP_KERNEL)))
return NULL;
if (!io)
return -ENODEV;
- cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+ cf = kzalloc(sizeof *cf, GFP_KERNEL);
if (!cf)
return -ENOMEM;
if (irq < 0)
return -EINVAL;
- cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+ cf = kzalloc(sizeof *cf, GFP_KERNEL);
if (!cf)
return -ENOMEM;
init_timer(&cf->timer);
struct pnp_id * id;
if (!dev)
return;
- id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
struct pnp_dev *dev;
isapnp_peek(tmp, size);
- dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev)
return NULL;
dev->number = number;
unsigned long bits;
isapnp_peek(tmp, size);
- irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
bits = (tmp[1] << 8) | tmp[0];
struct pnp_dma *dma;
isapnp_peek(tmp, size);
- dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
dma->map = tmp[0];
struct pnp_port *port;
isapnp_peek(tmp, size);
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = (tmp[2] << 8) | tmp[1];
struct pnp_port *port;
isapnp_peek(tmp, size);
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = (tmp[1] << 8) | tmp[0];
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device)
{
- struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ struct pnp_id * id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
header[4], header[5], header[6], header[7], header[8]);
printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
#endif
- if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
+ if ((card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
continue;
card->number = csn;
return 0;
pnp_dbg("ACPI device : hid %s", acpi_device_hid(device));
- dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev) {
pnp_err("Out of memory");
return -ENOMEM;
dev->number = num;
/* set the initial values for the PnP device */
- dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
goto err;
pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
for (i = 0; i < cid_list->count; i++) {
if (!ispnpidacpi(cid_list->id[i].value))
continue;
- dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
continue;
if (p->channel_count == 0)
return;
- dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
if (p->interrupt_count == 0)
return;
- irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
if (p->interrupt_count == 0)
return;
- irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
if (io->address_length == 0)
return;
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = io->minimum;
if (io->address_length == 0)
return;
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = io->address;
if (p->address_length == 0)
return;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = p->minimum;
if (p->address_length == 0)
return;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = p->minimum;
if (p->address_length == 0)
return;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = p->address;
return;
if (p->resource_type == ACPI_MEMORY_RANGE) {
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = p->minimum;
ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0;
pnp_register_mem_resource(option, mem);
} else if (p->resource_type == ACPI_IO_RANGE) {
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = p->minimum;
if (!res_cnt)
return -EINVAL;
buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
- buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL);
+ buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
if (!buffer->pointer)
return -ENOMEM;
pnp_dbg("Res cnt %d", res_cnt);
if (!current->fs->root) {
return -EAGAIN;
}
- if (!(envp = (char **) kcalloc (20, sizeof (char *), GFP_KERNEL))) {
+ if (!(envp = kcalloc(20, sizeof (char *), GFP_KERNEL))) {
return -ENOMEM;
}
- if (!(buf = kcalloc (1, 256, GFP_KERNEL))) {
+ if (!(buf = kzalloc(256, GFP_KERNEL))) {
kfree (envp);
return -ENOMEM;
}
if(!pnpbios_is_dynamic(dev))
return -EPERM;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
if (!pnpbios_is_dynamic(dev))
return -EPERM;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
return -EPERM;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -ENOMEM;
}
/* set the initial values for the PnP device */
- dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
return -1;
pnpid32_to_pnpid(node->eisa_id,id);
struct pnp_bios_node *node;
struct pnp_dev *dev;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return;
break;
}
nodes_got++;
- dev = kcalloc(1, sizeof (struct pnp_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof (struct pnp_dev), GFP_KERNEL);
if (!dev)
break;
if(insert_device(dev,node)<0)
return -EFBIG;
}
- tmpbuf = kcalloc(1, escd.escd_size, GFP_KERNEL);
+ tmpbuf = kzalloc(escd.escd_size, GFP_KERNEL);
if (!tmpbuf) return -ENOMEM;
if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
if (pos >= 0xff)
return 0;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
for (nodenum=pos; nodenum<0xff; ) {
u8 nodenum = (long)data;
int len;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
kfree(node);
u8 nodenum = (long)data;
int ret = count;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -ENOMEM;
if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = ((p[5] << 8) | p[4]) << 8;
pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
struct pnp_irq * irq;
unsigned long bits;
- irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
bits = (p[2] << 8) | p[1];
pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_dma * dma;
- dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
dma->map = p[1];
pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_port * port;
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = (p[3] << 8) | p[2];
pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_port * port;
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = (p[2] << 8) | p[1];
case SMALL_TAG_COMPATDEVID: /* compatible ID */
if (len != 4)
goto len_err;
- dev_id = kcalloc(1, sizeof (struct pnp_id), GFP_KERNEL);
+ dev_id = kzalloc(sizeof (struct pnp_id), GFP_KERNEL);
if (!dev_id)
return NULL;
memset(dev_id, 0, sizeof(struct pnp_id));
tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
tm->tm_year = at91_alarm_year - 1900;
+ alrm->enabled = (at91_sys_read(AT91_RTC_IMR) & AT91_RTC_ALARM)
+ ? 1 : 0;
+
pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
{
unsigned long imr = at91_sys_read(AT91_RTC_IMR);
- seq_printf(seq, "alarm_IRQ\t: %s\n",
- (imr & AT91_RTC_ALARM) ? "yes" : "no");
seq_printf(seq, "update_IRQ\t: %s\n",
(imr & AT91_RTC_ACKUPD) ? "yes" : "no");
seq_printf(seq, "periodic_IRQ\t: %s\n",
goto err_cdev_del;
}
- dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n",
+ dev_dbg(class_dev->dev, "rtc intf: dev (%d:%d)\n",
MAJOR(rtc->rtc_dev->devt),
MINOR(rtc->rtc_dev->devt));
local_irq_enable();
bcd2tm(&alm->time);
- alm->pending = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
+ alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
& OMAP_RTC_INTERRUPTS_IT_ALARM);
- alm->enabled = alm->pending && device_may_wakeup(dev);
return 0;
}
seq_printf(seq, "%02d\n", alrm.time.tm_mday);
else
seq_printf(seq, "**\n");
- seq_printf(seq, "alrm_wakeup\t: %s\n",
+ seq_printf(seq, "alarm_IRQ\t: %s\n",
alrm.enabled ? "yes" : "no");
seq_printf(seq, "alrm_pending\t: %s\n",
alrm.pending ? "yes" : "no");
ent->owner = rtc->owner;
ent->data = class_dev;
- dev_info(class_dev->dev, "rtc intf: proc\n");
+ dev_dbg(class_dev->dev, "rtc intf: proc\n");
}
else
rtc_dev = NULL;
alm_en = readb(base + S3C2410_RTCALM);
+ alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
+
pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
alm_en,
alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
- unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM);
unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
- seq_printf(seq, "alarm_IRQ\t: %s\n",
- (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
-
seq_printf(seq, "periodic_IRQ\t: %s\n",
(ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{
- seq_printf(seq, "trim/divider\t: 0x%08lx\n", RTTR);
- seq_printf(seq, "alarm_IRQ\t: %s\n",
- (RTSR & RTSR_ALE) ? "yes" : "no" );
+ seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
seq_printf(seq, "update_IRQ\t: %s\n",
(RTSR & RTSR_HZE) ? "yes" : "no");
seq_printf(seq, "periodic_IRQ\t: %s\n",
{
int err;
- dev_info(class_dev->dev, "rtc intf: sysfs\n");
+ dev_dbg(class_dev->dev, "rtc intf: sysfs\n");
err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
if (err)
raw->cdev = cdev;
raw->inbuf = (char *) raw + sizeof(struct raw3215_info);
memset(raw, 0, sizeof(struct raw3215_info));
- raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE,
+ raw->buffer = kmalloc(RAW3215_BUFFER_SIZE,
GFP_KERNEL|GFP_DMA);
if (raw->buffer == NULL) {
spin_lock(&raw3215_device_lock);
if (!(key_map = kbd->key_maps[tmp.kb_table])) {
int j;
- key_map = (ushort *) kmalloc(sizeof(plain_map),
+ key_map = kmalloc(sizeof(plain_map),
GFP_KERNEL);
if (!key_map)
return -ENOMEM;
struct cpi_sccb *sccb;
struct cpi_evbuf *evb;
- req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
+ req = kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
if (req == NULL)
return ERR_PTR(-ENOMEM);
sccb = (struct cpi_sccb *) __get_free_page(GFP_KERNEL | GFP_DMA);
struct completion work;
int rc;
- ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
struct completion work;
int rc;
- ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
struct completion work;
int rc;
- ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
struct completion work;
int rc;
- ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
};
int rc;
- ap_msg.message = (void *) kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
return -1;
}
memset(ch, 0, sizeof (struct channel));
- if ((ch->ccw = (struct ccw1 *) kmalloc(8*sizeof(struct ccw1),
+ if ((ch->ccw = kmalloc(8*sizeof(struct ccw1),
GFP_KERNEL | GFP_DMA)) == NULL) {
kfree(ch);
ctc_pr_warn("ctc: Out of memory in add_channel\n");
return -1;
}
fsm_newstate(ch->fsm, CH_STATE_IDLE);
- if ((ch->irb = (struct irb *) kmalloc(sizeof (struct irb),
+ if ((ch->irb = kmalloc(sizeof (struct irb),
GFP_KERNEL)) == NULL) {
ctc_pr_warn("ctc: Out of memory in add_channel\n");
kfree_fsm(ch->fsm);
DBF_TEXT(trace, 4, __FUNCTION__);
if (!priv)
return;
- sbuf = (char *)kmalloc(2048, GFP_KERNEL);
+ sbuf = kmalloc(2048, GFP_KERNEL);
if (sbuf == NULL)
return;
p = sbuf;
}
/* Allocate handler entry */
- new_handler = (handler *)kmalloc(sizeof(handler), GFP_ATOMIC);
+ new_handler = kmalloc(sizeof(handler), GFP_ATOMIC);
if (new_handler == NULL) {
printk(KERN_WARNING "%s: storage allocation for new handler "
"failed.\n", __FUNCTION__);
return 0;
len = strlen(devstr) + 1;
- str = (char *) kmalloc(len, GFP_KERNEL);
+ str = kmalloc(len, GFP_KERNEL);
if (!str)
goto err_out;
memcpy(str, devstr, len);
if (!cards)
return -ENODEV;
- vfc_dev_lst = (struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *) *
+ vfc_dev_lst = kmalloc(sizeof(struct vfc_dev *) *
(cards+1),
GFP_KERNEL);
if (vfc_dev_lst == NULL)
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
- fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(
+ fsa_dev_ptr = kmalloc(
sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
if (!fsa_dev_ptr) {
aac_fib_free(fibptr);
* Ok now init the communication subsystem
*/
- dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
+ dev->queues = kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
if (dev->queues == NULL) {
printk(KERN_ERR "Error could not allocate comm region.\n");
return NULL;
#endif
int i;
ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
- SCpnt->host_scribble = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+ SCpnt->host_scribble = kmalloc(512, GFP_KERNEL | GFP_DMA);
sgpnt = (struct scatterlist *) SCpnt->request_buffer;
cptr = (struct chain *) SCpnt->host_scribble;
if (cptr == NULL) {
}
}
scb_count = min( (i-1), p->scb_data->maxscbs - p->scb_data->numscbs);
- scb_ap = (struct aic7xxx_scb *)kmalloc(sizeof (struct aic7xxx_scb) * scb_count
+ scb_ap = kmalloc(sizeof (struct aic7xxx_scb) * scb_count
+ sizeof(struct aic7xxx_scb_dma), GFP_ATOMIC);
if (scb_ap == NULL)
return(0);
dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
while (pages--) {
- ptr = (struct SGentry *)kmalloc(PAGE_SIZE, GFP_KERNEL);
+ ptr = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!ptr) {
adapter_sg_tables_free(acb);
return 1;
s32 rcode;
memset(msg, 0, sizeof(msg));
- buf = (u8*)kmalloc(80,GFP_KERNEL|ADDR32);
+ buf = kmalloc(80,GFP_KERNEL|ADDR32);
if(!buf){
printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name);
return;
schedule_timeout_uninterruptible(1);
} while (m == EMPTY_QUEUE);
- status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32);
+ status = kmalloc(4, GFP_KERNEL|ADDR32);
if(status == NULL) {
adpt_send_nop(pHba, m);
printk(KERN_ERR"IOP reset failed - no free memory.\n");
}
continue;
}
- d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
+ d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
if(d==NULL)
{
printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name);
pDev = pDev->next_lun;
}
if(!pDev ) { // Something new add it
- d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
+ d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
if(d==NULL)
{
printk(KERN_CRIT "Out of memory for I2O device data.\n");
kfree(pHba->reply_pool);
- pHba->reply_pool = (u32*)kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
+ pHba->reply_pool = kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
if(!pHba->reply_pool){
printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name);
return -1;
for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
i = tul_num_ch * tul_num_scb * sizeof(SCB);
- if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
+ if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
break;
}
if (tul_scb == NULL) {
dev_num = i;
/* allocate a struct osst_tape for this device */
- tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
+ tpnt = kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
if (tpnt == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
#endif
return 0;
}
- fcs = (struct ctrl_inquiry *) kmalloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
+ fcs = kmalloc(sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
if (!fcs) {
printk ("PLUTO: Not enough memory to probe\n");
return 0;
if (!xa_test)
return 0;
- raw_sector = (unsigned char *) kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd));
+ raw_sector = kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd));
if (!raw_sector)
return -ENOMEM;
if (0 == sr_read_sector(cd, cd->ms_offset + 16,
density = (blocklength > 2048) ? 0x81 : 0x83;
#endif
- buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
return -ENOMEM;
if (cd->cdi.mask & CDC_MULTI_SESSION)
return 0;
- buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
return -ENOMEM;
/*
* Allocate the array of lists of CCBs hashed by DSA.
*/
- np->ccbh = kcalloc(sizeof(struct sym_ccb **), CCB_HASH_SIZE, GFP_KERNEL);
+ np->ccbh = kcalloc(CCB_HASH_SIZE, sizeof(struct sym_ccb **), GFP_KERNEL);
if (!np->ccbh)
goto attach_failed;
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_1_460800 },
+ /*
+ * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408).
+ * Cards are identified by their subsystem vendor IDs, which
+ * (in hex) match the model number.
+ *
+ * Note that JC140x are RS422/485 cards which require ox950
+ * ACR = 0x10, and as such are not currently fully supported.
+ */
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1204, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1402, 0x0002, 0, 0,
+ pbn_b0_2_921600 }, */
+/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1404, 0x0004, 0, 0,
+ pbn_b0_4_921600 }, */
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1,
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+
/*
* Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
*/
{
struct at91_request *req;
- req = kcalloc(1, sizeof (struct at91_request), gfp_flags);
+ req = kzalloc(sizeof (struct at91_request), gfp_flags);
if (!req)
return NULL;
if (size == 0)
return NULL;
- gb = (struct gs_buf *)kmalloc(sizeof(struct gs_buf), kmalloc_flags);
+ gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags);
if (gb == NULL)
return NULL;
/* Adds an urb_entry last in the list for this epid. */
static inline void urb_list_add(struct urb *urb, int epid)
{
- urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
+ urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
assert(urb_entry);
urb_entry->urb = urb;
bep->bufp = kmalloc (bufsize, GFP_KERNEL);
if (!bep->bufp)
goto bl_fail;
- bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
+ bep->dr = kmalloc(sizeof (struct usb_ctrlrequest), GFP_KERNEL);
if (!bep->dr)
goto bl_fail;
bep->urbp = usb_alloc_urb (0, GFP_KERNEL);
info("device is a %s", cp->dev_desc);
/* get the maximum allowed control transfer length */
- pbuf = (__le16 *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */
+ pbuf = kmalloc(2, GFP_KERNEL); /* use an allocated buffer because of urb target */
if (!pbuf) {
err( "out of memory");
goto pfail;
/*
* Allocate parport interface
*/
- if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
+ if (!(priv = kzalloc(sizeof(struct parport_uss720_private), GFP_KERNEL))) {
usb_put_dev(usbdev);
return -ENOMEM;
}
struct rndis_halt *halt;
/* try to clear any rndis state/activity (no i/o from stack!) */
- halt = kcalloc(1, sizeof *halt, GFP_KERNEL);
+ halt = kzalloc(sizeof *halt, GFP_KERNEL);
if (halt) {
halt->msg_type = RNDIS_MSG_HALT;
halt->msg_len = ccpu2(sizeof *halt);
if (size == 0)
return NULL;
- cb = (struct cypress_buf *)kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
+ cb = kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
if (cb == NULL)
return NULL;
for( i=0; i<serial->type->num_ports+1; i++ ) {
/* allocate port private structure */
- priv = (struct digi_port *)kmalloc( sizeof(struct digi_port),
+ priv = kmalloc( sizeof(struct digi_port),
GFP_KERNEL );
if( priv == (struct digi_port *)0 ) {
while( --i >= 0 )
}
/* allocate serial private structure */
- serial_priv = (struct digi_serial *)kmalloc( sizeof(struct digi_serial),
+ serial_priv = kmalloc( sizeof(struct digi_serial),
GFP_KERNEL );
if( serial_priv == (struct digi_serial *)0 ) {
for( i=0; i<serial->type->num_ports+1; i++ )
if (size == 0)
return NULL;
- eb = (struct edge_buf *)kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
+ eb = kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
if (eb == NULL)
return NULL;
bytes_in = 0;
bytes_out = 0;
- priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
+ priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
if (priv == NULL) {
err("%s - Out of memory", __FUNCTION__);
return -ENOMEM;
}
// allocate memory for write_urb transfer buffer
- port->write_urb->transfer_buffer = (unsigned char *) kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
+ port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
if (! port->write_urb->transfer_buffer) {
kfree(transfer_buffer);
usb_free_urb(port->write_urb);
return 0;
case TCFLSH: // 0x540B
- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
+ transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
if (! transfer_buffer) {
return -ENOBUFS;
}
if (size == 0)
return NULL;
- pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+ pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
if (pb == NULL)
return NULL;
{
struct circ_buf *cb;
- cb = (struct circ_buf *)kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+ cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
if (cb == NULL)
return NULL;
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
+ info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
err("%s: Out of memory for port structures\n", serial->type->description);
goto no_private;
usb_set_serial_port_data(port, info);
}
- command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+ command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
if (command_info == NULL) {
err("%s: Out of memory for port structures\n", serial->type->description);
goto no_command_private;
return result;
}
- buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO);
+ buf = kmalloc(bulklen, GFP_NOIO);
if (!buf)
return -ENOMEM;
goto out;
}
- fb = (struct clcd_fb *) kmalloc(sizeof(struct clcd_fb), GFP_KERNEL);
+ fb = kmalloc(sizeof(struct clcd_fb), GFP_KERNEL);
if (!fb) {
printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
ret = -ENOMEM;
par->crsr.spot_x = par->crsr.spot_y = 0;
par->crsr.height = par->crsr.width = 0;
-#if 0 /* fbmon not done. uncomment for 2.5.x -brad */
- if (!fbmon_valid_timings(pixclock[clk_shift], htotal, vtotal,
- &fb_info)) {
- DPRINTK("mode doesn't fit for monitor\n");
- return -EINVAL;
- }
-#endif
-
return 0;
}
else
info->var.accel_flags = 0;
-#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
- if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
- return -EINVAL;
-#endif
aty_crtc_to_var(&crtc, var);
var->pixclock = par->pll_ops->pll_to_var(info, &pll);
return 0;
unsigned long flags;
struct matroxfb_dh_maven_info* m2info;
- m2info = (struct matroxfb_dh_maven_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
+ m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
if (!m2info)
return NULL;
}
#ifdef CONFIG_FB_MATROX_MULTIHEAD
- minfo = (struct matrox_fb_info*)kmalloc(sizeof(*minfo), GFP_KERNEL);
+ minfo = kmalloc(sizeof(*minfo), GFP_KERNEL);
if (!minfo)
return -1;
#else
/* hardware is CRTC2 incapable... */
if (!ACCESS_FBINFO(devflags.crtc2))
return NULL;
- m2info = (struct matroxfb_dh_fb_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
+ m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
if (!m2info) {
printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
return NULL;
* Remove never finished and bogus 24/32bit support
* Clean up macro abuse
* Minor tidying for format.
+ * 12/2006 Helge Deller <deller@gmx.de>
+ * add /sys/class/graphics/fbX/vgapass sysfs-interface
+ * add module option "mode_option" to set initial screen mode
+ * use fbdev default videomode database
+ * remove debug functions from ioctl
*/
/*
*
* sstfb specific ioctls:
* toggle vga (0x46db) : toggle vga_pass_through
- * fill fb (0x46dc) : fills fb
- * test disp (0x46de) : draws a test image
*/
#undef SST_DEBUG
-/*
- Default video mode .
- 0 800x600@60 took from glide
- 1 640x480@75 took from glide
- 2 1024x768@76 std fb.mode
- 3 640x480@60 glide default */
-#define DEFAULT_MODE 3
/*
* Includes
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/io.h>
-#include <asm/ioctl.h>
#include <asm/uaccess.h>
#include <video/sstfb.h>
/* initialized by setup */
-static int vgapass; /* enable Vga passthrough cable */
+static int vgapass; /* enable VGA passthrough cable */
static int mem; /* mem size in MB, 0 = autodetect */
static int clipping = 1; /* use clipping (slower, safer) */
static int gfxclk; /* force FBI freq in Mhz . Dangerous */
static int slowpci; /* slow PCI settings */
-static char *mode_option __devinitdata;
+/*
+ Possible default video modes: 800x600@60, 640x480@75, 1024x768@76, 640x480@60
+*/
+#define DEFAULT_VIDEO_MODE "640x480@60"
+
+static char *mode_option __devinitdata = DEFAULT_VIDEO_MODE;
enum {
ID_VOODOO1 = 0,
{ .name = "Voodoo2", .default_gfx_clock = 75000, .max_gfxclk = 85 },
};
-static struct fb_var_screeninfo sstfb_default =
-#if ( DEFAULT_MODE == 0 )
- { /* 800x600@60, 16 bpp .borowed from glide/sst1/include/sst1init.h */
- 800, 600, 800, 600, 0, 0, 16, 0,
- {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0,
- 25000, 86, 41, 23, 1, 127, 4,
- 0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 1 )
- {/* 640x480@75, 16 bpp .borowed from glide/sst1/include/sst1init.h */
- 640, 480, 640, 480, 0, 0, 16, 0,
- {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0,
- 31746, 118, 17, 16, 1, 63, 3,
- 0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 2 )
- { /* 1024x768@76 took from my /etc/fb.modes */
- 1024, 768, 1024, 768,0, 0, 16,0,
- {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0,
- 11764, 208, 8, 36, 16, 120, 3 ,
- 0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 3 )
- { /* 640x480@60 , 16bpp glide default ?*/
- 640, 480, 640, 480, 0, 0, 16, 0,
- {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0,
- 39721 , 38, 26 , 25 ,18 , 96 ,2,
- 0, FB_VMODE_NONINTERLACED };
-#elif
- #error "Invalid DEFAULT_MODE value !"
-#endif
-
/*
* debug functions
*/
-static void sstfb_drawdebugimage(struct fb_info *info);
-static int sstfb_dump_regs(struct fb_info *info);
-
-
#if (SST_DEBUG_REG > 0)
static void sst_dbg_print_read_reg(u32 reg, u32 val) {
const char *regname;
return 0;
}
-static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+static void sstfb_setvgapass( struct fb_info *info, int enable )
{
struct sstfb_par *par = info->par;
struct pci_dev *sst_dev = par->dev;
- u32 fbiinit0, tmp, val;
- u_long p;
+ u32 fbiinit0, tmp;
+
+ enable = enable ? 1:0;
+ if (par->vgapass == enable)
+ return;
+ par->vgapass = enable;
+
+ pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
+ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+ tmp | PCI_EN_INIT_WR );
+ fbiinit0 = sst_read (FBIINIT0);
+ if (par->vgapass) {
+ sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH);
+ printk(KERN_INFO "fb%d: Enabling VGA pass-through\n", info->node );
+ } else {
+ sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH);
+ printk(KERN_INFO "fb%d: Disabling VGA pass-through\n", info->node );
+ }
+ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
+}
+
+static ssize_t store_vgapass(struct device *device, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *info = dev_get_drvdata(device);
+ char ** last = NULL;
+ int val;
+
+ val = simple_strtoul(buf, last, 0);
+ sstfb_setvgapass(info, val);
+
+ return count;
+}
+
+static ssize_t show_vgapass(struct device *device, struct device_attribute *attr,
+ char *buf)
+{
+ struct fb_info *info = dev_get_drvdata(device);
+ struct sstfb_par *par = info->par;
+ return snprintf(buf, PAGE_SIZE, "%d\n", par->vgapass);
+}
+
+static struct device_attribute device_attrs[] = {
+ __ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass)
+ };
+
+static int sstfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sstfb_par *par;
+ u32 val;
switch (cmd) {
-
- /* dump current FBIINIT values to system log */
- case _IO('F', 0xdb): /* 0x46db */
- return sstfb_dump_regs(info);
-
- /* fills lfb with #arg pixels */
- case _IOW('F', 0xdc, u32): /* 0x46dc */
+ /* set/get VGA pass_through mode */
+ case SSTFB_SET_VGAPASS:
if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
return -EFAULT;
- if (val > info->fix.smem_len)
- val = info->fix.smem_len;
- for (p = 0 ; p < val; p += 2)
- writew(p >> 6, info->screen_base + p);
+ sstfb_setvgapass(info, val);
return 0;
-
- /* change VGA pass_through mode */
- case _IOW('F', 0xdd, u32): /* 0x46dd */
- if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
+ case SSTFB_GET_VGAPASS:
+ par = info->par;
+ val = par->vgapass;
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
return -EFAULT;
- pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
- tmp | PCI_EN_INIT_WR );
- fbiinit0 = sst_read (FBIINIT0);
- if (val)
- sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH);
- else
- sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH);
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
- return 0;
-
- /* draw test image */
- case _IO('F', 0xde): /* 0x46de */
- f_dprintk("test color display at %d bpp\n",
- info->var.bits_per_pixel);
- sstfb_drawdebugimage(info);
return 0;
}
+
return -EINVAL;
}
/*
* FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
*/
+#if 0
static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct sstfb_par *par = info->par;
| (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) );
sst_wait_idle();
}
+#endif
struct pll_timing gfx_timings;
struct sst_spec *spec;
int Fout;
+ int gfx_clock;
spec = &voodoo_spec[par->type];
f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 "
}
/* set graphic clock */
- par->gfx_clock = spec->default_gfx_clock;
+ gfx_clock = spec->default_gfx_clock;
if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk);
- par->gfx_clock = gfxclk *1000;
+ gfx_clock = gfxclk *1000;
} else if (gfxclk) {
printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk);
}
- sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings);
+ sst_calc_pll(gfx_clock, &Fout, &gfx_timings);
par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
/* disable fbiinit remap */
fbiinit0 = FBIINIT0_DEFAULT;
fbiinit1 = FBIINIT1_DEFAULT;
fbiinit4 = FBIINIT4_DEFAULT;
- if (vgapass)
- fbiinit0 &= ~EN_VGA_PASSTHROUGH;
+ par->vgapass = vgapass;
+ if (par->vgapass)
+ fbiinit0 &= ~DIS_VGA_PASSTHROUGH;
else
- fbiinit0 |= EN_VGA_PASSTHROUGH;
+ fbiinit0 |= DIS_VGA_PASSTHROUGH;
if (slowpci) {
fbiinit1 |= SLOW_PCI_WRITES;
fbiinit4 |= SLOW_PCI_READS;
/* TODO maybe shutdown the dac, vrefresh and so on... */
pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR);
- sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH);
+ sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | DIS_VGA_PASSTHROUGH);
pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct
* from start ? */
/*
* Interface to the world
*/
-#ifndef MODULE
-static int __init sstfb_setup(char *options)
+static int __devinit sstfb_setup(char *options)
{
char *this_opt;
}
return 0;
}
-#endif
+
static struct fb_ops sstfb_ops = {
.owner = THIS_MODULE,
*/
fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */
- if ( mode_option &&
- fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) {
- printk(KERN_ERR "sstfb: can't set supplied video mode. Using default\n");
- info->var = sstfb_default;
- } else
- info->var = sstfb_default;
+ fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
if (sstfb_check_var(&info->var, info)) {
- printk(KERN_ERR "sstfb: invalid default video mode.\n");
+ printk(KERN_ERR "sstfb: invalid video mode.\n");
goto fail;
}
goto fail;
}
- if (1) /* set to 0 to see an initial bitmap instead */
- sstfb_clear_screen(info);
- else
- sstfb_drawdebugimage(info);
+ sstfb_clear_screen(info);
+
+ if (device_create_file(info->dev, &device_attrs[0]))
+ printk(KERN_WARNING "sstfb: can't create sysfs entry.\n");
+
printk(KERN_INFO "fb%d: %s frame buffer device at 0x%p\n",
info->node, fix->id, info->screen_base);
return 0;
fail:
+ fb_dealloc_cmap(&info->cmap);
iounmap(info->screen_base);
fail_fb_remap:
iounmap(par->mmio_vbase);
info = pci_get_drvdata(pdev);
par = info->par;
+ device_remove_file(info->dev, &device_attrs[0]);
sst_shutdown(info);
- unregister_framebuffer(info);
iounmap(info->screen_base);
iounmap(par->mmio_vbase);
release_mem_region(info->fix.smem_start, 0x400000);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+ fb_dealloc_cmap(&info->cmap);
+ unregister_framebuffer(info);
framebuffer_release(info);
}
-static struct pci_device_id sstfb_id_tbl[] = {
- { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },
- { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },
+static const struct pci_device_id sstfb_id_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO ),
+ .driver_data = ID_VOODOO1, },
+ { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2),
+ .driver_data = ID_VOODOO2, },
{ 0 },
};
static int __devinit sstfb_init(void)
{
-#ifndef MODULE
char *option = NULL;
if (fb_get_options("sstfb", &option))
return -ENODEV;
sstfb_setup(option);
-#endif
+
return pci_register_driver(&sstfb_driver);
}
-#ifdef MODULE
static void __devexit sstfb_exit(void)
{
pci_unregister_driver(&sstfb_driver);
}
-#endif
-/*
- * testing and debugging functions
- */
-
-static int sstfb_dump_regs(struct fb_info *info)
-{
-#ifdef SST_DEBUG
- static struct { u32 reg ; const char *reg_name;} pci_regs[] = {
- { PCI_INIT_ENABLE, "initenable"},
- { PCI_VCLK_ENABLE, "enable vclk"},
- { PCI_VCLK_DISABLE, "disable vclk"},
- };
-
- static struct { u32 reg ; const char *reg_name;} sst_regs[] = {
- {FBIINIT0,"fbiinit0"},
- {FBIINIT1,"fbiinit1"},
- {FBIINIT2,"fbiinit2"},
- {FBIINIT3,"fbiinit3"},
- {FBIINIT4,"fbiinit4"},
- {FBIINIT5,"fbiinit5"},
- {FBIINIT6,"fbiinit6"},
- {FBIINIT7,"fbiinit7"},
- {LFBMODE,"lfbmode"},
- {FBZMODE,"fbzmode"},
- };
-
- const int pci_s = ARRAY_SIZE(pci_regs);
- const int sst_s = ARRAY_SIZE(sst_regs);
- struct sstfb_par *par = info->par;
- struct pci_dev *dev = par->dev;
- u32 pci_res[pci_s];
- u32 sst_res[sst_s];
- int i;
-
- for (i=0; i<pci_s; i++) {
- pci_read_config_dword(dev, pci_regs[i].reg, &pci_res[i]);
- }
- for (i=0; i<sst_s; i++) {
- sst_res[i] = sst_read(sst_regs[i].reg);
- }
-
- dprintk("hardware register dump:\n");
- for (i=0; i<pci_s; i++) {
- dprintk("%s %0#10x\n", pci_regs[i].reg_name, pci_res[i]);
- }
- for (i=0; i<sst_s; i++) {
- dprintk("%s %0#10x\n", sst_regs[i].reg_name, sst_res[i]);
- }
- return 0;
-#else
- return -EINVAL;
-#endif
-}
-
-static void sstfb_fillrect_softw( struct fb_info *info, const struct fb_fillrect *rect)
-{
- u8 __iomem *fbbase_virt = info->screen_base;
- int x, y, w = info->var.bits_per_pixel == 16 ? 2 : 4;
- u32 color = rect->color, height = rect->height;
- u8 __iomem *p;
-
- if (w==2) color |= color<<16;
- for (y=rect->dy; height; y++, height--) {
- p = fbbase_virt + y*info->fix.line_length + rect->dx*w;
- x = rect->width;
- if (w==2) x>>=1;
- while (x) {
- writel(color, p);
- p += 4;
- x--;
- }
- }
-}
-
-static void sstfb_drawrect_XY( struct fb_info *info, int x, int y,
- int w, int h, int color, int hwfunc)
-{
- struct fb_fillrect rect;
- rect.dx = x;
- rect.dy = y;
- rect.height = h;
- rect.width = w;
- rect.color = color;
- rect.rop = ROP_COPY;
- if (hwfunc)
- sstfb_fillrect(info, &rect);
- else
- sstfb_fillrect_softw(info, &rect);
-}
-
-/* print some squares on the fb */
-static void sstfb_drawdebugimage(struct fb_info *info)
-{
- static int idx;
-
- /* clear screen */
- sstfb_clear_screen(info);
-
- idx = (idx+1) & 1;
-
- /* white rect */
- sstfb_drawrect_XY(info, 0, 0, 50, 50, 0xffff, idx);
-
- /* blue rect */
- sstfb_drawrect_XY(info, 50, 50, 50, 50, 0x001f, idx);
-
- /* green rect */
- sstfb_drawrect_XY(info, 100, 100, 80, 80, 0x07e0, idx);
-
- /* red rect */
- sstfb_drawrect_XY(info, 250, 250, 120, 100, 0xf800, idx);
-}
-
module_init(sstfb_init);
-
-#ifdef MODULE
module_exit(sstfb_exit);
-#endif
MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");
module_param(slowpci, bool, 0);
MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode (default=" DEFAULT_VIDEO_MODE ")");
+
tristate "Thermal family implementation"
depends on W1
help
- Say Y here if you want to connect 1-wire thermal sensors to you
+ Say Y here if you want to connect 1-wire thermal sensors to your
wire.
config W1_SLAVE_SMEM
depends on W1
help
Say Y here if you want to connect 1-wire
- simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+ simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
config W1_SLAVE_DS2433
tristate "4kb EEPROM family support (DS2433)"
* Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise
* it won't work. Update it accordingly if you change it here
*/
- activate_mm(active_mm, mm);
+ switch_mm(active_mm, mm, tsk);
task_unlock(tsk);
mmdrop(active_mm);
struct autofs_sb_info *sbi;
struct autofs_info *ino;
- sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL);
+ sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
if ( !sbi )
goto fail_unlock;
DPRINTK("starting up, sbi = %p",sbi);
goto error;
}
- this_node = (befs_btree_node *) kmalloc(sizeof (befs_btree_node),
+ this_node = kmalloc(sizeof (befs_btree_node),
GFP_NOFS);
if (!this_node) {
befs_error(sb, "befs_btree_find() failed to allocate %u "
befs_error(const struct super_block *sb, const char *fmt, ...)
{
va_list args;
- char *err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+ char *err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
if (err_buf == NULL) {
printk(KERN_ERR "could not allocate %d bytes\n", ERRBUFSIZE);
return;
befs_warning(const struct super_block *sb, const char *fmt, ...)
{
va_list args;
- char *err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+ char *err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
if (err_buf == NULL) {
printk(KERN_ERR "could not allocate %d bytes\n", ERRBUFSIZE);
return;
char *err_buf = NULL;
if (BEFS_SB(sb)->mount_opts.debug) {
- err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+ err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
if (err_buf == NULL) {
printk(KERN_ERR "could not allocate %d bytes\n",
ERRBUFSIZE);
/*
* fs/bfs/inode.c
* BFS superblock and inode operations.
- * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
+ * Copyright (C) 1999-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
* From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
*
* Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005.
#include <asm/uaccess.h>
#include "bfs.h"
-MODULE_AUTHOR("Tigran A. Aivazian <tigran@veritas.com>");
+MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux");
MODULE_LICENSE("GPL");
err = -ENOMEM;
memsize = sizeof(Node) + count + 8;
- e = (Node *) kmalloc(memsize, GFP_USER);
+ e = kmalloc(memsize, GFP_USER);
if (!e)
goto out;
}
}
-static void bio_release_pages(struct bio *bio)
+void bio_release_pages(struct bio *bio)
{
struct bio_vec *bvec = bio->bi_io_vec;
int i;
return 0;
}
-static int
-blkdev_get_blocks(struct inode *inode, sector_t iblock,
- struct buffer_head *bh, int create)
+static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error)
{
- sector_t end_block = max_block(I_BDEV(inode));
- unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
+ struct kiocb *iocb = bio->bi_private;
+ atomic_t *bio_count = &iocb->ki_bio_count;
- if ((iblock + max_blocks) > end_block) {
- max_blocks = end_block - iblock;
- if ((long)max_blocks <= 0) {
- if (create)
- return -EIO; /* write fully beyond EOF */
- /*
- * It is a read which is fully beyond EOF. We return
- * a !buffer_mapped buffer
- */
- max_blocks = 0;
- }
+ if (bio_data_dir(bio) == READ)
+ bio_check_pages_dirty(bio);
+ else {
+ bio_release_pages(bio);
+ bio_put(bio);
+ }
+
+ /* iocb->ki_nbytes stores error code from LLDD */
+ if (error)
+ iocb->ki_nbytes = -EIO;
+
+ if (atomic_dec_and_test(bio_count)) {
+ if (iocb->ki_nbytes < 0)
+ aio_complete(iocb, iocb->ki_nbytes, 0);
+ else
+ aio_complete(iocb, iocb->ki_left, 0);
}
- bh->b_bdev = I_BDEV(inode);
- bh->b_blocknr = iblock;
- bh->b_size = max_blocks << inode->i_blkbits;
- if (max_blocks)
- set_buffer_mapped(bh);
return 0;
}
+#define VEC_SIZE 16
+struct pvec {
+ unsigned short nr;
+ unsigned short idx;
+ struct page *page[VEC_SIZE];
+};
+
+#define PAGES_SPANNED(addr, len) \
+ (DIV_ROUND_UP((addr) + (len), PAGE_SIZE) - (addr) / PAGE_SIZE);
+
+/*
+ * get page pointer for user addr, we internally cache struct page array for
+ * (addr, count) range in pvec to avoid frequent call to get_user_pages. If
+ * internal page list is exhausted, a batch count of up to VEC_SIZE is used
+ * to get next set of page struct.
+ */
+static struct page *blk_get_page(unsigned long addr, size_t count, int rw,
+ struct pvec *pvec)
+{
+ int ret, nr_pages;
+ if (pvec->idx == pvec->nr) {
+ nr_pages = PAGES_SPANNED(addr, count);
+ nr_pages = min(nr_pages, VEC_SIZE);
+ down_read(¤t->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm, addr, nr_pages,
+ rw == READ, 0, pvec->page, NULL);
+ up_read(¤t->mm->mmap_sem);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ pvec->nr = ret;
+ pvec->idx = 0;
+ }
+ return pvec->page[pvec->idx++];
+}
+
static ssize_t
blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
-{
- struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_mapping->host;
+ loff_t pos, unsigned long nr_segs)
+{
+ struct inode *inode = iocb->ki_filp->f_mapping->host;
+ unsigned blkbits = blksize_bits(bdev_hardsect_size(I_BDEV(inode)));
+ unsigned blocksize_mask = (1 << blkbits) - 1;
+ unsigned long seg = 0; /* iov segment iterator */
+ unsigned long nvec; /* number of bio vec needed */
+ unsigned long cur_off; /* offset into current page */
+ unsigned long cur_len; /* I/O len of current page, up to PAGE_SIZE */
+
+ unsigned long addr; /* user iovec address */
+ size_t count; /* user iovec len */
+ size_t nbytes = iocb->ki_nbytes = iocb->ki_left; /* total xfer size */
+ loff_t size; /* size of block device */
+ struct bio *bio;
+ atomic_t *bio_count = &iocb->ki_bio_count;
+ struct page *page;
+ struct pvec pvec;
+
+ pvec.nr = 0;
+ pvec.idx = 0;
+
+ if (pos & blocksize_mask)
+ return -EINVAL;
+
+ size = i_size_read(inode);
+ if (pos + nbytes > size) {
+ nbytes = size - pos;
+ iocb->ki_left = nbytes;
+ }
+
+ /*
+ * check first non-zero iov alignment, the remaining
+ * iov alignment is checked inside bio loop below.
+ */
+ do {
+ addr = (unsigned long) iov[seg].iov_base;
+ count = min(iov[seg].iov_len, nbytes);
+ if (addr & blocksize_mask || count & blocksize_mask)
+ return -EINVAL;
+ } while (!count && ++seg < nr_segs);
+ atomic_set(bio_count, 1);
+
+ while (nbytes) {
+ /* roughly estimate number of bio vec needed */
+ nvec = (nbytes + PAGE_SIZE - 1) / PAGE_SIZE;
+ nvec = max(nvec, nr_segs - seg);
+ nvec = min(nvec, (unsigned long) BIO_MAX_PAGES);
+
+ /* bio_alloc should not fail with GFP_KERNEL flag */
+ bio = bio_alloc(GFP_KERNEL, nvec);
+ bio->bi_bdev = I_BDEV(inode);
+ bio->bi_end_io = blk_end_aio;
+ bio->bi_private = iocb;
+ bio->bi_sector = pos >> blkbits;
+same_bio:
+ cur_off = addr & ~PAGE_MASK;
+ cur_len = PAGE_SIZE - cur_off;
+ if (count < cur_len)
+ cur_len = count;
+
+ page = blk_get_page(addr, count, rw, &pvec);
+ if (unlikely(IS_ERR(page)))
+ goto backout;
+
+ if (bio_add_page(bio, page, cur_len, cur_off)) {
+ pos += cur_len;
+ addr += cur_len;
+ count -= cur_len;
+ nbytes -= cur_len;
+
+ if (count)
+ goto same_bio;
+ while (++seg < nr_segs) {
+ addr = (unsigned long) iov[seg].iov_base;
+ count = iov[seg].iov_len;
+ if (!count)
+ continue;
+ if (unlikely(addr & blocksize_mask ||
+ count & blocksize_mask)) {
+ page = ERR_PTR(-EINVAL);
+ goto backout;
+ }
+ count = min(count, nbytes);
+ goto same_bio;
+ }
+ }
- return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode),
- iov, offset, nr_segs, blkdev_get_blocks, NULL);
+ /* bio is ready, submit it */
+ if (rw == READ)
+ bio_set_pages_dirty(bio);
+ atomic_inc(bio_count);
+ submit_bio(rw, bio);
+ }
+
+completion:
+ iocb->ki_left -= nbytes;
+ nbytes = iocb->ki_left;
+ iocb->ki_pos += nbytes;
+
+ blk_run_address_space(inode->i_mapping);
+ if (atomic_dec_and_test(bio_count))
+ aio_complete(iocb, nbytes, 0);
+
+ return -EIOCBQUEUED;
+
+backout:
+ /*
+ * back out nbytes count constructed so far for this bio,
+ * we will throw away current bio.
+ */
+ nbytes += bio->bi_size;
+ bio_release_pages(bio);
+ bio_put(bio);
+
+ /*
+ * if no bio was submmitted, return the error code.
+ * otherwise, proceed with pending I/O completion.
+ */
+ if (atomic_read(bio_count) == 1)
+ return PTR_ERR(page);
+ goto completion;
}
static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
} else {
/* Add file to outstanding requests */
/* BB change to kmem cache alloc */
- dnotify_req = (struct dir_notify_req *) kmalloc(
+ dnotify_req = kmalloc(
sizeof(struct dir_notify_req),
GFP_KERNEL);
if(dnotify_req) {
#include <linux/kobject.h>
#include <linux/namei.h>
#include <linux/debugfs.h>
+#include <linux/fsnotify.h>
#define DEBUGFS_MAGIC 0x64626720
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ /* directory inodes start off with i_nlink == 2
+ * (for "." entry) */
inc_nlink(inode);
break;
}
mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
res = debugfs_mknod(dir, dentry, mode, 0);
- if (!res)
+ if (!res) {
inc_nlink(dir);
+ fsnotify_mkdir(dir, dentry);
+ }
return res;
}
static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
{
+ int res;
+
mode = (mode & S_IALLUGO) | S_IFREG;
- return debugfs_mknod(dir, dentry, mode, 0);
+ res = debugfs_mknod(dir, dentry, mode, 0);
+ if (!res)
+ fsnotify_create(dir, dentry);
+ return res;
}
static inline int debugfs_positive(struct dentry *dentry)
* block. A pointer to that is in the struct vfsmount that we
* have around.
*/
- if (!parent ) {
+ if (!parent) {
if (debugfs_mount && debugfs_mount->mnt_sb) {
parent = debugfs_mount->mnt_sb->s_root;
}
error = debugfs_mkdir(parent->d_inode, *dentry, mode);
else
error = debugfs_create(parent->d_inode, *dentry, mode);
+ dput(*dentry);
} else
error = PTR_ERR(*dentry);
mutex_unlock(&parent->d_inode->i_mutex);
pr_debug("debugfs: creating file '%s'\n",name);
- error = simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);
+ error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
+ &debugfs_mount_count);
if (error)
goto exit;
error = debugfs_create_by_name(name, mode, parent, &dentry);
if (error) {
dentry = NULL;
+ simple_release_fs(&debugfs_mount, &debugfs_mount_count);
goto exit;
}
void debugfs_remove(struct dentry *dentry)
{
struct dentry *parent;
+ int ret = 0;
if (!dentry)
return;
mutex_lock(&parent->d_inode->i_mutex);
if (debugfs_positive(dentry)) {
if (dentry->d_inode) {
- if (S_ISDIR(dentry->d_inode->i_mode))
- simple_rmdir(parent->d_inode, dentry);
- else
+ dget(dentry);
+ if (S_ISDIR(dentry->d_inode->i_mode)) {
+ ret = simple_rmdir(parent->d_inode, dentry);
+ if (ret)
+ printk(KERN_ERR
+ "DebugFS rmdir on %s failed : "
+ "directory not empty.\n",
+ dentry->d_name.name);
+ } else
simple_unlink(parent->d_inode, dentry);
- dput(dentry);
+ if (!ret)
+ d_delete(dentry);
+ dput(dentry);
}
}
mutex_unlock(&parent->d_inode->i_mutex);
res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
return res;
}
-
EXPORT_SYMBOL(bmap);
/**
if (IS_RDONLY(inode))
return;
-
- if ((inode->i_flags & S_NOATIME) ||
- (inode->i_sb->s_flags & MS_NOATIME) ||
- ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
+ if (inode->i_flags & S_NOATIME)
+ return;
+ if (inode->i_sb->s_flags & MS_NOATIME)
+ return;
+ if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
return;
/*
* We may have a NULL vfsmount when coming from NFSD
*/
- if (mnt &&
- ((mnt->mnt_flags & MNT_NOATIME) ||
- ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))))
- return;
+ if (mnt) {
+ if (mnt->mnt_flags & MNT_NOATIME)
+ return;
+ if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+ return;
- now = current_fs_time(inode->i_sb);
- if (!timespec_equal(&inode->i_atime, &now)) {
- inode->i_atime = now;
- mark_inode_dirty_sync(inode);
+ if (mnt->mnt_flags & MNT_RELATIME) {
+ /*
+ * With relative atime, only update atime if the
+ * previous atime is earlier than either the ctime or
+ * mtime.
+ */
+ if (timespec_compare(&inode->i_mtime,
+ &inode->i_atime) < 0 &&
+ timespec_compare(&inode->i_ctime,
+ &inode->i_atime) < 0)
+ return;
+ }
}
-}
+ now = current_fs_time(inode->i_sb);
+ if (timespec_equal(&inode->i_atime, &now))
+ return;
+
+ inode->i_atime = now;
+ mark_inode_dirty_sync(inode);
+}
EXPORT_SYMBOL(touch_atime);
/**
D1({
int len = dentry->d_name.len;
- char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
+ char *_name = kmalloc(len + 1, GFP_KERNEL);
memcpy(_name, dentry->d_name.name, len);
_name[len] = '\0';
printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
D1({
int len = dentry->d_name.len;
const char *name = dentry->d_name.name;
- char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
+ char *_name = kmalloc(len + 1, GFP_KERNEL);
memcpy(_name, name, len);
_name[len] = '\0';
printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
int i, length;
/* Allocate read buffer */
- read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL);
+ read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
if (!read_buf) {
printk(KERN_NOTICE "kmalloc failed in jffs_checksum_flash()\n");
return -ENOMEM;
/* Allocate read buffers */
- read_buf1 = (__u8 *) kmalloc (sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
+ read_buf1 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
if (!read_buf1)
return -ENOMEM;
- read_buf2 = (__u8 *) kmalloc (sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
+ read_buf2 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
if (!read_buf2) {
kfree(read_buf1);
return -ENOMEM;
}
/* Allocate read buffer */
- read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL);
+ read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
if (!read_buf) {
flash_safe_release(fmc->mtd);
return -ENOMEM;
kfree(f->name);
DJM(no_name--);
}
- if (!(f->name = (char *) kmalloc(raw_inode->nsize + 1,
+ if (!(f->name = kmalloc(raw_inode->nsize + 1,
GFP_KERNEL))) {
return -ENOMEM;
}
printk("jffs_find_child(): Found \"%s\".\n", f->name);
}
else {
- char *copy = (char *) kmalloc(len + 1, GFP_KERNEL);
+ char *copy = kmalloc(len + 1, GFP_KERNEL);
if (copy) {
memcpy(copy, name, len);
copy[len] = '\0';
return;
}
- if (!(space = (char *) kmalloc(indent + 1, GFP_KERNEL))) {
+ if (!(space = kmalloc(indent + 1, GFP_KERNEL))) {
printk("jffs_print_tree(): Out of memory!\n");
return;
}
struct component_name lkey;
struct component_name rkey;
- lkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ lkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
GFP_KERNEL);
if (lkey.name == NULL)
return -ENOMEM;
- rkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ rkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
GFP_KERNEL);
if (rkey.name == NULL) {
kfree(lkey.name);
* allocate/initialize the in-memory inode map control structure
*/
/* allocate the in-memory inode map control structure. */
- imap = (struct inomap *) kmalloc(sizeof(struct inomap), GFP_KERNEL);
+ imap = kmalloc(sizeof(struct inomap), GFP_KERNEL);
if (imap == NULL) {
jfs_err("diMount: kmalloc returned NULL!");
return -ENOMEM;
struct nlm_host * b_host;
struct file_lock * b_lock; /* local file lock */
unsigned short b_reclaim; /* got to reclaim lock */
- u32 b_status; /* grant callback status */
+ __be32 b_status; /* grant callback status */
};
static LIST_HEAD(nlm_blocked);
block->b_host = host;
block->b_lock = fl;
init_waitqueue_head(&block->b_wait);
- block->b_status = NLM_LCK_BLOCKED;
+ block->b_status = nlm_lck_blocked;
list_add(&block->b_list, &nlm_blocked);
}
return block;
* nlmclnt_lock for an explanation.
*/
ret = wait_event_interruptible_timeout(block->b_wait,
- block->b_status != NLM_LCK_BLOCKED,
+ block->b_status != nlm_lck_blocked,
timeout);
if (ret < 0)
return -ERESTARTSYS;
/* Alright, we found a lock. Set the return status
* and wake up the caller
*/
- block->b_status = NLM_LCK_GRANTED;
+ block->b_status = nlm_granted;
wake_up(&block->b_wait);
res = nlm_granted;
}
/* Now, wake up all processes that sleep on a blocked lock */
list_for_each_entry(block, &nlm_blocked, b_list) {
if (block->b_host == host) {
- block->b_status = NLM_LCK_DENIED_GRACE_PERIOD;
+ block->b_status = nlm_lck_denied_grace_period;
wake_up(&block->b_wait);
}
}
static int nlmclnt_test(struct nlm_rqst *, struct file_lock *);
static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
-static int nlm_stat_to_errno(u32 stat);
+static int nlm_stat_to_errno(__be32 stat);
static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
static int nlmclnt_cancel(struct nlm_host *, int , struct file_lock *);
}
break;
} else
- if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) {
+ if (resp->status == nlm_lck_denied_grace_period) {
dprintk("lockd: server in grace period\n");
if (argp->reclaim) {
printk(KERN_WARNING
goto out;
switch (req->a_res.status) {
- case NLM_LCK_GRANTED:
+ case nlm_granted:
fl->fl_type = F_UNLCK;
break;
- case NLM_LCK_DENIED:
+ case nlm_lck_denied:
/*
* Report the conflicting lock back to the application.
*/
if (!req->a_args.block)
break;
/* Did a reclaimer thread notify us of a server reboot? */
- if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD)
+ if (resp->status == nlm_lck_denied_grace_period)
continue;
- if (resp->status != NLM_LCK_BLOCKED)
+ if (resp->status != nlm_lck_blocked)
break;
/* Wait on an NLM blocking lock */
status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT);
*/
if (status < 0)
goto out_unblock;
- if (resp->status != NLM_LCK_BLOCKED)
+ if (resp->status != nlm_lck_blocked)
break;
}
- if (resp->status == NLM_LCK_GRANTED) {
+ if (resp->status == nlm_granted) {
down_read(&host->h_rwsem);
/* Check whether or not the server has rebooted */
if (fl->fl_u.nfs_fl.state != host->h_state) {
out_unblock:
nlmclnt_finish_block(block);
/* Cancel the blocked request if it is still pending */
- if (resp->status == NLM_LCK_BLOCKED)
+ if (resp->status == nlm_lck_blocked)
nlmclnt_cancel(host, req->a_args.block, fl);
out:
nlm_release_call(req);
req->a_args.reclaim = 1;
if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0
- && req->a_res.status == NLM_LCK_GRANTED)
+ && req->a_res.status == nlm_granted)
return 0;
printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "
"(errno %d, status %d)\n", fl->fl_pid,
- status, req->a_res.status);
+ status, ntohl(req->a_res.status));
/*
* FIXME: This is a serious failure. We can
if (status < 0)
goto out;
- if (resp->status == NLM_LCK_GRANTED)
+ if (resp->status == nlm_granted)
goto out;
- if (resp->status != NLM_LCK_DENIED_NOLOCKS)
+ if (resp->status != nlm_lck_denied_nolocks)
printk("lockd: unexpected unlock status: %d\n", resp->status);
/* What to do now? I'm out of my depth... */
status = -ENOLCK;
static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
{
struct nlm_rqst *req = data;
- int status = req->a_res.status;
+ u32 status = ntohl(req->a_res.status);
if (RPC_ASSASSINATED(task))
goto die;
static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
{
struct nlm_rqst *req = data;
+ u32 status = ntohl(req->a_res.status);
if (RPC_ASSASSINATED(task))
goto die;
}
dprintk("lockd: cancel status %u (task %u)\n",
- req->a_res.status, task->tk_pid);
+ status, task->tk_pid);
- switch (req->a_res.status) {
+ switch (status) {
case NLM_LCK_GRANTED:
case NLM_LCK_DENIED_GRACE_PERIOD:
case NLM_LCK_DENIED:
goto retry_cancel;
default:
printk(KERN_NOTICE "lockd: weird return %d for CANCEL call\n",
- req->a_res.status);
+ status);
}
die:
* Convert an NLM status code to a generic kernel errno
*/
static int
-nlm_stat_to_errno(u32 status)
+nlm_stat_to_errno(__be32 status)
{
- switch(status) {
+ switch(ntohl(status)) {
case NLM_LCK_GRANTED:
return 0;
case NLM_LCK_DENIED:
* block.
*/
void
-nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
+nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
{
struct nlm_block *block;
return;
if (block) {
- if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
+ if (status == nlm_lck_denied_grace_period) {
/* Try again in a couple of seconds */
nlmsvc_insert_block(block, 10 * HZ);
} else {
return nlm_lck_denied;
}
- share = (struct nlm_share *) kmalloc(sizeof(*share) + oh->len,
+ share = kmalloc(sizeof(*share) + oh->len,
GFP_KERNEL);
if (share == NULL)
return nlm_lck_denied_nolocks;
{
if (!(p = nlm_decode_cookie(p, &resp->cookie)))
return 0;
- resp->status = ntohl(*p++);
+ resp->status = *p++;
return xdr_argsize_check(rqstp, p);
}
{
if (!(p = nlm_decode_cookie(p, &resp->cookie)))
return -EIO;
- resp->status = ntohl(*p++);
- if (resp->status == NLM_LCK_DENIED) {
+ resp->status = *p++;
+ if (resp->status == nlm_lck_denied) {
struct file_lock *fl = &resp->lock.fl;
u32 excl;
s32 start, len, end;
{
if (!(p = nlm_decode_cookie(p, &resp->cookie)))
return -EIO;
- resp->status = ntohl(*p++);
+ resp->status = *p++;
return 0;
}
{
if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
return 0;
- resp->status = ntohl(*p++);
+ resp->status = *p++;
return xdr_argsize_check(rqstp, p);
}
{
if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
return -EIO;
- resp->status = ntohl(*p++);
- if (resp->status == NLM_LCK_DENIED) {
+ resp->status = *p++;
+ if (resp->status == nlm_lck_denied) {
struct file_lock *fl = &resp->lock.fl;
u32 excl;
s64 start, end, len;
{
if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
return -EIO;
- resp->status = ntohl(*p++);
+ resp->status = *p++;
return 0;
}
{ MNT_NOEXEC, ",noexec" },
{ MNT_NOATIME, ",noatime" },
{ MNT_NODIRATIME, ",nodiratime" },
+ { MNT_RELATIME, ",relatime" },
{ 0, NULL }
};
struct proc_fs_info *fs_infop;
mnt_flags |= MNT_NOATIME;
if (flags & MS_NODIRATIME)
mnt_flags |= MNT_NODIRATIME;
+ if (flags & MS_RELATIME)
+ mnt_flags |= MNT_RELATIME;
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
- MS_NOATIME | MS_NODIRATIME);
+ MS_NOATIME | MS_NODIRATIME | MS_RELATIME);
/* ... and get the mountpoint */
retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
char *optarg;
unsigned long optint;
int version = 0;
+ int ret;
data->flags = 0;
data->int_flags = 0;
data->mounted_uid = 0;
- data->wdog_pid = -1;
+ data->wdog_pid = NULL;
data->ncp_fd = ~0;
data->time_out = 10;
data->retry_count = 20;
data->mounted_vol[0] = 0;
while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
- if (optval < 0)
- return optval;
+ ret = optval;
+ if (ret < 0)
+ goto err;
switch (optval) {
case 'u':
data->uid = optint;
data->flags = optint;
break;
case 'w':
- data->wdog_pid = optint;
+ data->wdog_pid = find_get_pid(optint);
break;
case 'n':
data->ncp_fd = optint;
data->info_fd = optint;
break;
case 'v':
- if (optint < NCP_MOUNT_VERSION_V4) {
- return -ECHRNG;
- }
- if (optint > NCP_MOUNT_VERSION_V5) {
- return -ECHRNG;
- }
+ ret = -ECHRNG;
+ if (optint < NCP_MOUNT_VERSION_V4)
+ goto err;
+ if (optint > NCP_MOUNT_VERSION_V5)
+ goto err;
version = optint;
break;
}
}
return 0;
+err:
+ put_pid(data->wdog_pid);
+ data->wdog_pid = NULL;
+ return ret;
}
static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
#endif
struct ncp_entry_info finfo;
+ data.wdog_pid = NULL;
server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
if (!server)
return -ENOMEM;
data.flags = md->flags;
data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
data.mounted_uid = md->mounted_uid;
- data.wdog_pid = md->wdog_pid;
+ data.wdog_pid = find_get_pid(md->wdog_pid);
data.ncp_fd = md->ncp_fd;
data.time_out = md->time_out;
data.retry_count = md->retry_count;
data.flags = md->flags;
data.int_flags = 0;
data.mounted_uid = md->mounted_uid;
- data.wdog_pid = md->wdog_pid;
+ data.wdog_pid = find_get_pid(md->wdog_pid);
data.ncp_fd = md->ncp_fd;
data.time_out = md->time_out;
data.retry_count = md->retry_count;
*/
fput(ncp_filp);
out:
+ put_pid(data.wdog_pid);
sb->s_fs_info = NULL;
kfree(server);
return error;
if (server->info_filp)
fput(server->info_filp);
fput(server->ncp_filp);
- kill_proc(server->m.wdog_pid, SIGTERM, 1);
+ kill_pid(server->m.wdog_pid, SIGTERM, 1);
+ put_pid(server->m.wdog_pid);
kfree(server->priv.data);
kfree(server->auth.object_name);
struct nfs_server *server = NFS_SERVER(dir->d_inode);
struct unlink_desc *up;
- up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL);
+ up = kmalloc(sizeof(*up), GFP_KERNEL);
if (!up)
return -ENOMEM;
key.ex_dentry = dentry;
exp = svc_export_lookup(&key);
- if (exp != NULL)
- switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
+ if (exp != NULL) {
+ int err;
+
+ err = cache_check(&svc_export_cache, &exp->h, reqp);
+ switch (err) {
case 0: break;
case -EAGAIN:
- exp = ERR_PTR(-EAGAIN);
+ case -ETIMEDOUT:
+ exp = ERR_PTR(err);
break;
default:
exp = NULL;
}
+ }
return exp;
}
exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
+ memset(&new, 0, sizeof(new));
+
/* must make sure there won't be an ex_fsid clash */
if ((nxp->ex_flags & NFSEXP_FSID) &&
(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
new.h.expiry_time = NEVER;
new.h.flags = 0;
+ new.ex_path = kstrdup(nxp->ex_path, GFP_KERNEL);
+ if (!new.ex_path)
+ goto finish;
new.ex_client = clp;
new.ex_mnt = nd.mnt;
new.ex_dentry = nd.dentry;
/* failed to create at least one index */
exp_do_unexport(exp);
cache_flush();
- err = -ENOMEM;
- }
-
+ } else
+ err = 0;
finish:
+ if (new.ex_path)
+ kfree(new.ex_path);
if (exp)
exp_put(exp);
if (fsid_key && !IS_ERR(fsid_key))
path, nd.dentry, clp->name,
inode->i_sb->s_id, inode->i_ino);
exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
+ if (IS_ERR(exp)) {
+ err = PTR_ERR(exp);
+ goto out;
+ }
if (!exp) {
dprintk("nfsd: exp_rootfh export not found.\n");
goto out;
mk_fsid_v1(fsidv, 0);
exp = exp_find(clp, 1, fsidv, creq);
- if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
- return nfserr_dropit;
+ if (IS_ERR(exp))
+ return nfserrno(PTR_ERR(exp));
if (exp == NULL)
return nfserr_perm;
- else if (IS_ERR(exp))
- return nfserrno(PTR_ERR(exp));
rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
exp_put(exp);
return rv;
/*
* Note: we hold the dentry use count while the file is open.
*/
-static u32
+static __be32
nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
{
__be32 nfserr;
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Note: some routines in this file are just trivial wrappers
- * (e.g. nfsd4_lookup()) defined solely for the sake of consistent
- * naming. Since all such routines have been declared "inline",
- * there shouldn't be any associated overhead. At some point in
- * the future, I might inline these "by hand" to clean up a
- * little.
*/
#include <linux/param.h>
}
-static inline __be32
-nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
+static __be32
+nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_open *open)
{
__be32 status;
dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
status = nfsd4_process_open1(open);
if (status == nfserr_replay_me) {
struct nfs4_replay *rp = &open->op_stateowner->so_replay;
- fh_put(current_fh);
- current_fh->fh_handle.fh_size = rp->rp_openfh_len;
- memcpy(¤t_fh->fh_handle.fh_base, rp->rp_openfh,
+ fh_put(&cstate->current_fh);
+ cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
+ memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
rp->rp_openfh_len);
- status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+ status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
if (status)
dprintk("nfsd4_open: replay failed"
" restoring previous filehandle\n");
* (3) set open->op_truncate if the file is to be
* truncated after opening, (4) do permission checking.
*/
- status = do_open_lookup(rqstp, current_fh, open);
+ status = do_open_lookup(rqstp, &cstate->current_fh,
+ open);
if (status)
goto out;
break;
* open->op_truncate if the file is to be truncated
* after opening, (3) do permission checking.
*/
- status = do_open_fhandle(rqstp, current_fh, open);
+ status = do_open_fhandle(rqstp, &cstate->current_fh,
+ open);
if (status)
goto out;
break;
* successful, it (1) truncates the file if open->op_truncate was
* set, (2) sets open->op_stateid, (3) sets open->op_delegation.
*/
- status = nfsd4_process_open2(rqstp, current_fh, open);
+ status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
out:
if (open->op_stateowner) {
nfs4_get_stateowner(open->op_stateowner);
- *replay_owner = open->op_stateowner;
+ cstate->replay_owner = open->op_stateowner;
}
nfs4_unlock_state();
return status;
/*
* filehandle-manipulating ops.
*/
-static inline __be32
-nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh)
+static __be32
+nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct svc_fh **getfh)
{
- if (!current_fh->fh_dentry)
+ if (!cstate->current_fh.fh_dentry)
return nfserr_nofilehandle;
- *getfh = current_fh;
+ *getfh = &cstate->current_fh;
return nfs_ok;
}
-static inline __be32
-nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh)
+static __be32
+nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_putfh *putfh)
{
- fh_put(current_fh);
- current_fh->fh_handle.fh_size = putfh->pf_fhlen;
- memcpy(¤t_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen);
- return fh_verify(rqstp, current_fh, 0, MAY_NOP);
+ fh_put(&cstate->current_fh);
+ cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
+ memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
+ putfh->pf_fhlen);
+ return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
}
-static inline __be32
-nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
+static __be32
+nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ void *arg)
{
__be32 status;
- fh_put(current_fh);
- status = exp_pseudoroot(rqstp->rq_client, current_fh,
+ fh_put(&cstate->current_fh);
+ status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
&rqstp->rq_chandle);
return status;
}
-static inline __be32
-nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
+static __be32
+nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ void *arg)
{
- if (!save_fh->fh_dentry)
+ if (!cstate->save_fh.fh_dentry)
return nfserr_restorefh;
- fh_dup2(current_fh, save_fh);
+ fh_dup2(&cstate->current_fh, &cstate->save_fh);
return nfs_ok;
}
-static inline __be32
-nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
+static __be32
+nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ void *arg)
{
- if (!current_fh->fh_dentry)
+ if (!cstate->current_fh.fh_dentry)
return nfserr_nofilehandle;
- fh_dup2(save_fh, current_fh);
+ fh_dup2(&cstate->save_fh, &cstate->current_fh);
return nfs_ok;
}
/*
* misc nfsv4 ops
*/
-static inline __be32
-nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access)
+static __be32
+nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_access *access)
{
if (access->ac_req_access & ~NFS3_ACCESS_FULL)
return nfserr_inval;
access->ac_resp_access = access->ac_req_access;
- return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported);
+ return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
+ &access->ac_supported);
}
-static inline __be32
-nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit)
+static __be32
+nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_commit *commit)
{
__be32 status;
*p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec;
- status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count);
+ status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
+ commit->co_count);
if (status == nfserr_symlink)
status = nfserr_inval;
return status;
}
static __be32
-nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create)
+nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_create *create)
{
struct svc_fh resfh;
__be32 status;
fh_init(&resfh, NFS4_FHSIZE);
- status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE);
+ status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, MAY_CREATE);
if (status == nfserr_symlink)
status = nfserr_notdir;
if (status)
*/
create->cr_linkname[create->cr_linklen] = 0;
- status = nfsd_symlink(rqstp, current_fh, create->cr_name,
- create->cr_namelen, create->cr_linkname,
- create->cr_linklen, &resfh, &create->cr_iattr);
+ status = nfsd_symlink(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ create->cr_linkname, create->cr_linklen,
+ &resfh, &create->cr_iattr);
break;
case NF4BLK:
if (MAJOR(rdev) != create->cr_specdata1 ||
MINOR(rdev) != create->cr_specdata2)
return nfserr_inval;
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFBLK, rdev, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr, S_IFBLK, rdev, &resfh);
break;
case NF4CHR:
if (MAJOR(rdev) != create->cr_specdata1 ||
MINOR(rdev) != create->cr_specdata2)
return nfserr_inval;
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFCHR, rdev, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr,S_IFCHR, rdev, &resfh);
break;
case NF4SOCK:
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFSOCK, 0, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr, S_IFSOCK, 0, &resfh);
break;
case NF4FIFO:
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFIFO, 0, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr, S_IFIFO, 0, &resfh);
break;
case NF4DIR:
create->cr_iattr.ia_valid &= ~ATTR_SIZE;
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFDIR, 0, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr, S_IFDIR, 0, &resfh);
break;
default:
}
if (!status) {
- fh_unlock(current_fh);
- set_change_info(&create->cr_cinfo, current_fh);
- fh_dup2(current_fh, &resfh);
+ fh_unlock(&cstate->current_fh);
+ set_change_info(&create->cr_cinfo, &cstate->current_fh);
+ fh_dup2(&cstate->current_fh, &resfh);
}
fh_put(&resfh);
return status;
}
-static inline __be32
-nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr)
+static __be32
+nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_getattr *getattr)
{
__be32 status;
- status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+ status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
if (status)
return status;
getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
- getattr->ga_fhp = current_fh;
+ getattr->ga_fhp = &cstate->current_fh;
return nfs_ok;
}
-static inline __be32
-nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct svc_fh *save_fh, struct nfsd4_link *link)
+static __be32
+nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_link *link)
{
__be32 status = nfserr_nofilehandle;
- if (!save_fh->fh_dentry)
+ if (!cstate->save_fh.fh_dentry)
return status;
- status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh);
+ status = nfsd_link(rqstp, &cstate->current_fh,
+ link->li_name, link->li_namelen, &cstate->save_fh);
if (!status)
- set_change_info(&link->li_cinfo, current_fh);
+ set_change_info(&link->li_cinfo, &cstate->current_fh);
return status;
}
static __be32
-nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
+nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ void *arg)
{
struct svc_fh tmp_fh;
__be32 ret;
if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
&rqstp->rq_chandle)) != 0)
return ret;
- if (tmp_fh.fh_dentry == current_fh->fh_dentry) {
+ if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
fh_put(&tmp_fh);
return nfserr_noent;
}
fh_put(&tmp_fh);
- return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh);
+ return nfsd_lookup(rqstp, &cstate->current_fh,
+ "..", 2, &cstate->current_fh);
}
-static inline __be32
-nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup)
+static __be32
+nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_lookup *lookup)
{
- return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh);
+ return nfsd_lookup(rqstp, &cstate->current_fh,
+ lookup->lo_name, lookup->lo_len,
+ &cstate->current_fh);
}
-static inline __be32
-nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
+static __be32
+nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_read *read)
{
__be32 status;
nfs4_lock_state();
/* check stateid */
- if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
+ if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+ &read->rd_stateid,
CHECK_FH | RD_STATE, &read->rd_filp))) {
dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
goto out;
out:
nfs4_unlock_state();
read->rd_rqstp = rqstp;
- read->rd_fhp = current_fh;
+ read->rd_fhp = &cstate->current_fh;
return status;
}
-static inline __be32
-nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir)
+static __be32
+nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_readdir *readdir)
{
u64 cookie = readdir->rd_cookie;
static const nfs4_verifier zeroverf;
return nfserr_bad_cookie;
readdir->rd_rqstp = rqstp;
- readdir->rd_fhp = current_fh;
+ readdir->rd_fhp = &cstate->current_fh;
return nfs_ok;
}
-static inline __be32
-nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink)
+static __be32
+nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_readlink *readlink)
{
readlink->rl_rqstp = rqstp;
- readlink->rl_fhp = current_fh;
+ readlink->rl_fhp = &cstate->current_fh;
return nfs_ok;
}
-static inline __be32
-nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove)
+static __be32
+nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_remove *remove)
{
__be32 status;
if (nfs4_in_grace())
return nfserr_grace;
- status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
+ status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
+ remove->rm_name, remove->rm_namelen);
if (status == nfserr_symlink)
return nfserr_notdir;
if (!status) {
- fh_unlock(current_fh);
- set_change_info(&remove->rm_cinfo, current_fh);
+ fh_unlock(&cstate->current_fh);
+ set_change_info(&remove->rm_cinfo, &cstate->current_fh);
}
return status;
}
-static inline __be32
-nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct svc_fh *save_fh, struct nfsd4_rename *rename)
+static __be32
+nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_rename *rename)
{
__be32 status = nfserr_nofilehandle;
- if (!save_fh->fh_dentry)
+ if (!cstate->save_fh.fh_dentry)
return status;
- if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
+ if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
& NFSEXP_NOSUBTREECHECK))
return nfserr_grace;
- status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
- rename->rn_snamelen, current_fh,
+ status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
+ rename->rn_snamelen, &cstate->current_fh,
rename->rn_tname, rename->rn_tnamelen);
/* the underlying filesystem returns different error's than required
if (status == nfserr_isdir)
status = nfserr_exist;
else if ((status == nfserr_notdir) &&
- (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) &&
- S_ISDIR(current_fh->fh_dentry->d_inode->i_mode)))
+ (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
+ S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
status = nfserr_exist;
else if (status == nfserr_symlink)
status = nfserr_notdir;
if (!status) {
- set_change_info(&rename->rn_sinfo, current_fh);
- set_change_info(&rename->rn_tinfo, save_fh);
+ set_change_info(&rename->rn_sinfo, &cstate->current_fh);
+ set_change_info(&rename->rn_tinfo, &cstate->save_fh);
}
return status;
}
-static inline __be32
-nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
+static __be32
+nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_setattr *setattr)
{
__be32 status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
nfs4_lock_state();
- status = nfs4_preprocess_stateid_op(current_fh,
+ status = nfs4_preprocess_stateid_op(&cstate->current_fh,
&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
nfs4_unlock_state();
if (status) {
}
status = nfs_ok;
if (setattr->sa_acl != NULL)
- status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
+ status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
+ setattr->sa_acl);
if (status)
return status;
- status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
+ status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
0, (time_t)0);
return status;
}
-static inline __be32
-nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
+static __be32
+nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_write *write)
{
stateid_t *stateid = &write->wr_stateid;
struct file *filp = NULL;
return nfserr_inval;
nfs4_lock_state();
- status = nfs4_preprocess_stateid_op(current_fh, stateid,
+ status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,
CHECK_FH | WR_STATE, &filp);
if (filp)
get_file(filp);
*p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec;
- status = nfsd_write(rqstp, current_fh, filp, write->wr_offset,
- rqstp->rq_vec, write->wr_vlen, write->wr_buflen,
- &write->wr_how_written);
+ status = nfsd_write(rqstp, &cstate->current_fh, filp,
+ write->wr_offset, rqstp->rq_vec, write->wr_vlen,
+ write->wr_buflen, &write->wr_how_written);
if (filp)
fput(filp);
* to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
*/
static __be32
-nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify)
+_nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_verify *verify)
{
__be32 *buf, *p;
int count;
__be32 status;
- status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+ status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
if (status)
return status;
if (!buf)
return nfserr_resource;
- status = nfsd4_encode_fattr(current_fh, current_fh->fh_export,
- current_fh->fh_dentry, buf,
+ status = nfsd4_encode_fattr(&cstate->current_fh,
+ cstate->current_fh.fh_export,
+ cstate->current_fh.fh_dentry, buf,
&count, verify->ve_bmval,
rqstp);
return status;
}
+static __be32
+nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_verify *verify)
+{
+ __be32 status;
+
+ status = _nfsd4_verify(rqstp, cstate, verify);
+ return status == nfserr_not_same ? nfs_ok : status;
+}
+
+static __be32
+nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_verify *verify)
+{
+ __be32 status;
+
+ status = _nfsd4_verify(rqstp, cstate, verify);
+ return status == nfserr_same ? nfs_ok : status;
+}
+
/*
* NULL call.
*/
nfsdstats.nfs4_opcount[opnum]++;
}
+static void cstate_free(struct nfsd4_compound_state *cstate)
+{
+ if (cstate == NULL)
+ return;
+ fh_put(&cstate->current_fh);
+ fh_put(&cstate->save_fh);
+ BUG_ON(cstate->replay_owner);
+ kfree(cstate);
+}
+
+static struct nfsd4_compound_state *cstate_alloc(void)
+{
+ struct nfsd4_compound_state *cstate;
+
+ cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL);
+ if (cstate == NULL)
+ return NULL;
+ fh_init(&cstate->current_fh, NFS4_FHSIZE);
+ fh_init(&cstate->save_fh, NFS4_FHSIZE);
+ cstate->replay_owner = NULL;
+ return cstate;
+}
+
+typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
+ void *);
+
+struct nfsd4_operation {
+ nfsd4op_func op_func;
+ u32 op_flags;
+/* Most ops require a valid current filehandle; a few don't: */
+#define ALLOWED_WITHOUT_FH 1
+/* GETATTR and ops not listed as returning NFS4ERR_MOVED: */
+#define ALLOWED_ON_ABSENT_FS 2
+};
+
+static struct nfsd4_operation nfsd4_ops[];
/*
* COMPOUND call.
struct nfsd4_compoundres *resp)
{
struct nfsd4_op *op;
- struct svc_fh *current_fh = NULL;
- struct svc_fh *save_fh = NULL;
- struct nfs4_stateowner *replay_owner = NULL;
- int slack_space; /* in words, not bytes! */
+ struct nfsd4_operation *opdesc;
+ struct nfsd4_compound_state *cstate = NULL;
+ int slack_bytes;
__be32 status;
status = nfserr_resource;
- current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL);
- if (current_fh == NULL)
- goto out;
- fh_init(current_fh, NFS4_FHSIZE);
- save_fh = kmalloc(sizeof(*save_fh), GFP_KERNEL);
- if (save_fh == NULL)
+ cstate = cstate_alloc();
+ if (cstate == NULL)
goto out;
- fh_init(save_fh, NFS4_FHSIZE);
resp->xbuf = &rqstp->rq_res;
resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
* failed response to the next operation. If we don't
* have enough room, fail with ERR_RESOURCE.
*/
-/* FIXME - is slack_space *really* words, or bytes??? - neilb */
- slack_space = (char *)resp->end - (char *)resp->p;
- if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) {
- BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE);
+ slack_bytes = (char *)resp->end - (char *)resp->p;
+ if (slack_bytes < COMPOUND_SLACK_SPACE
+ + COMPOUND_ERR_SLACK_SPACE) {
+ BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
op->status = nfserr_resource;
goto encode_op;
}
- /* All operations except RENEW, SETCLIENTID, RESTOREFH
- * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
- * require a valid current filehandle
- */
- if (!current_fh->fh_dentry) {
- if (!((op->opnum == OP_PUTFH) ||
- (op->opnum == OP_PUTROOTFH) ||
- (op->opnum == OP_SETCLIENTID) ||
- (op->opnum == OP_SETCLIENTID_CONFIRM) ||
- (op->opnum == OP_RENEW) ||
- (op->opnum == OP_RESTOREFH) ||
- (op->opnum == OP_RELEASE_LOCKOWNER))) {
+ opdesc = &nfsd4_ops[op->opnum];
+
+ if (!cstate->current_fh.fh_dentry) {
+ if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
op->status = nfserr_nofilehandle;
goto encode_op;
}
- }
- /* Check must be done at start of each operation, except
- * for GETATTR and ops not listed as returning NFS4ERR_MOVED
- */
- else if (current_fh->fh_export->ex_fslocs.migrated &&
- !((op->opnum == OP_GETATTR) ||
- (op->opnum == OP_PUTROOTFH) ||
- (op->opnum == OP_PUTPUBFH) ||
- (op->opnum == OP_RENEW) ||
- (op->opnum == OP_SETCLIENTID) ||
- (op->opnum == OP_RELEASE_LOCKOWNER))) {
+ } else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
+ !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
op->status = nfserr_moved;
goto encode_op;
}
- switch (op->opnum) {
- case OP_ACCESS:
- op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
- break;
- case OP_CLOSE:
- op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner);
- break;
- case OP_COMMIT:
- op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
- break;
- case OP_CREATE:
- op->status = nfsd4_create(rqstp, current_fh, &op->u.create);
- break;
- case OP_DELEGRETURN:
- op->status = nfsd4_delegreturn(rqstp, current_fh, &op->u.delegreturn);
- break;
- case OP_GETATTR:
- op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr);
- break;
- case OP_GETFH:
- op->status = nfsd4_getfh(current_fh, &op->u.getfh);
- break;
- case OP_LINK:
- op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
- break;
- case OP_LOCK:
- op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner);
- break;
- case OP_LOCKT:
- op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
- break;
- case OP_LOCKU:
- op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner);
- break;
- case OP_LOOKUP:
- op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
- break;
- case OP_LOOKUPP:
- op->status = nfsd4_lookupp(rqstp, current_fh);
- break;
- case OP_NVERIFY:
- op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify);
- if (op->status == nfserr_not_same)
- op->status = nfs_ok;
- break;
- case OP_OPEN:
- op->status = nfsd4_open(rqstp, current_fh, &op->u.open, &replay_owner);
- break;
- case OP_OPEN_CONFIRM:
- op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner);
- break;
- case OP_OPEN_DOWNGRADE:
- op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner);
- break;
- case OP_PUTFH:
- op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
- break;
- case OP_PUTROOTFH:
- op->status = nfsd4_putrootfh(rqstp, current_fh);
- break;
- case OP_READ:
- op->status = nfsd4_read(rqstp, current_fh, &op->u.read);
- break;
- case OP_READDIR:
- op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir);
- break;
- case OP_READLINK:
- op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink);
- break;
- case OP_REMOVE:
- op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove);
- break;
- case OP_RENAME:
- op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename);
- break;
- case OP_RENEW:
- op->status = nfsd4_renew(&op->u.renew);
- break;
- case OP_RESTOREFH:
- op->status = nfsd4_restorefh(current_fh, save_fh);
- break;
- case OP_SAVEFH:
- op->status = nfsd4_savefh(current_fh, save_fh);
- break;
- case OP_SETATTR:
- op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr);
- break;
- case OP_SETCLIENTID:
- op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
- break;
- case OP_SETCLIENTID_CONFIRM:
- op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
- break;
- case OP_VERIFY:
- op->status = nfsd4_verify(rqstp, current_fh, &op->u.verify);
- if (op->status == nfserr_same)
- op->status = nfs_ok;
- break;
- case OP_WRITE:
- op->status = nfsd4_write(rqstp, current_fh, &op->u.write);
- break;
- case OP_RELEASE_LOCKOWNER:
- op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
- break;
- default:
+
+ if (opdesc->op_func)
+ op->status = opdesc->op_func(rqstp, cstate, &op->u);
+ else
BUG_ON(op->status == nfs_ok);
- break;
- }
encode_op:
if (op->status == nfserr_replay_me) {
- op->replay = &replay_owner->so_replay;
+ op->replay = &cstate->replay_owner->so_replay;
nfsd4_encode_replay(resp, op);
status = op->status = op->replay->rp_status;
} else {
nfsd4_encode_operation(resp, op);
status = op->status;
}
- if (replay_owner && (replay_owner != (void *)(-1))) {
- nfs4_put_stateowner(replay_owner);
- replay_owner = NULL;
+ if (cstate->replay_owner) {
+ nfs4_put_stateowner(cstate->replay_owner);
+ cstate->replay_owner = NULL;
}
/* XXX Ugh, we need to get rid of this kind of special case: */
if (op->opnum == OP_READ && op->u.read.rd_filp)
out:
nfsd4_release_compoundargs(args);
- if (current_fh)
- fh_put(current_fh);
- kfree(current_fh);
- if (save_fh)
- fh_put(save_fh);
- kfree(save_fh);
+ cstate_free(cstate);
return status;
}
+static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
+ [OP_ACCESS] = {
+ .op_func = (nfsd4op_func)nfsd4_access,
+ },
+ [OP_CLOSE] = {
+ .op_func = (nfsd4op_func)nfsd4_close,
+ },
+ [OP_COMMIT] = {
+ .op_func = (nfsd4op_func)nfsd4_commit,
+ },
+ [OP_CREATE] = {
+ .op_func = (nfsd4op_func)nfsd4_create,
+ },
+ [OP_DELEGRETURN] = {
+ .op_func = (nfsd4op_func)nfsd4_delegreturn,
+ },
+ [OP_GETATTR] = {
+ .op_func = (nfsd4op_func)nfsd4_getattr,
+ .op_flags = ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_GETFH] = {
+ .op_func = (nfsd4op_func)nfsd4_getfh,
+ },
+ [OP_LINK] = {
+ .op_func = (nfsd4op_func)nfsd4_link,
+ },
+ [OP_LOCK] = {
+ .op_func = (nfsd4op_func)nfsd4_lock,
+ },
+ [OP_LOCKT] = {
+ .op_func = (nfsd4op_func)nfsd4_lockt,
+ },
+ [OP_LOCKU] = {
+ .op_func = (nfsd4op_func)nfsd4_locku,
+ },
+ [OP_LOOKUP] = {
+ .op_func = (nfsd4op_func)nfsd4_lookup,
+ },
+ [OP_LOOKUPP] = {
+ .op_func = (nfsd4op_func)nfsd4_lookupp,
+ },
+ [OP_NVERIFY] = {
+ .op_func = (nfsd4op_func)nfsd4_nverify,
+ },
+ [OP_OPEN] = {
+ .op_func = (nfsd4op_func)nfsd4_open,
+ },
+ [OP_OPEN_CONFIRM] = {
+ .op_func = (nfsd4op_func)nfsd4_open_confirm,
+ },
+ [OP_OPEN_DOWNGRADE] = {
+ .op_func = (nfsd4op_func)nfsd4_open_downgrade,
+ },
+ [OP_PUTFH] = {
+ .op_func = (nfsd4op_func)nfsd4_putfh,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_PUTPUBFH] = {
+ /* unsupported; just for future reference: */
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_PUTROOTFH] = {
+ .op_func = (nfsd4op_func)nfsd4_putrootfh,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_READ] = {
+ .op_func = (nfsd4op_func)nfsd4_read,
+ },
+ [OP_READDIR] = {
+ .op_func = (nfsd4op_func)nfsd4_readdir,
+ },
+ [OP_READLINK] = {
+ .op_func = (nfsd4op_func)nfsd4_readlink,
+ },
+ [OP_REMOVE] = {
+ .op_func = (nfsd4op_func)nfsd4_remove,
+ },
+ [OP_RENAME] = {
+ .op_func = (nfsd4op_func)nfsd4_rename,
+ },
+ [OP_RENEW] = {
+ .op_func = (nfsd4op_func)nfsd4_renew,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_RESTOREFH] = {
+ .op_func = (nfsd4op_func)nfsd4_restorefh,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_SAVEFH] = {
+ .op_func = (nfsd4op_func)nfsd4_savefh,
+ },
+ [OP_SETATTR] = {
+ .op_func = (nfsd4op_func)nfsd4_setattr,
+ },
+ [OP_SETCLIENTID] = {
+ .op_func = (nfsd4op_func)nfsd4_setclientid,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_SETCLIENTID_CONFIRM] = {
+ .op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_VERIFY] = {
+ .op_func = (nfsd4op_func)nfsd4_verify,
+ },
+ [OP_WRITE] = {
+ .op_func = (nfsd4op_func)nfsd4_write,
+ },
+ [OP_RELEASE_LOCKOWNER] = {
+ .op_func = (nfsd4op_func)nfsd4_release_lockowner,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+};
+
#define nfs4svc_decode_voidargs NULL
#define nfs4svc_release_void NULL
#define nfsd4_voidres nfsd4_voidargs
*
*/
__be32
-nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_setclientid *setclid)
{
__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
struct xdr_netobj clname = {
* NOTE: callback information will be processed here in a future patch
*/
__be32
-nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
+nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *cstate,
+ struct nfsd4_setclientid_confirm *setclientid_confirm)
{
__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
struct nfs4_client *conf, *unconf;
static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
__be32
-nfsd4_renew(clientid_t *clid)
+nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ clientid_t *clid)
{
struct nfs4_client *clp;
__be32 status;
}
__be32
-nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner)
+nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_open_confirm *oc)
{
__be32 status;
struct nfs4_stateowner *sop;
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
- (int)current_fh->fh_dentry->d_name.len,
- current_fh->fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_dentry->d_name.len,
+ cstate->current_fh.fh_dentry->d_name.name);
- status = fh_verify(rqstp, current_fh, S_IFREG, 0);
+ status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
if (status)
return status;
nfs4_lock_state();
- if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
- &oc->oc_req_stateid,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ oc->oc_seqid, &oc->oc_req_stateid,
CHECK_FH | CONFIRM | OPEN_STATE,
&oc->oc_stateowner, &stp, NULL)))
goto out;
out:
if (oc->oc_stateowner) {
nfs4_get_stateowner(oc->oc_stateowner);
- *replay_owner = oc->oc_stateowner;
+ cstate->replay_owner = oc->oc_stateowner;
}
nfs4_unlock_state();
return status;
}
__be32
-nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner)
+nfsd4_open_downgrade(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *cstate,
+ struct nfsd4_open_downgrade *od)
{
__be32 status;
struct nfs4_stateid *stp;
unsigned int share_access;
dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
- (int)current_fh->fh_dentry->d_name.len,
- current_fh->fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_dentry->d_name.len,
+ cstate->current_fh.fh_dentry->d_name.name);
if (!access_valid(od->od_share_access)
|| !deny_valid(od->od_share_deny))
return nfserr_inval;
nfs4_lock_state();
- if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ od->od_seqid,
&od->od_stateid,
CHECK_FH | OPEN_STATE,
&od->od_stateowner, &stp, NULL)))
out:
if (od->od_stateowner) {
nfs4_get_stateowner(od->od_stateowner);
- *replay_owner = od->od_stateowner;
+ cstate->replay_owner = od->od_stateowner;
}
nfs4_unlock_state();
return status;
* nfs4_unlock_state() called after encode
*/
__be32
-nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
+nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_close *close)
{
__be32 status;
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_close on file %.*s\n",
- (int)current_fh->fh_dentry->d_name.len,
- current_fh->fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_dentry->d_name.len,
+ cstate->current_fh.fh_dentry->d_name.name);
nfs4_lock_state();
/* check close_lru for replay */
- if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ close->cl_seqid,
&close->cl_stateid,
CHECK_FH | OPEN_STATE | CLOSE_STATE,
&close->cl_stateowner, &stp, NULL)))
out:
if (close->cl_stateowner) {
nfs4_get_stateowner(close->cl_stateowner);
- *replay_owner = close->cl_stateowner;
+ cstate->replay_owner = close->cl_stateowner;
}
nfs4_unlock_state();
return status;
}
__be32
-nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr)
+nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_delegreturn *dr)
{
__be32 status;
- if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
+ if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
goto out;
nfs4_lock_state();
- status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL);
+ status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+ &dr->dr_stateid, DELEG_RET, NULL);
nfs4_unlock_state();
out:
return status;
* LOCK operation
*/
__be32
-nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
+nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_lock *lock)
{
struct nfs4_stateowner *open_sop = NULL;
struct nfs4_stateowner *lock_sop = NULL;
if (check_lock_length(lock->lk_offset, lock->lk_length))
return nfserr_inval;
- if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
+ if ((status = fh_verify(rqstp, &cstate->current_fh,
+ S_IFREG, MAY_LOCK))) {
dprintk("NFSD: nfsd4_lock: permission denied!\n");
return status;
}
goto out;
/* validate and update open stateid and open seqid */
- status = nfs4_preprocess_seqid_op(current_fh,
+ status = nfs4_preprocess_seqid_op(&cstate->current_fh,
lock->lk_new_open_seqid,
&lock->lk_new_open_stateid,
CHECK_FH | OPEN_STATE,
goto out;
} else {
/* lock (lock owner + lock stateid) already exists */
- status = nfs4_preprocess_seqid_op(current_fh,
+ status = nfs4_preprocess_seqid_op(&cstate->current_fh,
lock->lk_old_lock_seqid,
&lock->lk_old_lock_stateid,
CHECK_FH | LOCK_STATE,
conflock.fl_ops = NULL;
conflock.fl_lmops = NULL;
err = posix_lock_file_conf(filp, &file_lock, &conflock);
- dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status);
switch (-err) {
case 0: /* success! */
update_stateid(&lock_stp->st_stateid);
release_stateowner(lock_sop);
if (lock->lk_replay_owner) {
nfs4_get_stateowner(lock->lk_replay_owner);
- *replay_owner = lock->lk_replay_owner;
+ cstate->replay_owner = lock->lk_replay_owner;
}
nfs4_unlock_state();
return status;
* LOCKT operation
*/
__be32
-nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
+nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_lockt *lockt)
{
struct inode *inode;
struct file file;
if (STALE_CLIENTID(&lockt->lt_clientid))
goto out;
- if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
+ if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) {
dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
if (status == nfserr_symlink)
status = nfserr_inval;
goto out;
}
- inode = current_fh->fh_dentry->d_inode;
+ inode = cstate->current_fh.fh_dentry->d_inode;
locks_init_lock(&file_lock);
switch (lockt->lt_type) {
case NFS4_READ_LT:
* only the dentry:inode set.
*/
memset(&file, 0, sizeof (struct file));
- file.f_path.dentry = current_fh->fh_dentry;
+ file.f_path.dentry = cstate->current_fh.fh_dentry;
status = nfs_ok;
if (posix_test_lock(&file, &file_lock, &conflock)) {
}
__be32
-nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
+nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_locku *locku)
{
struct nfs4_stateid *stp;
struct file *filp = NULL;
nfs4_lock_state();
- if ((status = nfs4_preprocess_seqid_op(current_fh,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
locku->lu_seqid,
&locku->lu_stateid,
CHECK_FH | LOCK_STATE,
out:
if (locku->lu_stateowner) {
nfs4_get_stateowner(locku->lu_stateowner);
- *replay_owner = locku->lu_stateowner;
+ cstate->replay_owner = locku->lu_stateowner;
}
nfs4_unlock_state();
return status;
}
__be32
-nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
+nfsd4_release_lockowner(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *cstate,
+ struct nfsd4_release_lockowner *rlockowner)
{
clientid_t *clid = &rlockowner->rl_clientid;
struct nfs4_stateowner *sop;
exp_get(exp);
if (d_mountpoint(dentry)) {
- if (nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp)) {
- /*
- * -EAGAIN is the only error returned from
- * nfsd_cross_mnt() and it indicates that an
- * up-call has been initiated to fill in the export
- * options on exp. When the answer comes back,
- * this call will be retried.
- */
- nfserr = nfserr_dropit;
+ int err;
+
+ err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
+ if (err) {
+ nfserr = nfserrno(err);
goto out_put;
}
exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
}
- error = nfserr_dropit;
- if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
+ if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
+ || PTR_ERR(exp) == -ETIMEDOUT)) {
+ error = nfserrno(PTR_ERR(exp));
goto out;
+ }
error = nfserr_stale;
if (!exp || IS_ERR(exp))
/*
* Called from nfsd_lookup and encode_dirent. Check if we have crossed
* a mount point.
- * Returns -EAGAIN leaving *dpp and *expp unchanged,
+ * Returns -EAGAIN or -ETIMEDOUT leaving *dpp and *expp unchanged,
* or nfs_ok having possibly changed *dpp and *expp
*/
int
goto bail;
}
- *tc = kcalloc(1, sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
+ *tc = kzalloc(sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
if (!(*tc)) {
status = -ENOMEM;
mlog_errno(status);
struct o2hb_region *reg = NULL;
struct config_item *ret = NULL;
- reg = kcalloc(1, sizeof(struct o2hb_region), GFP_KERNEL);
+ reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL);
if (reg == NULL)
goto out; /* ENOMEM */
struct o2hb_heartbeat_group *hs = NULL;
struct config_group *ret = NULL;
- hs = kcalloc(1, sizeof(struct o2hb_heartbeat_group), GFP_KERNEL);
+ hs = kzalloc(sizeof(struct o2hb_heartbeat_group), GFP_KERNEL);
if (hs == NULL)
goto out;
if (strlen(name) > O2NM_MAX_NAME_LEN)
goto out; /* ENAMETOOLONG */
- node = kcalloc(1, sizeof(struct o2nm_node), GFP_KERNEL);
+ node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL);
if (node == NULL)
goto out; /* ENOMEM */
if (o2nm_single_cluster)
goto out; /* ENOSPC */
- cluster = kcalloc(1, sizeof(struct o2nm_cluster), GFP_KERNEL);
- ns = kcalloc(1, sizeof(struct o2nm_node_group), GFP_KERNEL);
+ cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL);
+ ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL);
defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL);
o2hb_group = o2hb_alloc_hb_set();
if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL)
struct page *page = NULL;
page = alloc_page(GFP_NOFS);
- sc = kcalloc(1, sizeof(*sc), GFP_NOFS);
+ sc = kzalloc(sizeof(*sc), GFP_NOFS);
if (sc == NULL || page == NULL)
goto out;
goto out;
}
- nmh = kcalloc(1, sizeof(struct o2net_msg_handler), GFP_NOFS);
+ nmh = kzalloc(sizeof(struct o2net_msg_handler), GFP_NOFS);
if (nmh == NULL) {
ret = -ENOMEM;
goto out;
o2quo_init();
- o2net_hand = kcalloc(1, sizeof(struct o2net_handshake), GFP_KERNEL);
- o2net_keep_req = kcalloc(1, sizeof(struct o2net_msg), GFP_KERNEL);
- o2net_keep_resp = kcalloc(1, sizeof(struct o2net_msg), GFP_KERNEL);
+ o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL);
+ o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
+ o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
if (!o2net_hand || !o2net_keep_req || !o2net_keep_resp) {
kfree(o2net_hand);
kfree(o2net_keep_req);
mlog_entry("%p", dlm);
- ctxt = kcalloc(1, sizeof(*ctxt), GFP_KERNEL);
+ ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt) {
status = -ENOMEM;
mlog_errno(status);
int i;
struct dlm_ctxt *dlm = NULL;
- dlm = kcalloc(1, sizeof(*dlm), GFP_KERNEL);
+ dlm = kzalloc(sizeof(*dlm), GFP_KERNEL);
if (!dlm) {
mlog_errno(-ENOMEM);
goto leave;
struct dlm_lock *lock;
int kernel_allocated = 0;
- lock = kcalloc(1, sizeof(*lock), GFP_NOFS);
+ lock = kzalloc(sizeof(*lock), GFP_NOFS);
if (!lock)
return NULL;
if (!lksb) {
/* zero memory only if kernel-allocated */
- lksb = kcalloc(1, sizeof(*lksb), GFP_NOFS);
+ lksb = kzalloc(sizeof(*lksb), GFP_NOFS);
if (!lksb) {
kfree(lock);
return NULL;
int ignore_higher, u8 request_from, u32 flags)
{
struct dlm_work_item *item;
- item = kcalloc(1, sizeof(*item), GFP_NOFS);
+ item = kzalloc(sizeof(*item), GFP_NOFS);
if (!item)
return -ENOMEM;
}
BUG_ON(num == dead_node);
- ndata = kcalloc(1, sizeof(*ndata), GFP_NOFS);
+ ndata = kzalloc(sizeof(*ndata), GFP_NOFS);
if (!ndata) {
dlm_destroy_recovery_area(dlm, dead_node);
return -ENOMEM;
}
BUG_ON(lr->dead_node != dlm->reco.dead_node);
- item = kcalloc(1, sizeof(*item), GFP_NOFS);
+ item = kzalloc(sizeof(*item), GFP_NOFS);
if (!item) {
dlm_put(dlm);
return -ENOMEM;
ret = -ENOMEM;
buf = kmalloc(be16_to_cpu(msg->data_len), GFP_NOFS);
- item = kcalloc(1, sizeof(*item), GFP_NOFS);
+ item = kzalloc(sizeof(*item), GFP_NOFS);
if (!buf || !item)
goto leave;
((vfsmnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
return 0;
+ if (vfsmnt->mnt_flags & MNT_RELATIME) {
+ if ((timespec_compare(&inode->i_atime, &inode->i_mtime) <= 0) ||
+ (timespec_compare(&inode->i_atime, &inode->i_ctime) <= 0))
+ return 1;
+
+ return 0;
+ }
+
now = CURRENT_TIME;
if ((now.tv_sec - inode->i_atime.tv_sec <= osb->s_atime_quantum))
return 0;
{
int status;
- *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
if (!(*ac)) {
status = -ENOMEM;
mlog_errno(status);
struct buffer_head *bh = NULL;
struct ocfs2_slot_info *si;
- si = kcalloc(1, sizeof(struct ocfs2_slot_info), GFP_KERNEL);
+ si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL);
if (!si) {
status = -ENOMEM;
mlog_errno(status);
int status;
u32 slot;
- *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
if (!(*ac)) {
status = -ENOMEM;
mlog_errno(status);
{
int status;
- *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
if (!(*ac)) {
status = -ENOMEM;
mlog_errno(status);
mlog_entry_void();
- *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
if (!(*ac)) {
status = -ENOMEM;
mlog_errno(status);
BUG_ON(uuid_bytes != OCFS2_VOL_UUID_LEN);
- osb->uuid_str = kcalloc(1, OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL);
+ osb->uuid_str = kzalloc(OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL);
if (osb->uuid_str == NULL)
return -ENOMEM;
mlog_entry_void();
- osb = kcalloc(1, sizeof(struct ocfs2_super), GFP_KERNEL);
+ osb = kzalloc(sizeof(struct ocfs2_super), GFP_KERNEL);
if (!osb) {
status = -ENOMEM;
mlog_errno(status);
*/
/* initialize our journal structure */
- journal = kcalloc(1, sizeof(struct ocfs2_journal), GFP_KERNEL);
+ journal = kzalloc(sizeof(struct ocfs2_journal), GFP_KERNEL);
if (!journal) {
mlog(ML_ERROR, "unable to alloc journal\n");
status = -ENOMEM;
{
struct ocfs2_net_wait_ctxt *w;
- w = kcalloc(1, sizeof(*w), GFP_NOFS);
+ w = kzalloc(sizeof(*w), GFP_NOFS);
if (!w) {
mlog_errno(-ENOMEM);
goto bail;
BUG_ON(!ocfs2_is_valid_vote_request(type));
- request = kcalloc(1, sizeof(*request), GFP_NOFS);
+ request = kzalloc(sizeof(*request), GFP_NOFS);
if (!request) {
mlog_errno(-ENOMEM);
} else {
return 0;
}
-static struct pipe_buf_operations anon_pipe_buf_ops = {
+static const struct pipe_buf_operations anon_pipe_buf_ops = {
.can_merge = 1,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
if (bufs) {
int curbuf = pipe->curbuf;
struct pipe_buffer *buf = pipe->bufs + curbuf;
- struct pipe_buf_operations *ops = buf->ops;
+ const struct pipe_buf_operations *ops = buf->ops;
void *addr;
size_t chars = buf->len;
int error, atomic;
int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
(PIPE_BUFFERS-1);
struct pipe_buffer *buf = pipe->bufs + lastbuf;
- struct pipe_buf_operations *ops = buf->ops;
+ const struct pipe_buf_operations *ops = buf->ops;
int offset = buf->offset + buf->len;
if (ops->can_merge && offset + chars <= PAGE_SIZE) {
.fasync = pipe_rdwr_fasync,
};
-static struct file_operations read_pipe_fops = {
+static const struct file_operations read_pipe_fops = {
.llseek = no_llseek,
.read = do_sync_read,
.aio_read = pipe_read,
.fasync = pipe_read_fasync,
};
-static struct file_operations write_pipe_fops = {
+static const struct file_operations write_pipe_fops = {
.llseek = no_llseek,
.read = bad_pipe_r,
.write = do_sync_write,
.fasync = pipe_write_fasync,
};
-static struct file_operations rdwr_pipe_fops = {
+static const struct file_operations rdwr_pipe_fops = {
.llseek = no_llseek,
.read = do_sync_read,
.aio_read = pipe_read,
return seg;
}
-EXPORT_UNUSED_SYMBOL(iov_shorten); /* June 2006 */
-
ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
{
int n;
*size = reiserfs_acl_size(acl->a_count);
- ext_acl = (reiserfs_acl_header *) kmalloc(sizeof(reiserfs_acl_header) +
+ ext_acl = kmalloc(sizeof(reiserfs_acl_header) +
acl->a_count *
sizeof(reiserfs_acl_entry),
GFP_NOFS);
smb_close_socket(server);
if (server->conn_pid)
- kill_proc(server->conn_pid, SIGTERM, 1);
+ kill_pid(server->conn_pid, SIGTERM, 1);
kfree(server->ops);
smb_unload_nls(server);
sb->s_fs_info = NULL;
smb_unlock_server(server);
+ put_pid(server->conn_pid);
kfree(server);
}
INIT_LIST_HEAD(&server->xmitq);
INIT_LIST_HEAD(&server->recvq);
server->conn_error = 0;
- server->conn_pid = 0;
+ server->conn_pid = NULL;
server->state = CONN_INVALID; /* no connection yet */
server->generation = 0;
goto out_putf;
server->sock_file = filp;
- server->conn_pid = current->pid;
+ server->conn_pid = get_pid(task_pid(current));
server->opt = *opt;
server->generation += 1;
server->state = CONN_VALID;
}
VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
- server->opt.protocol, server->opt.max_xmit, server->conn_pid,
- server->opt.capabilities);
+ server->opt.protocol, server->opt.max_xmit,
+ pid_nr(server->conn_pid), server->opt.capabilities);
/* FIXME: this really should be done by smbmount. */
if (server->opt.max_xmit > SMB_MAX_PACKET_SIZE) {
{
struct list_head *head;
struct smb_request *req;
- pid_t pid = server->conn_pid;
+ struct pid *pid = get_pid(server->conn_pid);
int result = 0;
VERBOSE("state: %d\n", server->state);
/*
* Note: use the "priv" flag, as a user process may need to reconnect.
*/
- result = kill_proc(pid, SIGUSR1, 1);
+ result = kill_pid(pid, SIGUSR1, 1);
if (result) {
/* FIXME: this is most likely fatal, umount? */
printk(KERN_ERR "smb_retry: signal failed [%d]\n", result);
/* FIXME: The retried requests should perhaps get a "time boost". */
out:
+ put_pid(pid);
return result;
}
struct partial_page *partial; /* pages[] may not be contig */
int nr_pages; /* number of pages in map */
unsigned int flags; /* splice flags */
- struct pipe_buf_operations *ops;/* ops associated with output pipe */
+ const struct pipe_buf_operations *ops;/* ops associated with output pipe */
};
/*
return err;
}
-static struct pipe_buf_operations page_cache_pipe_buf_ops = {
+static const struct pipe_buf_operations page_cache_pipe_buf_ops = {
.can_merge = 0,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
return generic_pipe_buf_steal(pipe, buf);
}
-static struct pipe_buf_operations user_page_pipe_buf_ops = {
+static const struct pipe_buf_operations user_page_pipe_buf_ops = {
.can_merge = 0,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
for (;;) {
if (pipe->nrbufs) {
struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
- struct pipe_buf_operations *ops = buf->ops;
+ const struct pipe_buf_operations *ops = buf->ops;
sd.len = buf->len;
if (sd.len > sd.total_len)
/* Caches aren't brain-dead on the Alpha. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
unsigned long len, int write);
#endif
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
/*
* flush_cache_user_range is used when we want to ensure that the
* Harvard caches are synchronised for the user space address range.
#define TIF_POLLING_NRFLAG 16
#define TIF_USING_IWMMXT 17
#define TIF_MEMDIE 18
+#define TIF_FREEZE 19
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
+#define _TIF_FREEZE (1 << TIF_FREEZE)
/*
* Change these and you break ASM code in entry-common.S
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma,start,end) do { } while (0)
#define flush_cache_page(vma,vmaddr,pfn) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm)
{
unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
- pgd_t *pgd = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
+ pgd_t *pgd = kmalloc(pgd_size, GFP_KERNEL);
if (pgd)
memset(pgd, 0, pgd_size);
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
*/
#define flush_cache_all() do {} while(0)
#define flush_cache_mm(mm) do {} while(0)
+#define flush_cache_dup_mm(mm) do {} while(0)
#define flush_cache_range(mm, start, end) do {} while(0)
#define flush_cache_page(vma, vmaddr, pfn) do {} while(0)
#define flush_cache_vmap(start, end) do {} while(0)
#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 /* OOM killer killed process */
+#define TIF_FREEZE 18 /* freezing for suspend */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_IRET (1 << TIF_IRET)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE (1 << TIF_FREEZE)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
#define flush_cache_all()
#define flush_cache_mm(mm)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma,a,b)
#define flush_cache_page(vma,p,pfn)
#define flush_dcache_page(page)
/* Caches aren't brain-dead on the intel. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define TIF_MEMDIE 16
#define TIF_DEBUG 17 /* uses debug registers */
#define TIF_IO_BITMAP 18 /* uses I/O bitmap */
+#define TIF_FREEZE 19 /* is freezing for suspend */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_DEBUG (1<<TIF_DEBUG)
#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_icache_page(vma,page) do { } while (0)
#define TIF_MEMDIE 17
#define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */
#define TIF_DB_DISABLED 19 /* debug trap disabled for fsyscall */
+#define TIF_FREEZE 20 /* is freezing for suspend */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_MCA_INIT (1 << TIF_MCA_INIT)
#define _TIF_DB_DISABLED (1 << TIF_DB_DISABLED)
+#define _TIF_FREEZE (1 << TIF_FREEZE)
/* "work to do on user-return" bits */
#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#elif defined(CONFIG_CHIP_M32102)
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#else
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
__flush_cache_030();
}
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
/* flush_cache_range/flush_cache_page must be macros to avoid
a dependency on linux/mm.h, which includes this file... */
static inline void flush_cache_range(struct vm_area_struct *vma,
+++ /dev/null
-/*
- * SWIM access through the IOP
- * Written by Joshua M. Thompson
- */
-
-/* IOP number and channel number for the SWIM */
-
-#define SWIM_IOP IOP_NUM_ISM
-#define SWIM_CHAN 1
-
-/* Command code: */
-
-#define CMD_INIT 0x01 /* Initialize */
-#define CMD_SHUTDOWN 0x02 /* Shutdown */
-#define CMD_START_POLL 0x03 /* Start insert/eject polling */
-#define CMD_STOP_POLL 0x04 /* Stop insert/eject polling */
-#define CMD_SETHFSTAG 0x05 /* Set HFS tag buffer address */
-#define CMD_STATUS 0x06 /* Status */
-#define CMD_EJECT 0x07 /* Eject */
-#define CMD_FORMAT 0x08 /* Format */
-#define CMD_FORMAT_VERIFY 0x09 /* Format and Verify */
-#define CMD_WRITE 0x0A /* Write */
-#define CMD_READ 0x0B /* Read */
-#define CMD_READ_VERIFY 0x0C /* Read and Verify */
-#define CMD_CACHE_CTRL 0x0D /* Cache control */
-#define CMD_TAGBUFF_CTRL 0x0E /* Tag buffer control */
-#define CMD_GET_ICON 0x0F /* Get Icon */
-
-/* Drive types: */
-
-/* note: apple sez DRV_FDHD is 4, but I get back a type */
-/* of 5 when I do a drive status check on my FDHD */
-
-#define DRV_NONE 0 /* No drive */
-#define DRV_UNKNOWN 1 /* Unspecified drive */
-#define DRV_400K 2 /* 400K */
-#define DRV_800K 3 /* 400K/800K */
-#define DRV_FDHD 5 /* 400K/800K/720K/1440K */
-#define DRV_HD20 7 /* Apple HD20 */
-
-/* Format types: */
-
-#define FMT_HD20 0x0001 /* Apple HD20 */
-#define FMT_400K 0x0002 /* 400K (GCR) */
-#define FMT_800K 0x0004 /* 800K (GCR) */
-#define FMT_720K 0x0008 /* 720K (MFM) */
-#define FMT_1440K 0x0010 /* 1.44M (MFM) */
-
-#define FMD_KIND_400K 1
-#define FMD_KIND_800K 2
-#define FMD_KIND_720K 3
-#define FMD_KIND_1440K 1
-
-/* Icon Flags: */
-
-#define ICON_MEDIA 0x01 /* Have IOP supply media icon */
-#define ICON_DRIVE 0x01 /* Have IOP supply drive icon */
-
-/* Error codes: */
-
-#define gcrOnMFMErr -400 /* GCR (400/800K) on HD media */
-#define verErr -84 /* verify failed */
-#define fmt2Err -83 /* can't get enough sync during format */
-#define fmt1Err -82 /* can't find sector 0 after track format */
-#define sectNFErr -81 /* can't find sector */
-#define seekErr -80 /* drive error during seek */
-#define spdAdjErr -79 /* can't set drive speed */
-#define twoSideErr -78 /* drive is single-sided */
-#define initIWMErr -77 /* error during initialization */
-#define tk0badErr -76 /* track zero is bad */
-#define cantStepErr -75 /* drive error during step */
-#define wrUnderrun -74 /* write underrun occurred */
-#define badDBtSlp -73 /* bad data bitslip marks */
-#define badDCksum -72 /* bad data checksum */
-#define noDtaMkErr -71 /* can't find data mark */
-#define badBtSlpErr -70 /* bad address bitslip marks */
-#define badCksmErr -69 /* bad address-mark checksum */
-#define dataVerErr -68 /* read-verify failed */
-#define noAdrMkErr -67 /* can't find an address mark */
-#define noNybErr -66 /* no nybbles? disk is probably degaussed */
-#define offLinErr -65 /* no disk in drive */
-#define noDriveErr -64 /* drive isn't connected */
-#define nsDrvErr -56 /* no such drive */
-#define paramErr -50 /* bad positioning information */
-#define wPrErr -44 /* write protected */
-#define openErr -23 /* already initialized */
-
-#ifndef __ASSEMBLY__
-
-struct swim_drvstatus {
- __u16 curr_track; /* Current track number */
- __u8 write_prot; /* 0x80 if disk is write protected */
- __u8 disk_in_drive; /* 0x01 or 0x02 if a disk is in the drive */
- __u8 installed; /* 0x01 if drive installed, 0xFF if not */
- __u8 num_sides; /* 0x80 if two-sided format supported */
- __u8 two_sided; /* 0xff if two-sided format diskette */
- __u8 new_interface; /* 0x00 if old 400K drive, 0xFF if newer */
- __u16 errors; /* Disk error count */
- struct { /* 32 bits */
- __u16 reserved;
- __u16 :4;
- __u16 external:1; /* Drive is external */
- __u16 scsi:1; /* Drive is a SCSI drive */
- __u16 fixed:1; /* Drive has fixed media */
- __u16 secondary:1; /* Drive is secondary drive */
- __u8 type; /* Drive type */
- } info;
- __u8 mfm_drive; /* 0xFF if this is an FDHD drive */
- __u8 mfm_disk; /* 0xFF if 720K/1440K (MFM) disk */
- __u8 mfm_format; /* 0x00 if 720K, 0xFF if 1440K */
- __u8 ctlr_type; /* 0x00 if IWM, 0xFF if SWIM */
- __u16 curr_format; /* Current format type */
- __u16 allowed_fmt; /* Allowed format types */
- __u32 num_blocks; /* Number of blocks on disk */
- __u8 icon_flags; /* Icon flags */
- __u8 unusued;
-};
-
-/* Commands issued from the host to the IOP: */
-
-struct swimcmd_init {
- __u8 code; /* CMD_INIT */
- __u8 unusued;
- __u16 error;
- __u8 drives[28]; /* drive type list */
-};
-
-struct swimcmd_startpoll {
- __u8 code; /* CMD_START_POLL */
- __u8 unusued;
- __u16 error;
-};
-
-struct swimcmd_sethfstag {
- __u8 code; /* CMD_SETHFSTAG */
- __u8 unusued;
- __u16 error;
- caddr_t tagbuf; /* HFS tag buffer address */
-};
-
-struct swimcmd_status {
- __u8 code; /* CMD_STATUS */
- __u8 drive_num;
- __u16 error;
- struct swim_drvstatus status;
-};
-
-struct swimcmd_eject {
- __u8 code; /* CMD_EJECT */
- __u8 drive_num;
- __u16 error;
- struct swim_drvstatus status;
-};
-
-struct swimcmd_format {
- __u8 code; /* CMD_FORMAT */
- __u8 drive_num;
- __u16 error;
- union {
- struct {
- __u16 fmt; /* format kind */
- __u8 hdrbyte; /* fmt byte for hdr (0=default) */
- __u8 interleave; /* interleave (0 = default) */
- caddr_t databuf; /* sector data buff (0=default */
- caddr_t tagbuf; /* tag data buffer (0=default) */
- } f;
- struct swim_drvstatus status;
- } p;
-};
-
-struct swimcmd_fmtverify {
- __u8 code; /* CMD_FORMAT_VERIFY */
- __u8 drive_num;
- __u16 error;
-};
-
-struct swimcmd_rw {
- __u8 code; /* CMD_READ, CMD_WRITE or CMD_READ_VERIFY */
- __u8 drive_num;
- __u16 error;
- caddr_t buffer; /* R/W buffer address */
- __u32 first_block; /* Starting block */
- __u32 num_blocks; /* Number of blocks */
- __u8 tag[12]; /* tag data */
-};
-
-struct swimcmd_cachectl {
- __u8 code; /* CMD_CACHE_CTRL */
- __u8 unused;
- __u16 error;
- __u8 enable; /* Nonzero to enable cache */
- __u8 install; /* +1 = install, -1 = remove, 0 = neither */
-};
-
-struct swimcmd_tagbufctl {
- __u8 code; /* CMD_TAGBUFF_CTRL */
- __u8 unused;
- __u16 error;
- caddr_t buf; /* buffer address or 0 to disable */
-};
-
-struct swimcmd_geticon {
- __u8 code; /* CMD_GET_ICON */
- __u8 drive_num;
- __u16 error;
- caddr_t buffer; /* Nuffer address */
- __u16 kind; /* 0 = media icon, 1 = drive icon */
- __u16 unused;
- __u16 max_bytes; /* maximum byte count */
-};
-
-/* Messages from the SWIM IOP to the host CPU: */
-
-struct swimmsg_status {
- __u8 code; /* 1 = insert, 2 = eject, 3 = status changed */
- __u8 drive_num;
- __u16 error;
- struct swim_drvstatus status;
-};
-
-#endif /* __ASSEMBLY__ */
#define flush_cache_all() __flush_cache_all()
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) __flush_cache_all()
#define flush_cache_page(vma, vmaddr) do { } while (0)
#define flush_dcache_range(start,len) __flush_cache_all()
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ * - flush_cache_dup mm(mm) handles cache flushing when forking
* - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
* - flush_icache_range(start, end) flush a range of instructions
extern void (*flush_cache_all)(void);
extern void (*__flush_cache_all)(void);
extern void (*flush_cache_mm)(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0)
extern void (*flush_cache_range)(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
#ifndef __ASSEMBLY__
#include <linux/pfn.h>
-#include <asm/cpu-features.h>
#include <asm/io.h>
extern void clear_page(void * page);
flush_data_cache_page((unsigned long)addr);
}
-static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
- struct page *to)
-{
- extern void (*flush_data_cache_page)(unsigned long addr);
+extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+ struct page *to);
+struct vm_area_struct;
+extern void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma);
- copy_page(vto, vfrom);
- if (!cpu_has_ic_fills_f_dc ||
- pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
- flush_data_cache_page((unsigned long)vto);
-}
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
/*
* These are used to make use of C type-checking..
#define flush_cache_mm(mm) flush_cache_all_local()
#endif
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
#define flush_kernel_dcache_range(start,size) \
flush_kernel_dcache_range_asm((start), (start)+(size));
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_icache_page(vma, page) do { } while (0)
#define TIF_RESTOREALL 12 /* Restore all regs (implies NOERROR) */
#define TIF_NOERROR 14 /* Force successful syscall return */
#define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */
+#define TIF_FREEZE 16 /* Freezing for suspend */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_RESTOREALL (1<<TIF_RESTOREALL)
#define _TIF_NOERROR (1<<TIF_NOERROR)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
/* Caches aren't brain-dead on the s390. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ * - flush_cache_dup mm(mm) handles cache flushing when forking
* - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
*
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ * - flush_cache_dup mm(mm) handles cache flushing when forking
* - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
*
void flush_cache_all(void);
void flush_cache_mm(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
#else
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
*/
void flush_cache_all(void);
void flush_cache_mm(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18
+#define TIF_FREEZE 19
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_WORK_MASK 0x000000FE /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x000000FF /* work to do on any return to u-space */
struct page *page, unsigned long addr,
int len);
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
static inline pgd_t *get_pgd_slow(void)
{
unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
- pgd_t *ret = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
+ pgd_t *ret = kmalloc(pgd_size, GFP_KERNEL);
return ret;
}
#define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
#define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
+#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
#define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
#define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
#define flush_icache_range(start, end) do { } while (0)
/* These are the same regardless of whether this is an SMP kernel or not. */
#define flush_cache_mm(__mm) \
do { if ((__mm) == current->mm) flushw_user(); } while(0)
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
#define flush_cache_range(vma, start, end) \
flush_cache_mm((vma)->vm_mm)
#define flush_cache_page(vma, page, pfn) \
systems with MMUs, so we don't need them. */
#define flush_cache_all() ((void)0)
#define flush_cache_mm(mm) ((void)0)
+#define flush_cache_dup_mm(mm) ((void)0)
#define flush_cache_range(vma, start, end) ((void)0)
#define flush_cache_page(vma, vmaddr, pfn) ((void)0)
#define flush_dcache_page(page) ((void)0)
/* Caches aren't brain-dead on the intel. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define TIF_MEMDIE 20
#define TIF_DEBUG 21 /* uses debug registers */
#define TIF_IO_BITMAP 22 /* uses I/O bitmap */
+#define TIF_FREEZE 23 /* is freezing for suspend */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_DEBUG (1<<TIF_DEBUG)
#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
#define flush_cache_all() __flush_invalidate_cache_all();
#define flush_cache_mm(mm) __flush_invalidate_cache_all();
+#define flush_cache_dup_mm(mm) __flush_invalidate_cache_all();
#define flush_cache_vmap(start,end) __flush_invalidate_cache_all();
#define flush_cache_vunmap(start,end) __flush_invalidate_cache_all();
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_vmap(start,end) do { } while (0)
#define flush_cache_vunmap(start,end) do { } while (0)
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#ifdef __ASSEMBLY__
-#define _ASMLANGUAGE
#include <asm/current.h>
#include <asm/asm-offsets.h>
#include <asm/processor.h>
wait_queue_t ki_wait;
loff_t ki_pos;
+ atomic_t ki_bio_count; /* num bio used for this iocb */
void *private;
/* State that we remember to be able to restart/retry */
unsigned short ki_opcode;
gfp_t);
extern void bio_set_pages_dirty(struct bio *bio);
extern void bio_check_pages_dirty(struct bio *bio);
+extern void bio_release_pages(struct bio *bio);
extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
extern int bio_uncopy_user(struct bio *);
void zero_fill_bio(struct bio *bio);
#define CODA_ALLOC(ptr, cast, size) do { \
if (size < PAGE_SIZE) \
- ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \
+ ptr = kmalloc((unsigned long) size, GFP_KERNEL); \
else \
ptr = (cast)vmalloc((unsigned long) size); \
if (!ptr) \
nodes_subset((nodes), current->mems_allowed)
int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
-extern int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask);
-static int inline cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+extern int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask);
+extern int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask);
+
+static int inline cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
+{
+ return number_of_cpusets <= 1 ||
+ __cpuset_zone_allowed_softwall(z, gfp_mask);
+}
+
+static int inline cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
{
- return number_of_cpusets <= 1 || __cpuset_zone_allowed(z, gfp_mask);
+ return number_of_cpusets <= 1 ||
+ __cpuset_zone_allowed_hardwall(z, gfp_mask);
}
extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
return 1;
}
-static inline int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+static inline int cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
+{
+ return 1;
+}
+
+static inline int cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
{
return 1;
}
#define FB_MODE_IS_FIRST 16
#define FB_MODE_IS_FROM_VAR 32
-extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
- const struct fb_info *fb_info);
extern int fbmon_dpms(const struct fb_info *fb_info);
extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
struct fb_info *info);
*/
static inline int freezing(struct task_struct *p)
{
- return p->flags & PF_FREEZE;
+ return test_tsk_thread_flag(p, TIF_FREEZE);
}
/*
* Request that a process be frozen
- * FIXME: SMP problem. We may not modify other process' flags!
*/
static inline void freeze(struct task_struct *p)
{
- p->flags |= PF_FREEZE;
+ set_tsk_thread_flag(p, TIF_FREEZE);
}
/*
*/
static inline void do_not_freeze(struct task_struct *p)
{
- p->flags &= ~PF_FREEZE;
+ clear_tsk_thread_flag(p, TIF_FREEZE);
}
/*
*/
static inline void frozen_process(struct task_struct *p)
{
- p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+ p->flags |= PF_FROZEN;
+ wmb();
+ clear_tsk_thread_flag(p, TIF_FREEZE);
}
extern void refrigerator(void);
#define MS_PRIVATE (1<<18) /* change to private */
#define MS_SLAVE (1<<19) /* change to slave */
#define MS_SHARED (1<<20) /* change to shared */
+#define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1<<31)
static inline struct gameport *gameport_allocate_port(void)
{
- struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL);
+ struct gameport *gameport = kzalloc(sizeof(struct gameport), GFP_KERNEL);
return gameport;
}
kunmap_atomic(kaddr, KM_USER0);
}
-static inline void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr)
+#ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE
+
+static inline void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma)
{
char *vfrom, *vto;
smp_wmb();
}
+#endif
+
static inline void copy_highpage(struct page *to, struct page *from)
{
char *vfrom, *vto;
#define I2C_DRIVERID_MTP008 1023
#define I2C_DRIVERID_DS1621 1024
#define I2C_DRIVERID_ADM1024 1025
-#define I2C_DRIVERID_IT87 1026
#define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
#define I2C_DRIVERID_FSCPOS 1028
#define I2C_DRIVERID_FSCSCY 1029
.pid_ns = &init_pid_ns, \
.count = ATOMIC_INIT(1), \
.nslock = __SPIN_LOCK_UNLOCKED(nsproxy.nslock), \
- .id = 0, \
.uts_ns = &init_uts_ns, \
.mnt_ns = NULL, \
INIT_IPC_NS(ipc_ns) \
* This is the set of functions for lockd->nfsd communication
*/
struct nlmsvc_binding {
- u32 (*fopen)(struct svc_rqst *,
+ __be32 (*fopen)(struct svc_rqst *,
struct nfs_fh *,
struct file **);
void (*fclose)(struct file *);
unsigned long nlmsvc_retry_blocked(void);
void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
nlm_host_match_fn_t match);
-void nlmsvc_grant_reply(struct nlm_cookie *, u32);
+void nlmsvc_grant_reply(struct nlm_cookie *, __be32);
/*
* File handling for the server personality
* Arguments for all calls to statd
*/
struct nsm_args {
- u32 addr; /* remote address */
+ __be32 addr; /* remote address */
u32 prog; /* RPC callback info */
u32 vers;
u32 proc;
*/
struct nlm_res {
struct nlm_cookie cookie;
- u32 status;
+ __be32 status;
struct nlm_lock lock;
};
char * mon;
int len;
u32 state;
- u32 addr;
- u32 vers;
- u32 proto;
+ __be32 addr;
+ __be32 vers;
+ __be32 proto;
};
/*
#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS)
extern void early_init_irq_lock_class(void);
#else
-# define early_init_irq_lock_class() do { } while (0)
+static inline void early_init_irq_lock_class(void)
+{
+}
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
extern void early_boot_irqs_off(void);
extern void early_boot_irqs_on(void);
+extern void print_irqtrace_events(struct task_struct *curr);
#else
-# define early_boot_irqs_off() do { } while (0)
-# define early_boot_irqs_on() do { } while (0)
+static inline void early_boot_irqs_off(void)
+{
+}
+static inline void early_boot_irqs_on(void)
+{
+}
+static inline void print_irqtrace_events(struct task_struct *curr)
+{
+}
#endif
/*
#define MNT_NOEXEC 0x04
#define MNT_NOATIME 0x08
#define MNT_NODIRATIME 0x10
+#define MNT_RELATIME 0x20
#define MNT_SHRINKABLE 0x100
struct r3964_client_info {
spinlock_t lock;
- pid_t pid;
+ struct pid *pid;
unsigned int sig_flags;
struct r3964_client_info *next;
unsigned int int_flags; /* internal flags */
#define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001
__kernel_uid32_t mounted_uid; /* Who may umount() this filesystem? */
- __kernel_pid_t wdog_pid; /* Who cares for our watchdog packets? */
+ struct pid *wdog_pid; /* Who cares for our watchdog packets? */
unsigned int ncp_fd; /* The socket to the ncp port */
unsigned int time_out; /* How long should I wait after
sending a NCP request? */
* we might process an operation with side effects, and be unable to
* tell the client that the operation succeeded.
*
- * COMPOUND_SLACK_SPACE - this is the minimum amount of buffer space
+ * COMPOUND_SLACK_SPACE - this is the minimum bytes of buffer space
* needed to encode an "ordinary" _successful_ operation. (GETATTR,
* READ, READDIR, and READLINK have their own buffer checks.) if we
* fall below this level, we fail the next operation with NFS4ERR_RESOURCE.
*
- * COMPOUND_ERR_SLACK_SPACE - this is the minimum amount of buffer space
+ * COMPOUND_ERR_SLACK_SPACE - this is the minimum bytes of buffer space
* needed to encode an operation which has failed with NFS4ERR_RESOURCE.
* care is taken to ensure that we never fall below this level for any
* reason.
((err) != nfserr_stale_stateid) && \
((err) != nfserr_bad_stateid))
-extern __be32 nfsd4_renew(clientid_t *clid);
extern __be32 nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
stateid_t *stateid, int flags, struct file **filp);
extern void nfs4_lock_state(void);
#define NFSD4_MAX_TAGLEN 128
#define XDR_LEN(n) (((n) + 3) & ~3)
+struct nfsd4_compound_state {
+ struct svc_fh current_fh;
+ struct svc_fh save_fh;
+ struct nfs4_stateowner *replay_owner;
+};
+
struct nfsd4_change_info {
u32 atomic;
u32 before_ctime_sec;
struct dentry *dentry, __be32 *buffer, int *countp,
u32 *bmval, struct svc_rqst *);
extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
struct nfsd4_setclientid *setclid);
extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
struct nfsd4_setclientid_confirm *setclientid_confirm);
extern __be32 nfsd4_process_open1(struct nfsd4_open *open);
extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
struct svc_fh *current_fh, struct nfsd4_open *open);
extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_open_confirm *oc,
- struct nfs4_stateowner **);
-extern __be32 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_close *close,
- struct nfs4_stateowner **replay_owner);
+ struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc);
+extern __be32 nfsd4_close(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
+ struct nfsd4_close *close);
extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_open_downgrade *od,
- struct nfs4_stateowner **replay_owner);
-extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_lock *lock,
- struct nfs4_stateowner **replay_owner);
-extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+ struct nfsd4_compound_state *,
+ struct nfsd4_open_downgrade *od);
+extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
+ struct nfsd4_lock *lock);
+extern __be32 nfsd4_lockt(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
struct nfsd4_lockt *lockt);
-extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_locku *locku,
- struct nfs4_stateowner **replay_owner);
+extern __be32 nfsd4_locku(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
+ struct nfsd4_locku *locku);
extern __be32
nfsd4_release_lockowner(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
struct nfsd4_release_lockowner *rlockowner);
extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_delegreturn *dr);
+ struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
+extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *, clientid_t *clid);
#endif
/*
struct nsproxy {
atomic_t count;
spinlock_t nslock;
- unsigned long id;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366
#define PCI_DEVICE_ID_JMICRON_JMB368 0x2368
+#define PCI_VENDOR_ID_KORENIX 0x1982
+#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600
+#define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff
+
#define PCI_VENDOR_ID_TEKRAM 0x1de1
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
struct pipe_buffer {
struct page *page;
unsigned int offset, len;
- struct pipe_buf_operations *ops;
+ const struct pipe_buf_operations *ops;
unsigned int flags;
};
struct pipe_inode_info {
wait_queue_head_t wait;
unsigned int nrbufs, curbuf;
- struct pipe_buffer bufs[PIPE_BUFFERS];
struct page *tmp_page;
- unsigned int start;
unsigned int readers;
unsigned int writers;
unsigned int waiting_writers;
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
struct inode *inode;
+ struct pipe_buffer bufs[PIPE_BUFFERS];
};
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
extern struct platform_device *platform_device_alloc(const char *name, unsigned int id);
extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
-extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size);
+extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size);
extern int platform_device_add(struct platform_device *pdev);
extern void platform_device_del(struct platform_device *pdev);
extern void platform_device_put(struct platform_device *pdev);
--- /dev/null
+#ifndef _LINUX_RECIPROCAL_DIV_H
+#define _LINUX_RECIPROCAL_DIV_H
+
+#include <linux/types.h>
+
+/*
+ * This file describes reciprocical division.
+ *
+ * This optimizes the (A/B) problem, when A and B are two u32
+ * and B is a known value (but not known at compile time)
+ *
+ * The math principle used is :
+ * Let RECIPROCAL_VALUE(B) be (((1LL << 32) + (B - 1))/ B)
+ * Then A / B = (u32)(((u64)(A) * (R)) >> 32)
+ *
+ * This replaces a divide by a multiply (and a shift), and
+ * is generally less expensive in CPU cycles.
+ */
+
+/*
+ * Computes the reciprocal value (R) for the value B of the divisor.
+ * Should not be called before each reciprocal_divide(),
+ * or else the performance is slower than a normal divide.
+ */
+extern u32 reciprocal_value(u32 B);
+
+
+static inline u32 reciprocal_divide(u32 A, u32 R)
+{
+ return (u32)(((u64)A * R) >> 32);
+}
+#endif
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_FLUSHER 0x00001000 /* responsible for disk writeback */
#define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */
-#define PF_FREEZE 0x00004000 /* this task is being frozen for suspend now */
#define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */
#define PF_FROZEN 0x00010000 /* frozen for system suspend */
#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
/*
- * linux/include/linux/slab.h
- * Written by Mark Hemment, 1996.
- * (markhe@nextd.demon.co.uk)
+ * Written by Mark Hemment, 1996 (markhe@nextd.demon.co.uk).
+ *
+ * (C) SGI 2006, Christoph Lameter <clameter@sgi.com>
+ * Cleaned up and restructured to ease the addition of alternative
+ * implementations of SLAB allocators.
*/
#ifndef _LINUX_SLAB_H
#ifdef __KERNEL__
#include <linux/gfp.h>
-#include <linux/init.h>
#include <linux/types.h>
-#include <asm/page.h> /* kmalloc_sizes.h needs PAGE_SIZE */
-#include <asm/cache.h> /* kmalloc_sizes.h needs L1_CACHE_BYTES */
-#include <linux/compiler.h>
-/* kmem_cache_t exists for legacy reasons and is not used by code in mm */
typedef struct kmem_cache kmem_cache_t __deprecated;
-/* flags to pass to kmem_cache_create().
- * The first 3 are only valid when the allocator as been build
- * SLAB_DEBUG_SUPPORT.
+/*
+ * Flags to pass to kmem_cache_create().
+ * The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
*/
-#define SLAB_DEBUG_FREE 0x00000100UL /* Peform (expensive) checks on free */
-#define SLAB_DEBUG_INITIAL 0x00000200UL /* Call constructor (as verifier) */
-#define SLAB_RED_ZONE 0x00000400UL /* Red zone objs in a cache */
-#define SLAB_POISON 0x00000800UL /* Poison objects */
-#define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */
-#define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */
-#define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */
-#define SLAB_STORE_USER 0x00010000UL /* store the last owner for bug hunting */
-#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* track pages allocated to indicate
- what is reclaimable later*/
-#define SLAB_PANIC 0x00040000UL /* panic if kmem_cache_create() fails */
-#define SLAB_DESTROY_BY_RCU 0x00080000UL /* defer freeing pages to RCU */
+#define SLAB_DEBUG_FREE 0x00000100UL /* DEBUG: Perform (expensive) checks on free */
+#define SLAB_DEBUG_INITIAL 0x00000200UL /* DEBUG: Call constructor (as verifier) */
+#define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */
+#define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */
+#define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */
+#define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */
+#define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* Force alignment even if debuggin is active */
+#define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */
+#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
+#define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */
+#define SLAB_DESTROY_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */
#define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */
-/* flags passed to a constructor func */
-#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */
-#define SLAB_CTOR_ATOMIC 0x002UL /* tell constructor it can't sleep */
-#define SLAB_CTOR_VERIFY 0x004UL /* tell constructor it's a verify call */
+/* Flags passed to a constructor functions */
+#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* If not set, then deconstructor */
+#define SLAB_CTOR_ATOMIC 0x002UL /* Tell constructor it can't sleep */
+#define SLAB_CTOR_VERIFY 0x004UL /* Tell constructor it's a verify call */
-#ifndef CONFIG_SLOB
-
-/* prototypes */
-extern void __init kmem_cache_init(void);
+/*
+ * struct kmem_cache related prototypes
+ */
+void __init kmem_cache_init(void);
+extern int slab_is_available(void);
-extern struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
+struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
unsigned long,
void (*)(void *, struct kmem_cache *, unsigned long),
void (*)(void *, struct kmem_cache *, unsigned long));
-extern void kmem_cache_destroy(struct kmem_cache *);
-extern int kmem_cache_shrink(struct kmem_cache *);
-extern void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
-extern void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
-extern void kmem_cache_free(struct kmem_cache *, void *);
-extern unsigned int kmem_cache_size(struct kmem_cache *);
-extern const char *kmem_cache_name(struct kmem_cache *);
+void kmem_cache_destroy(struct kmem_cache *);
+int kmem_cache_shrink(struct kmem_cache *);
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
+void kmem_cache_free(struct kmem_cache *, void *);
+unsigned int kmem_cache_size(struct kmem_cache *);
+const char *kmem_cache_name(struct kmem_cache *);
+int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
+
+#ifdef CONFIG_NUMA
+extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
+#else
+static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
+ gfp_t flags, int node)
+{
+ return kmem_cache_alloc(cachep, flags);
+}
+#endif
+
+/*
+ * Common kmalloc functions provided by all allocators
+ */
+void *__kmalloc(size_t, gfp_t);
+void *__kzalloc(size_t, gfp_t);
+void kfree(const void *);
+unsigned int ksize(const void *);
+
+/**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate.
+ */
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+ if (n != 0 && size > ULONG_MAX / n)
+ return NULL;
+ return __kzalloc(n * size, flags);
+}
-/* Size description struct for general caches. */
-struct cache_sizes {
- size_t cs_size;
- struct kmem_cache *cs_cachep;
- struct kmem_cache *cs_dmacachep;
-};
-extern struct cache_sizes malloc_sizes[];
+/*
+ * Allocator specific definitions. These are mainly used to establish optimized
+ * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by selecting
+ * the appropriate general cache at compile time.
+ */
-extern void *__kmalloc(size_t, gfp_t);
+#ifdef CONFIG_SLAB
+#include <linux/slab_def.h>
+#else
+/*
+ * Fallback definitions for an allocator not wanting to provide
+ * its own optimized kmalloc definitions (like SLOB).
+ */
/**
* kmalloc - allocate memory
*/
static inline void *kmalloc(size_t size, gfp_t flags)
{
- if (__builtin_constant_p(size)) {
- int i = 0;
-#define CACHE(x) \
- if (size <= x) \
- goto found; \
- else \
- i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
- {
- extern void __you_cannot_kmalloc_that_much(void);
- __you_cannot_kmalloc_that_much();
- }
-found:
- return kmem_cache_alloc((flags & GFP_DMA) ?
- malloc_sizes[i].cs_dmacachep :
- malloc_sizes[i].cs_cachep, flags);
- }
return __kmalloc(size, flags);
}
-/*
- * kmalloc_track_caller is a special version of kmalloc that records the
- * calling function of the routine calling it for slab leak tracking instead
- * of just the calling function (confusing, eh?).
- * It's useful when the call to kmalloc comes from a widely-used standard
- * allocator where we care about the real place the memory allocation
- * request comes from.
- */
-#ifndef CONFIG_DEBUG_SLAB
-#define kmalloc_track_caller(size, flags) \
- __kmalloc(size, flags)
-#else
-extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
-#define kmalloc_track_caller(size, flags) \
- __kmalloc_track_caller(size, flags, __builtin_return_address(0))
-#endif
-
-extern void *__kzalloc(size_t, gfp_t);
-
/**
* kzalloc - allocate memory. The memory is set to zero.
* @size: how many bytes of memory are required.
*/
static inline void *kzalloc(size_t size, gfp_t flags)
{
- if (__builtin_constant_p(size)) {
- int i = 0;
-#define CACHE(x) \
- if (size <= x) \
- goto found; \
- else \
- i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
- {
- extern void __you_cannot_kzalloc_that_much(void);
- __you_cannot_kzalloc_that_much();
- }
-found:
- return kmem_cache_zalloc((flags & GFP_DMA) ?
- malloc_sizes[i].cs_dmacachep :
- malloc_sizes[i].cs_cachep, flags);
- }
return __kzalloc(size, flags);
}
+#endif
-/**
- * kcalloc - allocate memory for an array. The memory is set to zero.
- * @n: number of elements.
- * @size: element size.
- * @flags: the type of memory to allocate.
- */
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+#ifndef CONFIG_NUMA
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
- if (n != 0 && size > ULONG_MAX / n)
- return NULL;
- return kzalloc(n * size, flags);
+ return kmalloc(size, flags);
}
-extern void kfree(const void *);
-extern unsigned int ksize(const void *);
-extern int slab_is_available(void);
-
-#ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
-extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
-
-static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+static inline void *__kmalloc_node(size_t size, gfp_t flags, int node)
{
- if (__builtin_constant_p(size)) {
- int i = 0;
-#define CACHE(x) \
- if (size <= x) \
- goto found; \
- else \
- i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
- {
- extern void __you_cannot_kmalloc_that_much(void);
- __you_cannot_kmalloc_that_much();
- }
-found:
- return kmem_cache_alloc_node((flags & GFP_DMA) ?
- malloc_sizes[i].cs_dmacachep :
- malloc_sizes[i].cs_cachep, flags, node);
- }
- return __kmalloc_node(size, flags, node);
+ return __kmalloc(size, flags);
}
+#endif /* !CONFIG_NUMA */
+/*
+ * kmalloc_track_caller is a special version of kmalloc that records the
+ * calling function of the routine calling it for slab leak tracking instead
+ * of just the calling function (confusing, eh?).
+ * It's useful when the call to kmalloc comes from a widely-used standard
+ * allocator where we care about the real place the memory allocation
+ * request comes from.
+ */
+#ifdef CONFIG_DEBUG_SLAB
+extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
+#define kmalloc_track_caller(size, flags) \
+ __kmalloc_track_caller(size, flags, __builtin_return_address(0))
+#else
+#define kmalloc_track_caller(size, flags) \
+ __kmalloc(size, flags)
+#endif /* DEBUG_SLAB */
+
+#ifdef CONFIG_NUMA
/*
* kmalloc_node_track_caller is a special version of kmalloc_node that
* records the calling function of the routine calling it for slab leak
* standard allocator where we care about the real place the memory
* allocation request comes from.
*/
-#ifndef CONFIG_DEBUG_SLAB
-#define kmalloc_node_track_caller(size, flags, node) \
- __kmalloc_node(size, flags, node)
-#else
+#ifdef CONFIG_DEBUG_SLAB
extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *);
#define kmalloc_node_track_caller(size, flags, node) \
__kmalloc_node_track_caller(size, flags, node, \
__builtin_return_address(0))
+#else
+#define kmalloc_node_track_caller(size, flags, node) \
+ __kmalloc_node(size, flags, node)
#endif
+
#else /* CONFIG_NUMA */
-static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
- gfp_t flags, int node)
-{
- return kmem_cache_alloc(cachep, flags);
-}
-static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
-{
- return kmalloc(size, flags);
-}
#define kmalloc_node_track_caller(size, flags, node) \
kmalloc_track_caller(size, flags)
-#endif
-extern int FASTCALL(kmem_cache_reap(int));
-extern int FASTCALL(kmem_ptr_validate(struct kmem_cache *cachep, void *ptr));
-
-#else /* CONFIG_SLOB */
-
-/* SLOB allocator routines */
-
-void kmem_cache_init(void);
-struct kmem_cache *kmem_cache_create(const char *c, size_t, size_t,
- unsigned long,
- void (*)(void *, struct kmem_cache *, unsigned long),
- void (*)(void *, struct kmem_cache *, unsigned long));
-void kmem_cache_destroy(struct kmem_cache *c);
-void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags);
-void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
-void kmem_cache_free(struct kmem_cache *c, void *b);
-const char *kmem_cache_name(struct kmem_cache *);
-void *kmalloc(size_t size, gfp_t flags);
-void *__kzalloc(size_t size, gfp_t flags);
-void kfree(const void *m);
-unsigned int ksize(const void *m);
-unsigned int kmem_cache_size(struct kmem_cache *c);
-
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-{
- return __kzalloc(n * size, flags);
-}
-
-#define kmem_cache_shrink(d) (0)
-#define kmem_cache_reap(a)
-#define kmem_ptr_validate(a, b) (0)
-#define kmem_cache_alloc_node(c, f, n) kmem_cache_alloc(c, f)
-#define kmalloc_node(s, f, n) kmalloc(s, f)
-#define kzalloc(s, f) __kzalloc(s, f)
-#define kmalloc_track_caller kmalloc
-
-#define kmalloc_node_track_caller kmalloc_node
-
-#endif /* CONFIG_SLOB */
+#endif /* DEBUG_SLAB */
#endif /* __KERNEL__ */
-
#endif /* _LINUX_SLAB_H */
+
--- /dev/null
+#ifndef _LINUX_SLAB_DEF_H
+#define _LINUX_SLAB_DEF_H
+
+/*
+ * Definitions unique to the original Linux SLAB allocator.
+ *
+ * What we provide here is a way to optimize the frequent kmalloc
+ * calls in the kernel by selecting the appropriate general cache
+ * if kmalloc was called with a size that can be established at
+ * compile time.
+ */
+
+#include <linux/init.h>
+#include <asm/page.h> /* kmalloc_sizes.h needs PAGE_SIZE */
+#include <asm/cache.h> /* kmalloc_sizes.h needs L1_CACHE_BYTES */
+#include <linux/compiler.h>
+
+/* Size description struct for general caches. */
+struct cache_sizes {
+ size_t cs_size;
+ struct kmem_cache *cs_cachep;
+ struct kmem_cache *cs_dmacachep;
+};
+extern struct cache_sizes malloc_sizes[];
+
+static inline void *kmalloc(size_t size, gfp_t flags)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+#define CACHE(x) \
+ if (size <= x) \
+ goto found; \
+ else \
+ i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __you_cannot_kmalloc_that_much(void);
+ __you_cannot_kmalloc_that_much();
+ }
+found:
+ return kmem_cache_alloc((flags & GFP_DMA) ?
+ malloc_sizes[i].cs_dmacachep :
+ malloc_sizes[i].cs_cachep, flags);
+ }
+ return __kmalloc(size, flags);
+}
+
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+#define CACHE(x) \
+ if (size <= x) \
+ goto found; \
+ else \
+ i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __you_cannot_kzalloc_that_much(void);
+ __you_cannot_kzalloc_that_much();
+ }
+found:
+ return kmem_cache_zalloc((flags & GFP_DMA) ?
+ malloc_sizes[i].cs_dmacachep :
+ malloc_sizes[i].cs_cachep, flags);
+ }
+ return __kzalloc(size, flags);
+}
+
+#ifdef CONFIG_NUMA
+extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+#define CACHE(x) \
+ if (size <= x) \
+ goto found; \
+ else \
+ i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __you_cannot_kmalloc_that_much(void);
+ __you_cannot_kmalloc_that_much();
+ }
+found:
+ return kmem_cache_alloc_node((flags & GFP_DMA) ?
+ malloc_sizes[i].cs_dmacachep :
+ malloc_sizes[i].cs_cachep, flags, node);
+ }
+ return __kmalloc_node(size, flags, node);
+}
+
+#endif /* CONFIG_NUMA */
+
+#endif /* _LINUX_SLAB_DEF_H */
* generation is incremented.
*/
unsigned int generation;
- pid_t conn_pid;
+ struct pid *conn_pid;
struct smb_conn_opt opt;
wait_queue_head_t conn_wq;
int conn_complete;
#ifdef CONFIG_MAGIC_SYSRQ
+extern int sysrq_on(void);
+
+/*
+ * Do not use this one directly:
+ */
+extern int __sysrq_enabled;
+
/* Generic SysRq interface -- you may call it from any device driver, supplying
* ASCII code of the key, pointer to registers and kbd/tty structs (if they
* are available -- else NULL's).
*/
-void handle_sysrq(int, struct tty_struct *);
-void __handle_sysrq(int, struct tty_struct *, int check_mask);
-int register_sysrq_key(int, struct sysrq_key_op *);
-int unregister_sysrq_key(int, struct sysrq_key_op *);
+void handle_sysrq(int key, struct tty_struct *tty);
+void __handle_sysrq(int key, struct tty_struct *tty, int check_mask);
+int register_sysrq_key(int key, struct sysrq_key_op *op);
+int unregister_sysrq_key(int key, struct sysrq_key_op *op);
struct sysrq_key_op *__sysrq_get_key_op(int key);
#else
+static inline int sysrq_on(void)
+{
+ return 0;
+}
static inline int __reterr(void)
{
return -EINVAL;
}
+static inline void handle_sysrq(int key, struct tty_struct *tty)
+{
+}
#define register_sysrq_key(ig,nore) __reterr()
#define unregister_sysrq_key(ig,nore) __reterr()
struct hci_filter {
unsigned long type_mask;
unsigned long event_mask[2];
- __u16 opcode;
+ __le16 opcode;
};
struct hci_ufilter {
__u32 type_mask;
__u32 event_mask[2];
- __u16 opcode;
+ __le16 opcode;
};
#define HCI_FLT_TYPE_BITS 31
#define BACKPORCH 0x0208
#define VIDEODIMENSIONS 0x020c
#define FBIINIT0 0x0210 /* misc+fifo controls */
-# define EN_VGA_PASSTHROUGH BIT(0)
+# define DIS_VGA_PASSTHROUGH BIT(0)
# define FBI_RESET BIT(1)
# define FIFO_RESET BIT(2)
#define FBIINIT1 0x0214 /* PCI + video controls */
# define DACREG_ICS_CLK1_A 0 /* bit4 */
/* sst default init registers */
-#define FBIINIT0_DEFAULT EN_VGA_PASSTHROUGH
+#define FBIINIT0_DEFAULT DIS_VGA_PASSTHROUGH
#define FBIINIT1_DEFAULT \
( \
*
*/
+/* ioctl to enable/disable VGA passthrough */
+#define SSTFB_SET_VGAPASS _IOW('F', 0xdd, __u32)
+#define SSTFB_GET_VGAPASS _IOR('F', 0xdd, __u32)
+
+
/* used to know witch clock to set */
enum {
VID_CLOCK=0,
};
struct dac_switch {
- char * name;
+ const char *name;
int (*detect) (struct fb_info *info);
int (*set_pll) (struct fb_info *info, const struct pll_timing *t, const int clock);
void (*set_vidmod) (struct fb_info *info, const int bpp);
struct pci_dev *dev;
int type;
u8 revision;
- int gfx_clock; /* status */
+ u8 vgapass; /* VGA pass through: 1=enabled, 0=disabled */
};
#endif /* _SSTFB_H_ */
if (alen > DATALEN_MSG)
alen = DATALEN_MSG;
- msg = (struct msg_msg *)kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
+ msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
if (msg == NULL)
return ERR_PTR(-ENOMEM);
alen = len;
if (alen > DATALEN_SEG)
alen = DATALEN_SEG;
- seg = (struct msg_msgseg *)kmalloc(sizeof(*seg) + alen,
+ seg = kmalloc(sizeof(*seg) + alen,
GFP_KERNEL);
if (seg == NULL) {
err = -ENOMEM;
}
/**
- * cpuset_zone_allowed - Can we allocate memory on zone z's memory node?
+ * cpuset_zone_allowed_softwall - Can we allocate on zone z's memory node?
* @z: is this zone on an allowed node?
- * @gfp_mask: memory allocation flags (we use __GFP_HARDWALL)
+ * @gfp_mask: memory allocation flags
*
- * If we're in interrupt, yes, we can always allocate. If zone
+ * If we're in interrupt, yes, we can always allocate. If
+ * __GFP_THISNODE is set, yes, we can always allocate. If zone
* z's node is in our tasks mems_allowed, yes. If it's not a
* __GFP_HARDWALL request and this zone's nodes is in the nearest
* mem_exclusive cpuset ancestor to this tasks cpuset, yes.
* Otherwise, no.
*
+ * If __GFP_HARDWALL is set, cpuset_zone_allowed_softwall()
+ * reduces to cpuset_zone_allowed_hardwall(). Otherwise,
+ * cpuset_zone_allowed_softwall() might sleep, and might allow a zone
+ * from an enclosing cpuset.
+ *
+ * cpuset_zone_allowed_hardwall() only handles the simpler case of
+ * hardwall cpusets, and never sleeps.
+ *
+ * The __GFP_THISNODE placement logic is really handled elsewhere,
+ * by forcibly using a zonelist starting at a specified node, and by
+ * (in get_page_from_freelist()) refusing to consider the zones for
+ * any node on the zonelist except the first. By the time any such
+ * calls get to this routine, we should just shut up and say 'yes'.
+ *
* GFP_USER allocations are marked with the __GFP_HARDWALL bit,
* and do not allow allocations outside the current tasks cpuset.
* GFP_KERNEL allocations are not so marked, so can escape to the
- * nearest mem_exclusive ancestor cpuset.
+ * nearest enclosing mem_exclusive ancestor cpuset.
*
- * Scanning up parent cpusets requires callback_mutex. The __alloc_pages()
- * routine only calls here with __GFP_HARDWALL bit _not_ set if
- * it's a GFP_KERNEL allocation, and all nodes in the current tasks
- * mems_allowed came up empty on the first pass over the zonelist.
- * So only GFP_KERNEL allocations, if all nodes in the cpuset are
- * short of memory, might require taking the callback_mutex mutex.
+ * Scanning up parent cpusets requires callback_mutex. The
+ * __alloc_pages() routine only calls here with __GFP_HARDWALL bit
+ * _not_ set if it's a GFP_KERNEL allocation, and all nodes in the
+ * current tasks mems_allowed came up empty on the first pass over
+ * the zonelist. So only GFP_KERNEL allocations, if all nodes in the
+ * cpuset are short of memory, might require taking the callback_mutex
+ * mutex.
*
* The first call here from mm/page_alloc:get_page_from_freelist()
- * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets, so
- * no allocation on a node outside the cpuset is allowed (unless in
- * interrupt, of course).
+ * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets,
+ * so no allocation on a node outside the cpuset is allowed (unless
+ * in interrupt, of course).
*
* The second pass through get_page_from_freelist() doesn't even call
* here for GFP_ATOMIC calls. For those calls, the __alloc_pages()
* GFP_USER - only nodes in current tasks mems allowed ok.
*
* Rule:
- * Don't call cpuset_zone_allowed() if you can't sleep, unless you
+ * Don't call cpuset_zone_allowed_softwall if you can't sleep, unless you
* pass in the __GFP_HARDWALL flag set in gfp_flag, which disables
* the code that might scan up ancestor cpusets and sleep.
- **/
+ */
-int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
{
int node; /* node that zone z is on */
const struct cpuset *cs; /* current cpuset ancestors */
return allowed;
}
+/*
+ * cpuset_zone_allowed_hardwall - Can we allocate on zone z's memory node?
+ * @z: is this zone on an allowed node?
+ * @gfp_mask: memory allocation flags
+ *
+ * If we're in interrupt, yes, we can always allocate.
+ * If __GFP_THISNODE is set, yes, we can always allocate. If zone
+ * z's node is in our tasks mems_allowed, yes. Otherwise, no.
+ *
+ * The __GFP_THISNODE placement logic is really handled elsewhere,
+ * by forcibly using a zonelist starting at a specified node, and by
+ * (in get_page_from_freelist()) refusing to consider the zones for
+ * any node on the zonelist except the first. By the time any such
+ * calls get to this routine, we should just shut up and say 'yes'.
+ *
+ * Unlike the cpuset_zone_allowed_softwall() variant, above,
+ * this variant requires that the zone be in the current tasks
+ * mems_allowed or that we're in interrupt. It does not scan up the
+ * cpuset hierarchy for the nearest enclosing mem_exclusive cpuset.
+ * It never sleeps.
+ */
+
+int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
+{
+ int node; /* node that zone z is on */
+
+ if (in_interrupt() || (gfp_mask & __GFP_THISNODE))
+ return 1;
+ node = zone_to_nid(z);
+ if (node_isset(node, current->mems_allowed))
+ return 1;
+ return 0;
+}
+
/**
* cpuset_lock - lock out any changes to cpuset structures
*
struct mempolicy *pol;
down_write(&oldmm->mmap_sem);
- flush_cache_mm(oldmm);
+ flush_cache_dup_mm(oldmm);
/*
* Not linked in yet - no deadlock potential:
*/
#include "lockdep_internals.h"
/*
- * hash_lock: protects the lockdep hashes and class/list/hash allocators.
+ * lockdep_lock: protects the lockdep graph, the hashes and the
+ * class/list/hash allocators.
*
* This is one of the rare exceptions where it's justified
* to use a raw spinlock - we really dont want the spinlock
- * code to recurse back into the lockdep code.
+ * code to recurse back into the lockdep code...
*/
-static raw_spinlock_t hash_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+static raw_spinlock_t lockdep_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+
+static int graph_lock(void)
+{
+ __raw_spin_lock(&lockdep_lock);
+ /*
+ * Make sure that if another CPU detected a bug while
+ * walking the graph we dont change it (while the other
+ * CPU is busy printing out stuff with the graph lock
+ * dropped already)
+ */
+ if (!debug_locks) {
+ __raw_spin_unlock(&lockdep_lock);
+ return 0;
+ }
+ return 1;
+}
+
+static inline int graph_unlock(void)
+{
+ __raw_spin_unlock(&lockdep_lock);
+ return 0;
+}
+
+/*
+ * Turn lock debugging off and return with 0 if it was off already,
+ * and also release the graph lock:
+ */
+static inline int debug_locks_off_graph_unlock(void)
+{
+ int ret = debug_locks_off();
+
+ __raw_spin_unlock(&lockdep_lock);
+
+ return ret;
+}
static int lockdep_initialized;
static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
/*
- * Allocate a lockdep entry. (assumes hash_lock held, returns
+ * Allocate a lockdep entry. (assumes the graph_lock held, returns
* with NULL on failure)
*/
static struct lock_list *alloc_list_entry(void)
{
if (nr_list_entries >= MAX_LOCKDEP_ENTRIES) {
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
+ if (!debug_locks_off_graph_unlock())
+ return NULL;
+
printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n");
printk("turning off the locking correctness validator.\n");
return NULL;
*/
#define VERBOSE 0
-#ifdef VERBOSE
-# define VERY_VERBOSE 0
-#endif
+#define VERY_VERBOSE 0
#if VERBOSE
# define HARDIRQ_VERBOSE 1
!strcmp(class->name, "&struct->lockfield"))
return 1;
#endif
- /* Allow everything else. 0 would be filter everything else */
- return 1;
+ /* Filter everything else. 1 would be to allow everything else */
+ return 0;
}
#endif
/*
* Stack-trace: tightly packed array of stack backtrace
- * addresses. Protected by the hash_lock.
+ * addresses. Protected by the graph_lock.
*/
unsigned long nr_stack_trace_entries;
static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
trace->max_entries = trace->nr_entries;
nr_stack_trace_entries += trace->nr_entries;
- if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) {
- __raw_spin_unlock(&hash_lock);
- return 0;
- }
if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) {
- __raw_spin_unlock(&hash_lock);
- if (debug_locks_off()) {
- printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
- printk("turning off the locking correctness validator.\n");
- dump_stack();
- }
+ if (!debug_locks_off_graph_unlock())
+ return 0;
+
+ printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
+ printk("turning off the locking correctness validator.\n");
+ dump_stack();
+
return 0;
}
{
struct task_struct *curr = current;
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n=======================================================\n");
if (debug_locks_silent)
return 0;
- /* hash_lock unlocked by the header */
- __raw_spin_lock(&hash_lock);
this.class = check_source->class;
if (!save_trace(&this.trace))
return 0;
- __raw_spin_unlock(&hash_lock);
+
print_circular_bug_entry(&this, 0);
printk("\nother info that might help us debug this:\n\n");
static int noinline print_infinite_recursion_bug(void)
{
- __raw_spin_unlock(&hash_lock);
- DEBUG_LOCKS_WARN_ON(1);
+ if (!debug_locks_off_graph_unlock())
+ return 0;
+
+ WARN_ON(1);
return 0;
}
enum lock_usage_bit bit2,
const char *irqclass)
{
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n======================================================\n");
print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
struct held_lock *next)
{
- debug_locks_off();
- __raw_spin_unlock(&hash_lock);
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n=============================================\n");
* Debugging printouts:
*/
if (verbose(prev->class) || verbose(next->class)) {
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
printk("\n new dependency: ");
print_lock_name(prev->class);
printk(" => ");
print_lock_name(next->class);
printk("\n");
dump_stack();
- __raw_spin_lock(&hash_lock);
+ return graph_lock();
}
return 1;
}
}
return 1;
out_bug:
- __raw_spin_unlock(&hash_lock);
- DEBUG_LOCKS_WARN_ON(1);
+ if (!debug_locks_off_graph_unlock())
+ return 0;
+
+ WARN_ON(1);
return 0;
}
hash_head = classhashentry(key);
raw_local_irq_save(flags);
- __raw_spin_lock(&hash_lock);
+ if (!graph_lock()) {
+ raw_local_irq_restore(flags);
+ return NULL;
+ }
/*
* We have to do the hash-walk again, to avoid races
* with another CPU:
* the hash:
*/
if (nr_lock_classes >= MAX_LOCKDEP_KEYS) {
- __raw_spin_unlock(&hash_lock);
+ if (!debug_locks_off_graph_unlock()) {
+ raw_local_irq_restore(flags);
+ return NULL;
+ }
raw_local_irq_restore(flags);
- debug_locks_off();
+
printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
printk("turning off the locking correctness validator.\n");
return NULL;
list_add_tail_rcu(&class->hash_entry, hash_head);
if (verbose(class)) {
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
raw_local_irq_restore(flags);
+
printk("\nnew class %p: %s", class->key, class->name);
if (class->name_version > 1)
printk("#%d", class->name_version);
printk("\n");
dump_stack();
+
raw_local_irq_save(flags);
- __raw_spin_lock(&hash_lock);
+ if (!graph_lock()) {
+ raw_local_irq_restore(flags);
+ return NULL;
+ }
}
out_unlock_set:
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
raw_local_irq_restore(flags);
if (!subclass || force)
* add it and return 0 - in this case the new dependency chain is
* validated. If the key is already hashed, return 1.
*/
-static inline int lookup_chain_cache(u64 chain_key)
+static inline int lookup_chain_cache(u64 chain_key, struct lock_class *class)
{
struct list_head *hash_head = chainhashentry(chain_key);
struct lock_chain *chain;
if (chain->chain_key == chain_key) {
cache_hit:
debug_atomic_inc(&chain_lookup_hits);
- /*
- * In the debugging case, force redundant checking
- * by returning 1:
- */
-#ifdef CONFIG_DEBUG_LOCKDEP
- __raw_spin_lock(&hash_lock);
- return 1;
-#endif
+ if (very_verbose(class))
+ printk("\nhash chain already cached, key: %016Lx tail class: [%p] %s\n", chain_key, class->key, class->name);
return 0;
}
}
+ if (very_verbose(class))
+ printk("\nnew hash chain, key: %016Lx tail class: [%p] %s\n", chain_key, class->key, class->name);
/*
* Allocate a new chain entry from the static array, and add
* it to the hash:
*/
- __raw_spin_lock(&hash_lock);
+ if (!graph_lock())
+ return 0;
/*
* We have to walk the chain again locked - to avoid duplicates:
*/
list_for_each_entry(chain, hash_head, entry) {
if (chain->chain_key == chain_key) {
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
goto cache_hit;
}
}
if (unlikely(nr_lock_chains >= MAX_LOCKDEP_CHAINS)) {
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
+ if (!debug_locks_off_graph_unlock())
+ return 0;
+
printk("BUG: MAX_LOCKDEP_CHAINS too low!\n");
printk("turning off the locking correctness validator.\n");
return 0;
struct held_lock *this, int forwards,
const char *irqclass)
{
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n=========================================================\n");
return print_irq_inversion_bug(curr, backwards_match, this, 0, irqclass);
}
-static inline void print_irqtrace_events(struct task_struct *curr)
+void print_irqtrace_events(struct task_struct *curr)
{
printk("irq event stamp: %u\n", curr->irq_events);
printk("hardirqs last enabled at (%u): ", curr->hardirq_enable_event);
print_ip_sym(curr->softirq_disable_ip);
}
-#else
-static inline void print_irqtrace_events(struct task_struct *curr)
-{
-}
#endif
static int
print_usage_bug(struct task_struct *curr, struct held_lock *this,
enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit)
{
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n=================================\n");
if (likely(this->class->usage_mask & new_mask))
return 1;
- __raw_spin_lock(&hash_lock);
+ if (!graph_lock())
+ return 0;
/*
* Make sure we didnt race:
*/
if (unlikely(this->class->usage_mask & new_mask)) {
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
return 1;
}
debug_atomic_dec(&nr_unused_locks);
break;
default:
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
+ if (!debug_locks_off_graph_unlock())
+ return 0;
WARN_ON(1);
return 0;
}
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
/*
- * We must printk outside of the hash_lock:
+ * We must printk outside of the graph_lock:
*/
if (ret == 2) {
printk("\nmarked lock as {%s}:\n", usage_str[new_bit]);
* We look up the chain_key and do the O(N^2) check and update of
* the dependencies only if this is a new dependency chain.
* (If lookup_chain_cache() returns with 1 it acquires
- * hash_lock for us)
+ * graph_lock for us)
*/
- if (!trylock && (check == 2) && lookup_chain_cache(chain_key)) {
+ if (!trylock && (check == 2) && lookup_chain_cache(chain_key, class)) {
/*
* Check whether last held lock:
*
if (!chain_head && ret != 2)
if (!check_prevs_add(curr, hlock))
return 0;
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
}
curr->lockdep_depth++;
check_chain_key(curr);
void lockdep_reset(void)
{
unsigned long flags;
+ int i;
raw_local_irq_save(flags);
current->curr_chain_key = 0;
nr_softirq_chains = 0;
nr_process_chains = 0;
debug_locks = 1;
+ for (i = 0; i < CHAINHASH_SIZE; i++)
+ INIT_LIST_HEAD(chainhash_table + i);
raw_local_irq_restore(flags);
}
int i;
raw_local_irq_save(flags);
- __raw_spin_lock(&hash_lock);
+ graph_lock();
/*
* Unhash all classes that were created by this module:
zap_class(class);
}
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
raw_local_irq_restore(flags);
}
* Debug check: in the end all mapped classes should
* be gone.
*/
- __raw_spin_lock(&hash_lock);
+ graph_lock();
for (i = 0; i < CLASSHASH_SIZE; i++) {
head = classhash_table + i;
if (list_empty(head))
continue;
list_for_each_entry_safe(class, next, head, hash_entry) {
if (unlikely(class == lock->class_cache)) {
- __raw_spin_unlock(&hash_lock);
- DEBUG_LOCKS_WARN_ON(1);
+ if (debug_locks_off_graph_unlock())
+ WARN_ON(1);
goto out_restore;
}
}
}
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
out_restore:
raw_local_irq_restore(flags);
}
#endif /* CONFIG_MODULE_UNLOAD */
+static ssize_t show_initstate(struct module_attribute *mattr,
+ struct module *mod, char *buffer)
+{
+ const char *state = "unknown";
+
+ switch (mod->state) {
+ case MODULE_STATE_LIVE:
+ state = "live";
+ break;
+ case MODULE_STATE_COMING:
+ state = "coming";
+ break;
+ case MODULE_STATE_GOING:
+ state = "going";
+ break;
+ }
+ return sprintf(buffer, "%s\n", state);
+}
+
+static struct module_attribute initstate = {
+ .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
+ .show = show_initstate,
+};
+
static struct module_attribute *modinfo_attrs[] = {
&modinfo_version,
&modinfo_srcversion,
+ &initstate,
#ifdef CONFIG_MODULE_UNLOAD
&refcnt,
#endif
struct nsproxy *ns;
ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
- if (ns) {
+ if (ns)
atomic_set(&ns->count, 1);
- ns->id = -1;
- }
return ns;
}
sending the processor to sleep and saving power.
config PM_LEGACY
- bool "Legacy Power Management API"
+ bool "Legacy Power Management API (DEPRECATED)"
depends on PM
- default y
+ default n
---help---
- Support for pm_register() and friends.
+ Support for pm_register() and friends. This old API is obsoleted
+ by the driver model.
- If unsure, say Y.
+ If unsure, say N.
config PM_DEBUG
bool "Power Management Debug Support"
if ((p == current) ||
(p->flags & PF_NOFREEZE) ||
(p->exit_state == EXIT_ZOMBIE) ||
- (p->exit_state == EXIT_DEAD) ||
- (p->state == TASK_STOPPED))
+ (p->exit_state == EXIT_DEAD))
return 0;
return 1;
}
unsigned long flags;
if (!freezing(p)) {
- freeze(p);
- spin_lock_irqsave(&p->sighand->siglock, flags);
- signal_wake_up(p, 0);
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ rmb();
+ if (!frozen(p)) {
+ if (p->state == TASK_STOPPED)
+ force_sig_specific(SIGSTOP, p);
+
+ freeze(p);
+ spin_lock_irqsave(&p->sighand->siglock, flags);
+ signal_wake_up(p, p->state == TASK_STOPPED);
+ spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ }
}
}
if (frozen(p))
continue;
- if (p->state == TASK_TRACED &&
- (frozen(p->parent) ||
- p->parent->state == TASK_STOPPED)) {
+ if (p->state == TASK_TRACED && frozen(p->parent)) {
cancel_freezing(p);
continue;
}
*/
struct rchan_buf *relay_create_buf(struct rchan *chan)
{
- struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
+ struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
if (!buf)
return NULL;
if (!(subbuf_size && n_subbufs))
return NULL;
- chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL);
+ chan = kzalloc(sizeof(struct rchan), GFP_KERNEL);
if (!chan)
return NULL;
"%s/0x%08x/%d\n",
current->comm, preempt_count(), current->pid);
debug_show_held_locks(current);
+ if (irqs_disabled())
+ print_irqtrace_events(current);
dump_stack();
}
profile_hit(SCHED_PROFILING, __builtin_return_address(0));
printk("in_atomic():%d, irqs_disabled():%d\n",
in_atomic(), irqs_disabled());
debug_show_held_locks(current);
+ if (irqs_disabled())
+ print_irqtrace_events(current);
dump_stack();
}
#endif
read_unlock(&tasklist_lock);
}
- schedule();
+ do {
+ schedule();
+ } while (try_to_freeze());
/*
* Now we don't run again until continued.
*/
extern int sysctl_overcommit_ratio;
extern int sysctl_panic_on_oom;
extern int max_threads;
-extern int sysrq_enabled;
extern int core_uses_pid;
extern int suid_dumpable;
extern char core_pattern[];
{
.ctl_name = KERN_SYSRQ,
.procname = "sysrq",
- .data = &sysrq_enabled,
+ .data = &__sysrq_enabled,
.maxlen = sizeof (int),
.mode = 0644,
.proc_handler = &proc_dointvec,
unsigned long active_tasks; /* fixed-point */
static int count = LOAD_FREQ;
- active_tasks = count_active_tasks();
- for (count -= ticks; count < 0; count += LOAD_FREQ) {
- CALC_LOAD(avenrun[0], EXP_1, active_tasks);
- CALC_LOAD(avenrun[1], EXP_5, active_tasks);
- CALC_LOAD(avenrun[2], EXP_15, active_tasks);
+ count -= ticks;
+ if (unlikely(count < 0)) {
+ active_tasks = count_active_tasks();
+ do {
+ CALC_LOAD(avenrun[0], EXP_1, active_tasks);
+ CALC_LOAD(avenrun[1], EXP_5, active_tasks);
+ CALC_LOAD(avenrun[2], EXP_15, active_tasks);
+ count += LOAD_FREQ;
+ } while (count < 0);
}
}
config PLIST
boolean
+config IOMAP_COPY
+ boolean
+ depends on !UML
+ default y
+
endmenu
lib-y := ctype.o string.o vsprintf.o cmdline.o \
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
- sha1.o irq_regs.o
+ sha1.o irq_regs.o reciprocal_div.o
lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
lib-y += kobject.o kref.o kobject_uevent.o klist.o
-obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o random32.o
+obj-y += sort.o parser.o halfmd4.o debug_locks.o random32.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
CFLAGS_kobject_uevent.o += -DDEBUG
endif
+obj-$(CONFIG_IOMAP_COPY) += iomap_copy.o
obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
*
* (C) Copyright 1995 1996 Linus Torvalds
*/
-#include <linux/io.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
--- /dev/null
+#include <asm/div64.h>
+#include <linux/reciprocal_div.h>
+
+u32 reciprocal_value(u32 k)
+{
+ u64 val = (1LL << 32) + (k - 1);
+ do_div(val, k);
+ return (u32)val;
+}
}
static void copy_huge_page(struct page *dst, struct page *src,
- unsigned long addr)
+ unsigned long addr, struct vm_area_struct *vma)
{
int i;
might_sleep();
for (i = 0; i < HPAGE_SIZE/PAGE_SIZE; i++) {
cond_resched();
- copy_user_highpage(dst + i, src + i, addr + i*PAGE_SIZE);
+ copy_user_highpage(dst + i, src + i, addr + i*PAGE_SIZE, vma);
}
}
for (z = zonelist->zones; *z; z++) {
nid = zone_to_nid(*z);
- if (cpuset_zone_allowed(*z, GFP_HIGHUSER) &&
+ if (cpuset_zone_allowed_softwall(*z, GFP_HIGHUSER) &&
!list_empty(&hugepage_freelists[nid]))
break;
}
}
spin_unlock(&mm->page_table_lock);
- copy_huge_page(new_page, old_page, address);
+ copy_huge_page(new_page, old_page, address, vma);
spin_lock(&mm->page_table_lock);
ptep = huge_pte_offset(mm, address & HPAGE_MASK);
return pte;
}
-static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va)
+static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma)
{
/*
* If the source page was a PFN mapping, we don't have
kunmap_atomic(kaddr, KM_USER0);
flush_dcache_page(dst);
return;
-
+
}
- copy_user_highpage(dst, src, va);
+ copy_user_highpage(dst, src, va, vma);
}
/*
new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
if (!new_page)
goto oom;
- cow_user_page(new_page, old_page, address);
+ cow_user_page(new_page, old_page, address, vma);
}
/*
page = alloc_page_vma(GFP_HIGHUSER, vma, address);
if (!page)
goto oom;
- copy_user_highpage(page, new_page, address);
+ copy_user_highpage(page, new_page, address, vma);
page_cache_release(new_page);
new_page = page;
anon = 1;
nodemask_t nodes = node_online_map;
for (z = zonelist->zones; *z; z++)
- if (cpuset_zone_allowed(*z, gfp_mask))
+ if (cpuset_zone_allowed_softwall(*z, gfp_mask))
node_clear(zone_to_nid(*z), nodes);
else
return CONSTRAINT_CPUSET;
zone->zone_pgdat != zonelist->zones[0]->zone_pgdat))
break;
if ((alloc_flags & ALLOC_CPUSET) &&
- !cpuset_zone_allowed(zone, gfp_mask))
+ !cpuset_zone_allowed_softwall(zone, gfp_mask))
goto try_next_zone;
if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {
#include <linux/mutex.h>
#include <linux/fault-inject.h>
#include <linux/rtmutex.h>
+#include <linux/reciprocal_div.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
unsigned int shared;
unsigned int buffer_size;
+ u32 reciprocal_buffer_size;
/* 3) touched by every alloc & free from the backend */
struct kmem_list3 *nodelists[MAX_NUMNODES];
return slab->s_mem + cache->buffer_size * idx;
}
-static inline unsigned int obj_to_index(struct kmem_cache *cache,
- struct slab *slab, void *obj)
+/*
+ * We want to avoid an expensive divide : (offset / cache->buffer_size)
+ * Using the fact that buffer_size is a constant for a particular cache,
+ * we can replace (offset / cache->buffer_size) by
+ * reciprocal_divide(offset, cache->reciprocal_buffer_size)
+ */
+static inline unsigned int obj_to_index(const struct kmem_cache *cache,
+ const struct slab *slab, void *obj)
{
- return (unsigned)(obj - slab->s_mem) / cache->buffer_size;
+ u32 offset = (obj - slab->s_mem);
+ return reciprocal_divide(offset, cache->reciprocal_buffer_size);
}
/*
cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,
cache_line_size());
+ cache_cache.reciprocal_buffer_size =
+ reciprocal_value(cache_cache.buffer_size);
for (order = 0; order < MAX_ORDER; order++) {
cache_estimate(order, cache_cache.buffer_size,
if (flags & SLAB_CACHE_DMA)
cachep->gfpflags |= GFP_DMA;
cachep->buffer_size = size;
+ cachep->reciprocal_buffer_size = reciprocal_value(size);
if (flags & CFLGS_OFF_SLAB) {
cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
struct zone **z;
void *obj = NULL;
int nid;
+ gfp_t local_flags = (flags & GFP_LEVEL_MASK);
retry:
/*
for (z = zonelist->zones; *z && !obj; z++) {
nid = zone_to_nid(*z);
- if (cpuset_zone_allowed(*z, flags | __GFP_HARDWALL) &&
+ if (cpuset_zone_allowed_hardwall(*z, flags) &&
cache->nodelists[nid] &&
cache->nodelists[nid]->free_objects)
obj = ____cache_alloc_node(cache,
* We may trigger various forms of reclaim on the allowed
* set and go into memory reserves if necessary.
*/
+ if (local_flags & __GFP_WAIT)
+ local_irq_enable();
+ kmem_flagcheck(cache, flags);
obj = kmem_getpages(cache, flags, -1);
+ if (local_flags & __GFP_WAIT)
+ local_irq_disable();
if (obj) {
/*
* Insert into the appropriate per node queues
*
* Currently only used for dentry validation.
*/
-int fastcall kmem_ptr_validate(struct kmem_cache *cachep, void *ptr)
+int fastcall kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr)
{
unsigned long addr = (unsigned long)ptr;
unsigned long min_addr = PAGE_OFFSET;
return order;
}
-void *kmalloc(size_t size, gfp_t gfp)
+void *__kmalloc(size_t size, gfp_t gfp)
{
slob_t *m;
bigblock_t *bb;
slob_free(bb, sizeof(bigblock_t));
return 0;
}
-
-EXPORT_SYMBOL(kmalloc);
+EXPORT_SYMBOL(__kmalloc);
void kfree(const void *block)
{
static struct timer_list slob_timer = TIMER_INITIALIZER(
(void (*)(unsigned long))kmem_cache_init, 0, 0);
+int kmem_cache_shrink(struct kmem_cache *d)
+{
+ return 0;
+}
+EXPORT_SYMBOL(kmem_cache_shrink);
+
+int kmem_ptr_validate(struct kmem_cache *a, const void *b)
+{
+ return 0;
+}
+
void kmem_cache_init(void)
{
void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
if (!populated_zone(zone))
continue;
- if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
continue;
note_zone_scanning_priority(zone, priority);
for (i = 0; zones[i] != NULL; i++) {
struct zone *zone = zones[i];
- if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
continue;
lru_pages += zone->nr_active + zone->nr_inactive;
for (i = 0; zones[i] != 0; i++) {
struct zone *zone = zones[i];
- if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
continue;
zone->prev_priority = priority;
return;
if (pgdat->kswapd_max_order < order)
pgdat->kswapd_max_order = order;
- if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
return;
if (!waitqueue_active(&pgdat->kswapd_wait))
return;
if (flt->opcode &&
((evt == HCI_EV_CMD_COMPLETE &&
flt->opcode !=
- get_unaligned((__u16 *)(skb->data + 3))) ||
+ get_unaligned((__le16 *)(skb->data + 3))) ||
(evt == HCI_EV_CMD_STATUS &&
flt->opcode !=
- get_unaligned((__u16 *)(skb->data + 4)))))
+ get_unaligned((__le16 *)(skb->data + 4)))))
continue;
}
integ_len = svc_getnl(&buf->head[0]);
if (integ_len & 3)
- goto out;
+ return stat;
if (integ_len > buf->len)
- goto out;
+ return stat;
if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len))
BUG();
/* copy out mic... */
if (read_u32_from_xdr_buf(buf, integ_len, &mic.len))
BUG();
if (mic.len > RPC_MAX_AUTH_SIZE)
- goto out;
+ return stat;
mic.data = kmalloc(mic.len, GFP_KERNEL);
if (!mic.data)
- goto out;
+ return stat;
if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
goto out;
maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
goto out;
stat = 0;
out:
+ kfree(mic.data);
return stat;
}
}
switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
case -EAGAIN:
- goto drop;
+ case -ETIMEDOUT:
case -ENOENT:
goto drop;
case 0:
#define RPCDBG_FACILITY RPCDBG_CACHE
-static void cache_defer_req(struct cache_req *req, struct cache_head *item);
+static int cache_defer_req(struct cache_req *req, struct cache_head *item);
static void cache_revisit_request(struct cache_head *item);
static void cache_init(struct cache_head *h)
*
* Returns 0 if the cache_head can be used, or cache_puts it and returns
* -EAGAIN if upcall is pending,
+ * -ETIMEDOUT if upcall failed and should be retried,
* -ENOENT if cache entry was negative
*/
int cache_check(struct cache_detail *detail,
}
if (rv == -EAGAIN)
- cache_defer_req(rqstp, h);
+ if (cache_defer_req(rqstp, h) != 0)
+ rv = -ETIMEDOUT;
if (rv)
cache_put(h, detail);
static struct list_head cache_defer_hash[DFR_HASHSIZE];
static int cache_defer_cnt;
-static void cache_defer_req(struct cache_req *req, struct cache_head *item)
+static int cache_defer_req(struct cache_req *req, struct cache_head *item)
{
struct cache_deferred_req *dreq;
int hash = DFR_HASH(item);
+ if (cache_defer_cnt >= DFR_MAX) {
+ /* too much in the cache, randomly drop this one,
+ * or continue and drop the oldest below
+ */
+ if (net_random()&1)
+ return -ETIMEDOUT;
+ }
dreq = req->defer(req);
if (dreq == NULL)
- return;
+ return -ETIMEDOUT;
dreq->item = item;
dreq->recv_time = get_seconds();
/* it is in, now maybe clean up */
dreq = NULL;
if (++cache_defer_cnt > DFR_MAX) {
- /* too much in the cache, randomly drop
- * first or last
- */
- if (net_random()&1)
- dreq = list_entry(cache_defer_list.next,
- struct cache_deferred_req,
- recent);
- else
- dreq = list_entry(cache_defer_list.prev,
- struct cache_deferred_req,
- recent);
+ dreq = list_entry(cache_defer_list.prev,
+ struct cache_deferred_req, recent);
list_del(&dreq->recent);
list_del(&dreq->hash);
cache_defer_cnt--;
/* must have just been validated... */
cache_revisit_request(item);
}
+ return 0;
}
static void cache_revisit_request(struct cache_head *item)
serv->sv_nrpools = npools;
serv->sv_pools =
- kcalloc(sizeof(struct svc_pool), serv->sv_nrpools,
+ kcalloc(serv->sv_nrpools, sizeof(struct svc_pool),
GFP_KERNEL);
if (!serv->sv_pools) {
kfree(serv);
return NULL;
kref_init(&new->h.ref);
new->h.name = kstrdup(name, GFP_KERNEL);
+ if (new->h.name == NULL) {
+ kfree(new);
+ return NULL;
+ }
new->h.flavour = &svcauth_unix;
new->addr_changes = 0;
rv = auth_domain_lookup(name, &new->h);
default:
BUG();
case -EAGAIN:
+ case -ETIMEDOUT:
return SVC_DROP;
case -ENOENT:
return SVC_DENIED;
if (mng.link_subscriptions > 64)
break;
- sub = (struct subscr_data *)kmalloc(sizeof(*sub),
+ sub = kmalloc(sizeof(*sub),
GFP_ATOMIC);
if (sub == NULL) {
warn("Memory squeeze; dropped remote link subscription\n");
input_mode = ask_silent;
valid_stdin = 1;
}
- } else if (sym_change_count) {
+ } else if (conf_get_changed()) {
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
in = zconf_fopen(name);
if (in)
goto load;
- sym_change_count++;
+ sym_add_change_count(1);
if (!sym_defconfig_list)
return 1;
struct expr *e;
int i, flags;
- sym_change_count = 0;
+ sym_set_change_count(0);
if (conf_read_simple(name, S_DEF_USER))
return 1;
sym->flags &= flags | ~SYMBOL_DEF_USER;
}
- sym_change_count += conf_warnings || conf_unsaved;
+ sym_add_change_count(conf_warnings || conf_unsaved);
return 0;
}
use_timestamp ? "# " : "",
use_timestamp ? ctime(&now) : "");
- if (!sym_change_count)
+ if (!conf_get_changed())
sym_clear_all_valid();
menu = rootmenu.list;
"# configuration written to %s\n"
"#\n"), newname);
- sym_change_count = 0;
+ sym_set_change_count(0);
return 0;
}
return 0;
}
+
+static int sym_change_count;
+static void (*conf_changed_callback)(void);
+
+void sym_set_change_count(int count)
+{
+ int _sym_change_count = sym_change_count;
+ sym_change_count = count;
+ if (conf_changed_callback &&
+ (bool)_sym_change_count != (bool)count)
+ conf_changed_callback();
+}
+
+void sym_add_change_count(int count)
+{
+ sym_set_change_count(count + sym_change_count);
+}
+
+bool conf_get_changed(void)
+{
+ return sym_change_count;
+}
+
+void conf_set_changed_callback(void (*fn)(void))
+{
+ conf_changed_callback = fn;
+}
static gboolean show_debug = FALSE;
static gboolean resizeable = FALSE;
-static gboolean config_changed = FALSE;
-
static char nohelp_text[] =
N_("Sorry, no help available for this option yet.\n");
GtkWidget *hpaned = NULL;
GtkWidget *vpaned = NULL;
GtkWidget *back_btn = NULL;
+GtkWidget *save_btn = NULL;
+GtkWidget *save_menu_item = NULL;
GtkTextTag *tag1, *tag2;
GdkColor color;
static void update_tree(struct menu *src, GtkTreeIter * dst);
static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
static gchar **fill_row(struct menu *menu);
-
+static void conf_changed(void);
/* Helping/Debugging Functions */
gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
show_value);
+ save_btn = glade_xml_get_widget(xml, "button3");
+ save_menu_item = glade_xml_get_widget(xml, "save1");
+ conf_set_changed_callback(conf_changed);
+
style = gtk_widget_get_style(main_wnd);
widget = glade_xml_get_widget(xml, "toolbar1");
/* Main Windows Callbacks */
-void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data);
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
gpointer user_data)
{
GtkWidget *dialog, *label;
gint result;
- if (config_changed == FALSE)
+ if (!conf_get_changed())
return FALSE;
dialog = gtk_dialog_new_with_buttons(_("Warning !"),
result = gtk_dialog_run(GTK_DIALOG(dialog));
switch (result) {
case GTK_RESPONSE_YES:
- on_save1_activate(NULL, NULL);
+ on_save_activate(NULL, NULL);
return FALSE;
case GTK_RESPONSE_NO:
return FALSE;
}
-void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data)
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
{
if (conf_write(NULL))
text_insert_msg(_("Error"), _("Unable to save configuration !"));
-
- config_changed = FALSE;
}
}
-void on_save_clicked(GtkButton * button, gpointer user_data)
-{
- on_save1_activate(NULL, user_data);
-}
-
-
void on_single_clicked(GtkButton * button, gpointer user_data)
{
view_mode = SINGLE_VIEW;
sym_set_string_value(sym, new_def);
- config_changed = TRUE;
update_tree(&rootmenu, NULL);
gtk_tree_path_free(path);
if (!sym_tristate_within_range(sym, newval))
newval = yes;
sym_set_tristate_value(sym, newval);
- config_changed = TRUE;
if (view_mode == FULL_VIEW)
update_tree(&rootmenu, NULL);
else if (view_mode == SPLIT_VIEW) {
return 0;
}
+
+static void conf_changed(void)
+{
+ bool changed = conf_get_changed();
+ gtk_widget_set_sensitive(save_btn, changed);
+ gtk_widget_set_sensitive(save_menu_item, changed);
+}
<property name="tooltip" translatable="yes">Save the config in .config</property>
<property name="label" translatable="yes">_Save</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_save1_activate"/>
+ <signal name="activate" handler="on_save_activate"/>
<accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_save_clicked"/>
+ <signal name="clicked" handler="on_save_activate"/>
</widget>
<packing>
<property name="expand">False</property>
/* confdata.c */
char *conf_get_default_confname(void);
+void sym_set_change_count(int count);
+void sym_add_change_count(int count);
/* kconfig_load.c */
void kconfig_load(void);
P(conf_read_simple,int,(const char *name, int));
P(conf_write,int,(const char *name));
P(conf_write_autoconf,int,(void));
+P(conf_get_changed,bool,(void));
+P(conf_set_changed_callback, void,(void (*fn)(void)));
/* menu.c */
P(rootmenu,struct menu,);
/* symbol.c */
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
-P(sym_change_count,int,);
P(sym_lookup,struct symbol *,(const char *name, int isconst));
P(sym_find,struct symbol *,(const char *name));
do {
conf(&rootmenu);
dialog_clear();
- res = dialog_yesno(NULL,
- _("Do you wish to save your "
- "new kernel configuration?\n"
- "<ESC><ESC> to continue."),
- 6, 60);
+ if (conf_get_changed())
+ res = dialog_yesno(NULL,
+ _("Do you wish to save your "
+ "new kernel configuration?\n"
+ "<ESC><ESC> to continue."),
+ 6, 60);
+ else
+ res = -1;
} while (res == KEY_ESC);
end_dialog();
- if (res == 0) {
+
+ switch (res) {
+ case 0:
if (conf_write(NULL)) {
fprintf(stderr, _("\n\n"
"Error during writing of the kernel configuration.\n"
"\n\n"));
return 1;
}
+ case -1:
printf(_("\n\n"
"*** End of Linux kernel configuration.\n"
"*** Execute 'make' to build the kernel or try 'make help'."
"\n\n"));
- } else {
+ break;
+ default:
fprintf(stderr, _("\n\n"
"Your kernel configuration changes were NOT saved."
"\n\n"));
static QApplication *configApp;
static ConfigSettings *configSettings;
+QAction *ConfigMainWindow::saveAction;
+
static inline QString qgettext(const char* str)
{
return QString::fromLocal8Bit(gettext(str));
connect(quitAction, SIGNAL(activated()), SLOT(close()));
QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
- QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
+ saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
+ conf_set_changed_callback(conf_changed);
+ // Set saveAction's initial state
+ conf_changed();
QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
QAction *searchAction = new QAction("Search", "&Search", CTRL+Key_F, this);
*/
void ConfigMainWindow::closeEvent(QCloseEvent* e)
{
- if (!sym_change_count) {
+ if (!conf_get_changed()) {
e->accept();
return;
}
configSettings->writeSizes("/split2", split2->sizes());
}
+void ConfigMainWindow::conf_changed(void)
+{
+ if (saveAction)
+ saveAction->setEnabled(conf_get_changed());
+}
+
void fixup_rootmenu(struct menu *menu)
{
struct menu *child;
class ConfigMainWindow : public QMainWindow {
Q_OBJECT
+
+ static QAction *saveAction;
+ static void conf_changed(void);
public:
ConfigMainWindow(void);
public slots:
.flags = SYMBOL_VALID,
};
-int sym_change_count;
struct symbol *sym_defconfig_list;
struct symbol *modules_sym;
tristate modules_val;
for_all_symbols(i, sym)
sym->flags &= ~SYMBOL_VALID;
- sym_change_count++;
+ sym_add_change_count(1);
if (modules_sym)
sym_calc_value(modules_sym);
}
sym_check_deps(sym);
}
- sym_change_count = 1;
+ sym_set_change_count(1);
}
const char *zconf_tokenname(int token)
sym_check_deps(sym);
}
- sym_change_count = 1;
+ sym_set_change_count(1);
}
const char *zconf_tokenname(int token)
"__bug_table", /* used by powerpc for BUG() */
".exitcall.exit",
".eh_frame",
+ ".parainstructions",
".stab",
"__ex_table",
".fixup",
}
up_read(&mixer->card->controls_rwsem);
if (slot.present != 0) {
- pslot = (struct slot *)kmalloc(sizeof(slot), GFP_KERNEL);
+ pslot = kmalloc(sizeof(slot), GFP_KERNEL);
if (! pslot)
return -ENOMEM;
*pslot = slot;
devc->audio_flags |= DMA_DUPLEX;
}
- portc = (ad1848_port_info *) kmalloc(sizeof(ad1848_port_info), GFP_KERNEL);
+ portc = kmalloc(sizeof(ad1848_port_info), GFP_KERNEL);
if(portc==NULL) {
release_region(devc->base, 4);
return -1;
{
struct address_info *isapnpcfg;
- isapnpcfg=(struct address_info*)kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
+ isapnpcfg = kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
if (!isapnpcfg)
return -ENOMEM;
match:
- wave_dev = (struct emu10k1_wavedevice *) kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
+ wave_dev = kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
if (wave_dev == NULL) {
ERROR();
/* Recording */
struct wiinst *wiinst;
- if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
+ if ((wiinst = kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
ERROR();
kfree(wave_dev);
return -ENOMEM;
struct woinst *woinst;
int i;
- if ((woinst = (struct woinst *) kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
+ if ((woinst = kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
ERROR();
kfree(wave_dev);
return -ENOMEM;
midihdr->flags |= MIDIBUF_INQUEUE; /* set */
midihdr->flags &= ~MIDIBUF_DONE; /* clear */
- if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
+ if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
/* Message lost */
return -1;
}
midihdr->flags |= MIDIBUF_INQUEUE;
midihdr->flags &= ~MIDIBUF_DONE;
- if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
+ if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
/* Message lost */
return -1;
}
{
struct midi_hdr *midihdr;
- if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
+ if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
ERROR();
return -EINVAL;
}
mutex_lock(&card->open_sem);
}
- if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
+ if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
return -EINVAL;
midi_dev->card = card;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
- if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
+ if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
return -EINVAL;
midihdr->bufferlength = count;
DPF(2, "emu10k1_seq_midi_open()\n");
- if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
+ if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
return -EINVAL;
midi_dev->card = card;
card = midi_devs[dev]->devc;
- if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
+ if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
return -EINVAL;
midihdr->bufferlength = 1;
case SOUND_MIXER_PRIVATE3:
- ctl = (struct mixer_private_ioctl *) kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
+ ctl = kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
if (ctl == NULL)
return -ENOMEM;
int ret = 0;
struct hal2_card *hal2;
- hal2 = (struct hal2_card *) kmalloc(sizeof(struct hal2_card), GFP_KERNEL);
+ hal2 = kmalloc(sizeof(struct hal2_card), GFP_KERNEL);
if (!hal2)
return -ENOMEM;
memset(hal2, 0, sizeof(struct hal2_card));
devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */
- mpu401_synth_operations[m] = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+ mpu401_synth_operations[m] = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
if (mpu401_synth_operations[m] == NULL)
{
return 0;
}
- devc = (struct opl_devinfo *)kmalloc(sizeof(*devc), GFP_KERNEL);
+ devc = kmalloc(sizeof(*devc), GFP_KERNEL);
if (devc == NULL)
{
*/
- detected_devc = (sb_devc *)kmalloc(sizeof(sb_devc), GFP_KERNEL);
+ detected_devc = kmalloc(sizeof(sb_devc), GFP_KERNEL);
if (detected_devc == NULL)
{
printk(KERN_ERR "sb: Can't allocate memory for device information\n");
return;
}
std_midi_synth.midi_dev = devc->my_mididev = dev;
- midi_devs[dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
+ midi_devs[dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
if (midi_devs[dev] == NULL)
{
printk(KERN_WARNING "Sound Blaster: failed to allocate MIDI memory.\n");
midi_devs[dev]->devc = devc;
- midi_devs[dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+ midi_devs[dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
if (midi_devs[dev]->converter == NULL)
{
printk(KERN_WARNING "Sound Blaster: failed to allocate MIDI memory.\n");
if (m == -1)
return 0;
- mixer_devs[m] = (struct mixer_operations *)kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
+ mixer_devs[m] = kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
if (mixer_devs[m] == NULL)
{
printk(KERN_ERR "sb_mixer: Can't allocate memory\n");
return;
}
- m=(struct vmidi_memory *)kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
+ m = kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
if (m == NULL)
{
printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n");
conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
devc->hw.dma, devc->hw.dma2);
- portc = (wavnc_port_info *)kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
+ portc = kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
if (portc == NULL)
goto nomem;