diff options
286 files changed, 16129 insertions, 9463 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index afeaf6218ea2..c7a4d0faab22 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -158,13 +158,6 @@ Who: Adrian Bunk <bunk@stusta.de> --------------------------- -What: Legacy /proc/pci interface (PCI_LEGACY_PROC) -When: March 2006 -Why: deprecated since 2.5.53 in favor of lspci(8) -Who: Adrian Bunk <bunk@stusta.de> - ---------------------------- - What: pci_module_init(driver) When: January 2007 Why: Is replaced by pci_register_driver(pci_driver). diff --git a/Documentation/hwmon/w83627hf b/Documentation/hwmon/w83627hf index bbeaba680443..792231921241 100644 --- a/Documentation/hwmon/w83627hf +++ b/Documentation/hwmon/w83627hf @@ -18,6 +18,10 @@ Supported chips: Prefix: 'w83637hf' Addresses scanned: ISA address retrieved from Super I/O registers Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf + * Winbond W83687THF + Prefix: 'w83687thf' + Addresses scanned: ISA address retrieved from Super I/O registers + Datasheet: Provided by Winbond on request Authors: Frodo Looijaard <frodol@dds.nl>, diff --git a/Documentation/hwmon/w83781d b/Documentation/hwmon/w83781d index e5459333ba68..b1e9f80098ee 100644 --- a/Documentation/hwmon/w83781d +++ b/Documentation/hwmon/w83781d @@ -36,6 +36,11 @@ Module parameters Use 'init=0' to bypass initializing the chip. Try this if your computer crashes when you load the module. +* reset int + (default 0) + The driver used to reset the chip on load, but does no more. Use + 'reset=1' to restore the old behavior. Report if you need to do this. + force_subclients=bus,caddr,saddr,saddr This is used to force the i2c addresses for subclients of a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b' @@ -123,6 +128,25 @@ When an alarm goes off, you can be warned by a beeping signal through your computer speaker. It is possible to enable all beeping globally, or only the beeping for some alarms. +Individual alarm and beep bits: + +0x000001: in0 +0x000002: in1 +0x000004: in2 +0x000008: in3 +0x000010: temp1 +0x000020: temp2 (+temp3 on W83781D) +0x000040: fan1 +0x000080: fan2 +0x000100: in4 +0x000200: in5 +0x000400: in6 +0x000800: fan3 +0x001000: chassis +0x002000: temp3 (W83782D and W83627HF only) +0x010000: in7 (W83782D and W83627HF only) +0x020000: in8 (W83782D and W83627HF only) + If an alarm triggers, it will remain triggered until the hardware register is read at least once. This means that the cause for the alarm may already have disappeared! Note that in the current implementation, all diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index 856b4b8b962c..a1c8f581afed 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -4,7 +4,7 @@ Supported adapters: * Intel 82371AB PIIX4 and PIIX4E * Intel 82443MX (440MX) Datasheet: Publicly available at the Intel website - * ServerWorks OSB4, CSB5 and CSB6 southbridges + * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges Datasheet: Only available via NDA from ServerWorks * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge Datasheet: Publicly available at the SMSC website http://www.smsc.com diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb index 08c8cd1df60c..f50e69981ec6 100644 --- a/Documentation/i2c/busses/scx200_acb +++ b/Documentation/i2c/busses/scx200_acb @@ -6,9 +6,10 @@ Module Parameters ----------------- * base: int - Base addresses for the ACCESS.bus controllers + Base addresses for the ACCESS.bus controllers on SCx200 and SC1100 devices Description ----------- -Enable the use of the ACCESS.bus controllers of a SCx200 processor. +Enable the use of the ACCESS.bus controller on the Geode SCx200 and +SC1100 processors and the CS5535 and CS5536 Geode companion devices. diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 7b7382d0f758..44a25f3f51d1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -49,6 +49,7 @@ restrictions referred to are that the relevant option is valid if: MCA MCA bus support is enabled. MDA MDA console support is enabled. MOUSE Appropriate mouse support is enabled. + MSI Message Signaled Interrupts (PCI). MTD MTD support is enabled. NET Appropriate network support is enabled. NUMA NUMA support is enabled. @@ -1152,6 +1153,9 @@ running once the system is up. Mechanism 2. nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI Configuration + nomsi [MSI] If the PCI_MSI kernel config parameter is + enabled, this kernel boot option can be used to + disable the use of MSI interrupts system-wide. nosort [IA-32] Don't sort PCI devices according to order given by the PCI BIOS. This sorting is done to get a device order compatible with diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt index cc4b4d04129c..278771c9ad99 100644 --- a/Documentation/networking/pktgen.txt +++ b/Documentation/networking/pktgen.txt @@ -109,6 +109,22 @@ Examples: cycle through the port range. pgset "udp_dst_max 9" set UDP destination port max. + pgset "mpls 0001000a,0002000a,0000000a" set MPLS labels (in this example + outer label=16,middle label=32, + inner label=0 (IPv4 NULL)) Note that + there must be no spaces between the + arguments. Leading zeros are required. + Do not set the bottom of stack bit, + thats done automatically. If you do + set the bottom of stack bit, that + indicates that you want to randomly + generate that address and the flag + MPLS_RND will be turned on. You + can have any mix of random and fixed + labels in the label stack. + + pgset "mpls 0" turn off mpls (or any invalid argument works too!) + pgset stop aborts injection. Also, ^C aborts generator. @@ -167,6 +183,8 @@ pkt_size min_pkt_size max_pkt_size +mpls + udp_src_min udp_src_max @@ -211,4 +229,4 @@ Grant Grundler for testing on IA-64 and parisc, Harald Welte, Lennert Buytenhek Stephen Hemminger, Andi Kleen, Dave Miller and many others. -Good luck with the linux net-development.
\ No newline at end of file +Good luck with the linux net-development. diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index aeabb4196861..7ec6cfa01fb3 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c @@ -543,7 +543,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) > 0x100000000ULL) continue; - res = alloc_bootmem_low(sizeof(struct resource)); + res = kzalloc(sizeof(struct resource), GFP_ATOMIC); switch (md->type) { case EFI_RESERVED_TYPE: res->name = "Reserved Memory"; diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 2d8782960f41..d313a11acafa 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1288,7 +1288,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat struct resource *res; if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL) continue; - res = alloc_bootmem_low(sizeof(struct resource)); + res = kzalloc(sizeof(struct resource), GFP_ATOMIC); switch (e820.map[i].type) { case E820_RAM: res->name = "System RAM"; break; case E820_ACPI: res->name = "ACPI Tables"; break; @@ -1316,13 +1316,15 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat /* * Request address space for all standard resources + * + * This is called just before pcibios_assign_resources(), which is also + * an fs_initcall, but is linked in later (in arch/i386/pci/i386.c). */ -static void __init register_memory(void) +static int __init request_standard_resources(void) { - unsigned long gapstart, gapsize, round; - unsigned long long last; - int i; + int i; + printk("Setting up standard PCI resources\n"); if (efi_enabled) efi_initialize_iomem_resources(&code_resource, &data_resource); else @@ -1334,6 +1336,16 @@ static void __init register_memory(void) /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < STANDARD_IO_RESOURCES; i++) request_resource(&ioport_resource, &standard_io_resources[i]); + return 0; +} + +fs_initcall(request_standard_resources); + +static void __init register_memory(void) +{ + unsigned long gapstart, gapsize, round; + unsigned long long last; + int i; /* * Search for the bigest gap in the low 32 bits of the e820 diff --git a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile index 5461d4d5ea1e..62ad75c57e6a 100644 --- a/arch/i386/pci/Makefile +++ b/arch/i386/pci/Makefile @@ -1,4 +1,4 @@ -obj-y := i386.o +obj-y := i386.o init.o obj-$(CONFIG_PCI_BIOS) += pcbios.o obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index f6bc48da4d2a..dbece776c5b2 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -8,6 +8,7 @@ #include <linux/pci.h> #include <linux/ioport.h> #include <linux/init.h> +#include <linux/dmi.h> #include <asm/acpi.h> #include <asm/segment.h> @@ -120,11 +121,42 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b) pci_read_bridge_bases(b); } +/* + * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) + */ +#ifdef __i386__ +static int __devinit assign_all_busses(struct dmi_system_id *d) +{ + pci_probe |= PCI_ASSIGN_ALL_BUSSES; + printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" + " (pci=assign-busses)\n", d->ident); + return 0; +} +#endif + +/* + * Laptops which need pci=assign-busses to see Cardbus cards + */ +static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { +#ifdef __i386__ + { + .callback = assign_all_busses, + .ident = "Samsung X20 Laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"), + }, + }, +#endif /* __i386__ */ + {} +}; struct pci_bus * __devinit pcibios_scan_root(int busnum) { struct pci_bus *bus = NULL; + dmi_check_system(pciprobe_dmi_table); + while ((bus = pci_find_next_bus(bus)) != NULL) { if (bus->number == busnum) { /* Already scanned */ diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c index e3ac502bf2fb..99012b93bd12 100644 --- a/arch/i386/pci/direct.c +++ b/arch/i386/pci/direct.c @@ -245,7 +245,7 @@ static int __init pci_check_type2(void) return works; } -static int __init pci_direct_init(void) +void __init pci_direct_init(void) { struct resource *region, *region2; @@ -258,16 +258,16 @@ static int __init pci_direct_init(void) if (pci_check_type1()) { printk(KERN_INFO "PCI: Using configuration type 1\n"); raw_pci_ops = &pci_direct_conf1; - return 0; + return; } release_resource(region); type2: if ((pci_probe & PCI_PROBE_CONF2) == 0) - goto out; + return; region = request_region(0xCF8, 4, "PCI conf2"); if (!region) - goto out; + return; region2 = request_region(0xC000, 0x1000, "PCI conf2"); if (!region2) goto fail2; @@ -275,15 +275,10 @@ static int __init pci_direct_init(void) if (pci_check_type2()) { printk(KERN_INFO "PCI: Using configuration type 2\n"); raw_pci_ops = &pci_direct_conf2; - return 0; + return; } release_resource(region2); fail2: release_resource(region); - - out: - return 0; } - -arch_initcall(pci_direct_init); diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c new file mode 100644 index 000000000000..f9156d3ac723 --- /dev/null +++ b/arch/i386/pci/init.c @@ -0,0 +1,25 @@ +#include <linux/config.h> +#include <linux/pci.h> +#include <linux/init.h> +#include "pci.h" + +/* arch_initcall has too random ordering, so call the initializers + in the right sequence from here. */ +static __init int pci_access_init(void) +{ +#ifdef CONFIG_PCI_MMCONFIG + pci_mmcfg_init(); +#endif + if (raw_pci_ops) + return 0; +#ifdef CONFIG_PCI_BIOS + pci_pcbios_init(); +#endif + if (raw_pci_ops) + return 0; +#ifdef CONFIG_PCI_DIRECT + pci_direct_init(); +#endif + return 0; +} +arch_initcall(pci_access_init); diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 0ee8a983708c..613789071f30 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c @@ -172,25 +172,20 @@ static __init void unreachable_devices(void) } } -static int __init pci_mmcfg_init(void) +void __init pci_mmcfg_init(void) { if ((pci_probe & PCI_PROBE_MMCONF) == 0) - goto out; + return; acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); if ((pci_mmcfg_config_num == 0) || (pci_mmcfg_config == NULL) || (pci_mmcfg_config[0].base_address == 0)) - goto out; + return; printk(KERN_INFO "PCI: Using MMCONFIG\n"); raw_pci_ops = &pci_mmcfg; pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; unreachable_devices(); - - out: - return 0; } - -arch_initcall(pci_mmcfg_init); diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c index b9d65f0bc2d1..1eec0868f4b3 100644 --- a/arch/i386/pci/pcbios.c +++ b/arch/i386/pci/pcbios.c @@ -476,14 +476,12 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) } EXPORT_SYMBOL(pcibios_set_irq_routing); -static int __init pci_pcbios_init(void) +void __init pci_pcbios_init(void) { if ((pci_probe & PCI_PROBE_BIOS) && ((raw_pci_ops = pci_find_bios()))) { pci_probe |= PCI_BIOS_SORT; pci_bios_present = 1; } - return 0; } -arch_initcall(pci_pcbios_init); diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index f550781ec310..12035e29108b 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h @@ -80,4 +80,7 @@ extern int pci_conf1_write(unsigned int seg, unsigned int bus, extern int pci_conf1_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value); +extern void pci_direct_init(void); +extern void pci_pcbios_init(void); +extern void pci_mmcfg_init(void); diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile index a8f75a2a0f6f..a3f6ad570179 100644 --- a/arch/x86_64/pci/Makefile +++ b/arch/x86_64/pci/Makefile @@ -7,7 +7,7 @@ CFLAGS += -Iarch/i386/pci obj-y := i386.o obj-$(CONFIG_PCI_DIRECT)+= direct.o -obj-y += fixup.o +obj-y += fixup.o init.o obj-$(CONFIG_ACPI) += acpi.o obj-y += legacy.o irq.o common.o # mmconfig has a 64bit special @@ -22,3 +22,4 @@ irq-y += ../../i386/pci/irq.o common-y += ../../i386/pci/common.o fixup-y += ../../i386/pci/fixup.o i386-y += ../../i386/pci/i386.o +init-y += ../../i386/pci/init.o diff --git a/block/Kconfig b/block/Kconfig index 377f6dd20e17..96783645092d 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -11,4 +11,16 @@ config LBD your machine, or if you want to have a raid or loopback device bigger than 2TB. Otherwise say N. +config BLK_DEV_IO_TRACE + bool "Support for tracing block io actions" + select RELAY + select DEBUG_FS + help + Say Y here, if you want to be able to trace the block layer actions + on a given queue. Tracing allows you to see any traffic happening + on a block device queue. For more information (and the user space + support tools needed), fetch the blktrace app from: + + git://brick.kernel.dk/data/git/blktrace.git + source block/Kconfig.iosched diff --git a/block/Makefile b/block/Makefile index 7e4f93e2b44e..c05de0e0037f 100644 --- a/block/Makefile +++ b/block/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o obj-$(CONFIG_IOSCHED_AS) += as-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o + +obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o diff --git a/block/blktrace.c b/block/blktrace.c new file mode 100644 index 000000000000..36f3a172275f --- /dev/null +++ b/block/blktrace.c @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2006 Jens Axboe <axboe@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/blkdev.h> +#include <linux/blktrace_api.h> +#include <linux/percpu.h> +#include <linux/init.h> +#include <linux/mutex.h> +#include <linux/debugfs.h> +#include <asm/uaccess.h> + +static DEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, }; +static unsigned int blktrace_seq __read_mostly = 1; + +/* + * Send out a notify for this process, if we haven't done so since a trace + * started + */ +static void trace_note_tsk(struct blk_trace *bt, struct task_struct *tsk) +{ + struct blk_io_trace *t; + + t = relay_reserve(bt->rchan, sizeof(*t) + sizeof(tsk->comm)); + if (t) { + t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + t->device = bt->dev; + t->action = BLK_TC_ACT(BLK_TC_NOTIFY); + t->pid = tsk->pid; + t->cpu = smp_processor_id(); + t->pdu_len = sizeof(tsk->comm); + memcpy((void *) t + sizeof(*t), tsk->comm, t->pdu_len); + tsk->btrace_seq = blktrace_seq; + } +} + +static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, + pid_t pid) +{ + if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0) + return 1; + if (sector < bt->start_lba || sector > bt->end_lba) + return 1; + if (bt->pid && pid != bt->pid) + return 1; + + return 0; +} + +/* + * Data direction bit lookup + */ +static u32 ddir_act[2] __read_mostly = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK_TC_WRITE) }; + +/* + * Bio action bits of interest + */ +static u32 bio_act[3] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC) }; + +/* + * More could be added as needed, taking care to increment the decrementer + * to get correct indexing + */ +#define trace_barrier_bit(rw) \ + (((rw) & (1 << BIO_RW_BARRIER)) >> (BIO_RW_BARRIER - 0)) +#define trace_sync_bit(rw) \ + (((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1)) + +/* + * The worker for the various blk_add_trace*() types. Fills out a + * blk_io_trace structure and places it in a per-cpu subbuffer. + */ +void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, + int rw, u32 what, int error, int pdu_len, void *pdu_data) +{ + struct task_struct *tsk = current; + struct blk_io_trace *t; + unsigned long flags; + unsigned long *sequence; + pid_t pid; + int cpu; + + if (unlikely(bt->trace_state != Blktrace_running)) + return; + + what |= ddir_act[rw & WRITE]; + what |= bio_act[trace_barrier_bit(rw)]; + what |= bio_act[trace_sync_bit(rw)]; + + pid = tsk->pid; + if (unlikely(act_log_check(bt, what, sector, pid))) + return; + + /* + * A word about the locking here - we disable interrupts to reserve + * some space in the relay per-cpu buffer, to prevent an irq + * from coming in and stepping on our toes. Once reserved, it's + * enough to get preemption disabled to prevent read of this data + * before we are through filling it. get_cpu()/put_cpu() does this + * for us + */ + local_irq_save(flags); + + if (unlikely(tsk->btrace_seq != blktrace_seq)) + trace_note_tsk(bt, tsk); + + t = relay_reserve(bt->rchan, sizeof(*t) + pdu_len); + if (t) { + cpu = smp_processor_id(); + sequence = per_cpu_ptr(bt->sequence, cpu); + + t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + t->sequence = ++(*sequence); + t->time = sched_clock() - per_cpu(blk_trace_cpu_offset, cpu); + t->sector = sector; + t->bytes = bytes; + t->action = what; + t->pid = pid; + t->device = bt->dev; + t->cpu = cpu; + t->error = error; + t->pdu_len = pdu_len; + + if (pdu_len) + memcpy((void *) t + sizeof(*t), pdu_data, pdu_len); + } + + local_irq_restore(flags); +} + +EXPORT_SYMBOL_GPL(__blk_add_trace); + +static struct dentry *blk_tree_root; +static struct mutex blk_tree_mutex; +static unsigned int root_users; + +static inline void blk_remove_root(void) +{ + if (blk_tree_root) { + debugfs_remove(blk_tree_root); + blk_tree_root = NULL; + } +} + +static void blk_remove_tree(struct dentry *dir) +{ + mutex_lock(&blk_tree_mutex); + debugfs_remove(dir); + if (--root_users == 0) + blk_remove_root(); + mutex_unlock(&blk_tree_mutex); +} + +static struct dentry *blk_create_tree(const char *blk_name) +{ + struct dentry *dir = NULL; + + mutex_lock(&blk_tree_mutex); + + if (!blk_tree_root) { + blk_tree_root = debugfs_create_dir("block", NULL); + if (!blk_tree_root) + goto err; + } + + dir = debugfs_create_dir(blk_name, blk_tree_root); + if (dir) + root_users++; + else + blk_remove_root(); + +err: + mutex_unlock(&blk_tree_mutex); + return dir; +} + +static void blk_trace_cleanup(struct blk_trace *bt) +{ + relay_close(bt->rchan); + debugfs_remove(bt->dropped_file); + blk_remove_tree(bt->dir); + free_percpu(bt->sequence); + kfree(bt); +} + +static int blk_trace_remove(request_queue_t *q) +{ + struct blk_trace *bt; + + bt = xchg(&q->blk_trace, NULL); + if (!bt) + return -EINVAL; + + if (bt->trace_state == Blktrace_setup || + bt->trace_state == Blktrace_stopped) + blk_trace_cleanup(bt); + + return 0; +} + +static int blk_dropped_open(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->u.generic_ip; + + return 0; +} + +static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct blk_trace *bt = filp->private_data; + char buf[16]; + + snprintf(buf, sizeof(buf), "%u\n", atomic_read(&bt->dropped)); + + return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); +} + +static struct file_operations blk_dropped_fops = { + .owner = THIS_MODULE, + .open = blk_dropped_open, + .read = blk_dropped_read, +}; + +/* + * Keep track of how many times we encountered a full subbuffer, to aid + * the user space app in telling how many lost events there were. + */ +static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf, + void *prev_subbuf, size_t prev_padding) +{ + struct blk_trace *bt; + + if (!relay_buf_full(buf)) + return 1; + + bt = buf->chan->private_data; + atomic_inc(&bt->dropped); + return 0; +} + +static int blk_remove_buf_file_callback(struct dentry *dentry) +{ + debugfs_remove(dentry); + return 0; +} + +static struct dentry *blk_create_buf_file_callback(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global) +{ + return debugfs_create_file(filename, mode, parent, buf, + &relay_file_operations); +} + +static struct rchan_callbacks blk_relay_callbacks = { + .subbuf_start = blk_subbuf_start_callback, + .create_buf_file = blk_create_buf_file_callback, + .remove_buf_file = blk_remove_buf_file_callback, +}; + +/* + * Setup everything required to start tracing + */ +static int blk_trace_setup(request_queue_t *q, struct block_device *bdev, + char __user *arg) +{ + struct blk_user_trace_setup buts; + struct blk_trace *old_bt, *bt = NULL; + struct dentry *dir = NULL; + char b[BDEVNAME_SIZE]; + int ret, i; + + if (copy_from_user(&buts, arg, sizeof(buts))) + return -EFAULT; + + if (!buts.buf_size || !buts.buf_nr) + return -EINVAL; + + strcpy(buts.name, bdevname(bdev, b)); + + /* + * some device names have larger paths - convert the slashes + * to underscores for this to work as expected + */ + for (i = 0; i < strlen(buts.name); i++) + if (buts.name[i] == '/') + buts.name[i] = '_'; + + if (copy_to_user(arg, &buts, sizeof(buts))) + return -EFAULT; + + ret = -ENOMEM; + bt = kzalloc(sizeof(*bt), GFP_KERNEL); + if (!bt) + goto err; + + bt->sequence = alloc_percpu(unsigned long); + if (!bt->sequence) + goto err; + + ret = -ENOENT; + dir = blk_create_tree(buts.name); + if (!dir) + goto err; + + bt->dir = dir; + bt->dev = bdev->bd_dev; + atomic_set(&bt->dropped, 0); + + ret = -EIO; + bt->dropped_file = debugfs_create_file("dropped", 0444, dir, bt, &blk_dropped_fops); + if (!bt->dropped_file) + goto err; + + bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks); + if (!bt->rchan) + goto err; + bt->rchan->private_data = bt; + + bt->act_mask = buts.act_mask; + if (!bt->act_mask) + bt->act_mask = (u16) -1; + + bt->start_lba = buts.start_lba; + bt->end_lba = buts.end_lba; + if (!bt->end_lba) + bt->end_lba = -1ULL; + + bt->pid = buts.pid; + bt->trace_state = Blktrace_setup; + + ret = -EBUSY; + old_bt = xchg(&q->blk_trace, bt); + if (old_bt) { + (void) xchg(&q->blk_trace, old_bt); + goto err; + } + + return 0; +err: + if (dir) + blk_remove_tree(dir); + if (bt) { + if (bt->dropped_file) + debugfs_remove(bt->dropped_file); + if (bt->sequence) + free_percpu(bt->sequence); + if (bt->rchan) + relay_close(bt->rchan); + kfree(bt); + } + return ret; +} + +static int blk_trace_startstop(request_queue_t *q, int start) +{ + struct blk_trace *bt; + int ret; + + if ((bt = q->blk_trace) == NULL) + return -EINVAL; + + /* + * For starting a trace, we can transition from a setup or stopped + * trace. For stopping a trace, the state must be running + */ + ret = -EINVAL; + if (start) { + if (bt->trace_state == Blktrace_setup || + bt->trace_state == Blktrace_stopped) { + blktrace_seq++; + smp_mb(); + bt->trace_state = Blktrace_running; + ret = 0; + } + } else { + if (bt->trace_state == Blktrace_running) { + bt->trace_state = Blktrace_stopped; + relay_flush(bt->rchan); + ret = 0; + } + } + + return ret; +} + +/** + * blk_trace_ioctl: - handle the ioctls associated with tracing + * @bdev: the block device + * @cmd: the ioctl cmd + * @arg: the argument data, if any + * + **/ +int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) +{ + request_queue_t *q; + int ret, start = 0; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + + mutex_lock(&bdev->bd_mutex); + + switch (cmd) { + case BLKTRACESETUP: + ret = blk_trace_setup(q, bdev, arg); + break; + case BLKTRACESTART: + start = 1; + case BLKTRACESTOP: + ret = blk_trace_startstop(q, start); + break; + case BLKTRACETEARDOWN: + ret = blk_trace_remove(q); + break; + default: + ret = -ENOTTY; + break; + } + + mutex_unlock(&bdev->bd_mutex); + return ret; +} + +/** + * blk_trace_shutdown: - stop and cleanup trace structures + * @q: the request queue associated with the device + * + **/ +void blk_trace_shutdown(request_queue_t *q) +{ + blk_trace_startstop(q, 0); + blk_trace_remove(q); +} + +/* + * Average offset over two calls to sched_clock() with a gettimeofday() + * in the middle + */ +static void blk_check_time(unsigned long long *t) +{ + unsigned long long a, b; + struct timeval tv; + + a = sched_clock(); + do_gettimeofday(&tv); + b = sched_clock(); + + *t = tv.tv_sec * 1000000000 + tv.tv_usec * 1000; + *t -= (a + b) / 2; +} + +static void blk_trace_check_cpu_time(void *data) +{ + unsigned long long *t; + int cpu = get_cpu(); + + t = &per_cpu(blk_trace_cpu_offset, cpu); + + /* + * Just call it twice, hopefully the second call will be cache hot + * and a little more precise + */ + blk_check_time(t); + blk_check_time(t); + + put_cpu(); +} + +/* + * Call blk_trace_check_cpu_time() on each CPU to calibrate our inter-CPU + * timings + */ +static void blk_trace_calibrate_offsets(void) +{ + unsigned long flags; + + smp_call_function(blk_trace_check_cpu_time, NULL, 1, 1); + local_irq_save(flags); + blk_trace_check_cpu_time(NULL); + local_irq_restore(flags); +} + +static void blk_trace_set_ht_offsets(void) +{ +#if defined(CONFIG_SCHED_SMT) + int cpu, i; + + /* + * now make sure HT siblings have the same time offset + */ + preempt_disable(); + for_each_online_cpu(cpu) { + unsigned long long *cpu_off, *sibling_off; + + for_each_cpu_mask(i, cpu_sibling_map[cpu]) { + if (i == cpu) + continue; + + cpu_off = &per_cpu(blk_trace_cpu_offset, cpu); + sibling_off = &per_cpu(blk_trace_cpu_offset, i); + *sibling_off = *cpu_off; + } + } + preempt_enable(); +#endif +} + +static __init int blk_trace_init(void) +{ + mutex_init(&blk_tree_mutex); + blk_trace_calibrate_offsets(); + blk_trace_set_ht_offsets(); + + return 0; +} + +module_init(blk_trace_init); + diff --git a/block/elevator.c b/block/elevator.c index db3d0d8296a0..5e558c4689a4 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -33,6 +33,7 @@ #include <linux/init.h> #include <linux/compiler.h> #include <linux/delay.h> +#include <linux/blktrace_api.h> #include <asm/uaccess.h> @@ -333,6 +334,8 @@ void elv_insert(request_queue_t *q, struct request *rq, int where) struct list_head *pos; unsigned ordseq; + blk_add_trace_rq(q, rq, BLK_TA_INSERT); + rq->q = q; switch (where) { @@ -499,6 +502,7 @@ struct request *elv_next_request(request_queue_t *q) * not be passed by new incoming requests */ rq->flags |= REQ_STARTED; + blk_add_trace_rq(q, rq, BLK_TA_ISSUE); } if (!q->boundary_rq || q->boundary_rq == rq) { diff --git a/block/ioctl.c b/block/ioctl.c index 35fdb7dc6512..9cfa2e1ecb24 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -5,6 +5,7 @@ #include <linux/backing-dev.h> #include <linux/buffer_head.h> #include <linux/smp_lock.h> +#include <linux/blktrace_api.h> #include <asm/uaccess.h> static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) @@ -189,6 +190,11 @@ static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, return put_ulong(arg, bdev->bd_inode->i_size >> 9); case BLKGETSIZE64: return put_u64(arg, bdev->bd_inode->i_size); + case BLKTRACESTART: + case BLKTRACESTOP: + case BLKTRACESETUP: + case BLKTRACETEARDOWN: + return blk_trace_ioctl(bdev, cmd, (char __user *) arg); } return -ENOIOCTLCMD; } diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 6c793b196aa9..062067fa7ead 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -28,6 +28,7 @@ #include <linux/writeback.h> #include <linux/interrupt.h> #include <linux/cpu.h> +#include <linux/blktrace_api.h> /* * for max sense size @@ -1556,8 +1557,10 @@ void blk_plug_device(request_queue_t *q) if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) return; - if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) + if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) { mod_timer(&q->unplug_timer, jiffies + q->unplug_delay); + blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG); + } } EXPORT_SYMBOL(blk_plug_device); @@ -1621,14 +1624,21 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi, /* * devices don't necessarily have an ->unplug_fn defined */ - if (q->unplug_fn) + if (q->unplug_fn) { + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + q->unplug_fn(q); + } } static void blk_unplug_work(void *data) { request_queue_t *q = data; + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + q->unplug_fn(q); } @@ -1636,6 +1646,9 @@ static void blk_unplug_timeout(unsigned long data) { request_queue_t *q = (request_queue_t *)data; + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_TIMER, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + kblockd_schedule_work(&q->unplug_work); } @@ -1753,6 +1766,9 @@ static void blk_release_queue(struct kobject *kobj) if (q->queue_tags) __blk_queue_free_tags(q); + if (q->blk_trace) + blk_trace_shutdown(q); + kmem_cache_free(requestq_cachep, q); } @@ -2129,6 +2145,8 @@ rq_starved: rq_init(q, rq); rq->rl = rl; + + blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ); out: return rq; } @@ -2157,6 +2175,8 @@ static struct request *get_request_wait(request_queue_t *q, int rw, if (!rq) { struct io_context *ioc; + blk_add_trace_generic(q, bio, rw, BLK_TA_SLEEPRQ); + __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); io_schedule(); @@ -2210,6 +2230,8 @@ EXPORT_SYMBOL(blk_get_request); */ void blk_requeue_request(request_queue_t *q, struct request *rq) { + blk_add_trace_rq(q, rq, BLK_TA_REQUEUE); + if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); @@ -2844,6 +2866,8 @@ static int __make_request(request_queue_t *q, struct bio *bio) if (!q->back_merge_fn(q, req, bio)) break; + blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE); + req->biotail->bi_next = bio; req->biotail = bio; req->nr_sectors = req->hard_nr_sectors += nr_sectors; @@ -2859,6 +2883,8 @@ static int __make_request(request_queue_t *q, struct bio *bio) if (!q->front_merge_fn(q, req, bio)) break; + blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE); + bio->bi_next = req->bio; req->bio = bio; @@ -2976,6 +3002,7 @@ void generic_make_request(struct bio *bio) request_queue_t *q; sector_t maxsector; int ret, nr_sectors = bio_sectors(bio); + dev_t old_dev; might_sleep(); /* Test device or partition size, when known. */ @@ -3002,6 +3029,8 @@ void generic_make_request(struct bio *bio) * NOTE: we don't repeat the blk_size check for each new device. * Stacking drivers are expected to know what they are doing. */ + maxsector = -1; + old_dev = 0; do { char b[BDEVNAME_SIZE]; @@ -3034,6 +3063,15 @@ end_io: */ blk_partition_remap(bio); + if (maxsector != -1) + blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, + maxsector); + + blk_add_trace_bio(q, bio, BLK_TA_QUEUE); + + maxsector = bio->bi_sector; + old_dev = bio->bi_bdev->bd_dev; + ret = q->make_request_fn(q, bio); } while (ret); } @@ -3153,6 +3191,8 @@ static int __end_that_request_first(struct request *req, int uptodate, int total_bytes, bio_nbytes, error, next_idx = 0; struct bio *bio; + blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE); + /* * extend uptodate bool to allow < 0 value to be direct io error */ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 33e2ca847a26..82710ae39228 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -205,6 +205,18 @@ config ACPI_IBM If you have an IBM ThinkPad laptop, say Y or M here. +config ACPI_IBM_DOCK + bool "Legacy Docking Station Support" + depends on ACPI_IBM + default n + ---help--- + Allows the ibm_acpi driver to handle docking station events. + This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI. It will + allow locking and removing the laptop from the docking station, + but will not properly connect PCI devices. + + If you are not sure, say N here. + config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on X86 diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 5cc090326ddc..262b1f41335a 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -160,13 +160,13 @@ IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */ "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */ "\\CMS", /* R40, R40e */ ); /* all others */ - +#ifdef CONFIG_ACPI_IBM_DOCK IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */ "\\_SB.PCI0.PCI1.DOCK", /* all others */ "\\_SB.PCI.ISA.SLCE", /* 570 */ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ - +#endif IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */ @@ -844,7 +844,7 @@ static int _sta(acpi_handle handle) return status; } - +#ifdef CONFIG_ACPI_IBM_DOCK #define dock_docked() (_sta(dock_handle) & 1) static int dock_read(char *p) @@ -907,6 +907,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event) acpi_bus_generate_event(ibm->device, event, 0); /* unknown */ } } +#endif static int bay_status_supported; static int bay_status2_supported; @@ -1574,6 +1575,7 @@ static struct ibm_struct ibms[] = { .read = light_read, .write = light_write, }, +#ifdef CONFIG_ACPI_IBM_DOCK { .name = "dock", .read = dock_read, @@ -1589,6 +1591,7 @@ static struct ibm_struct ibms[] = { .handle = &pci_handle, .type = ACPI_SYSTEM_NOTIFY, }, +#endif { .name = "bay", .init = bay_init, @@ -1880,7 +1883,9 @@ IBM_PARAM(hotkey); IBM_PARAM(bluetooth); IBM_PARAM(video); IBM_PARAM(light); +#ifdef CONFIG_ACPI_IBM_DOCK IBM_PARAM(dock); +#endif IBM_PARAM(bay); IBM_PARAM(cmos); IBM_PARAM(led); @@ -1927,7 +1932,9 @@ static int __init acpi_ibm_init(void) IBM_HANDLE_INIT(hkey); IBM_HANDLE_INIT(lght); IBM_HANDLE_INIT(cmos); +#ifdef CONFIG_ACPI_IBM_DOCK IBM_HANDLE_INIT(dock); +#endif IBM_HANDLE_INIT(pci); IBM_HANDLE_INIT(bay); if (bay_handle) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9271e5209ac1..a0ab828b2cc5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -23,7 +23,6 @@ static LIST_HEAD(acpi_device_list); DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); -static int acpi_bus_trim(struct acpi_device *start, int rmdevice); static void acpi_device_release(struct kobject *kobj) { @@ -1284,7 +1283,7 @@ int acpi_bus_start(struct acpi_device *device) EXPORT_SYMBOL(acpi_bus_start); -static int acpi_bus_trim(struct acpi_device *start, int rmdevice) +int acpi_bus_trim(struct acpi_device *start, int rmdevice) { acpi_status status; struct acpi_device *parent, *child; @@ -1337,6 +1336,8 @@ static int acpi_bus_trim(struct acpi_device *start, int rmdevice) } return err; } +EXPORT_SYMBOL_GPL(acpi_bus_trim); + static int acpi_bus_scan_fixed(struct acpi_device *root) { diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e29b8926f80e..1f2890989b56 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -38,6 +38,7 @@ #include <linux/hdreg.h> #include <linux/spinlock.h> #include <linux/compat.h> +#include <linux/blktrace_api.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -2331,6 +2332,7 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, cmd->rq->completion_data = cmd; cmd->rq->errors = status; + blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE); blk_complete_request(cmd->rq); } diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 7230d4e08196..99cdc612d2c6 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -406,13 +406,14 @@ config SENSORS_W83L785TS will be called w83l785ts. config SENSORS_W83627HF - tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF" - depends on HWMON && I2C && EXPERIMENTAL + tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" + depends on HWMON && I2C select I2C_ISA select HWMON_VID help If you say yes here you get support for the Winbond W836X7 series - of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF + of sensor chips: the W83627HF, W83627THF, W83637HF, W83687THF and + W83697HF. This driver can also be built as a module. If so, the module will be called w83627hf. diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 665612729cb9..2b6e74dd4a82 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -26,6 +26,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* Addresses to scan */ @@ -92,7 +93,7 @@ struct adm1021_data { struct class_device *class_dev; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -162,10 +163,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct adm1021_data *data = i2c_get_clientdata(client); \ int temp = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = TEMP_TO_REG(temp); \ adm1021_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } set(temp_max, ADM1021_REG_TOS_W); @@ -275,7 +276,7 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, type_name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -351,7 +352,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct adm1021_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -375,7 +376,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 9331c56d2ba6..a4c859c9fbf8 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -53,6 +53,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> /* * Addresses to scan @@ -133,7 +134,7 @@ static struct i2c_driver adm1025_driver = { struct adm1025_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -207,11 +208,11 @@ static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute struct adm1025_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \ data->in_min[offset]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } \ static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ @@ -221,11 +222,11 @@ static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute struct adm1025_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \ data->in_max[offset]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } \ static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ @@ -247,11 +248,11 @@ static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribut struct adm1025_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->temp_min[offset-1] = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \ data->temp_min[offset-1]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } \ static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ @@ -261,11 +262,11 @@ static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribut struct adm1025_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->temp_max[offset-1] = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \ data->temp_max[offset-1]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } \ static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ @@ -404,7 +405,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -523,7 +524,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct adm1025_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { int i; @@ -558,7 +559,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index fefe6e74fd02..6d4f8b8d358e 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -32,6 +32,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; @@ -260,10 +261,10 @@ struct pwm_data { struct adm1026_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; int valid; /* !=0 if following fields are valid */ unsigned long last_reading; /* In jiffies */ unsigned long last_config; /* In jiffies */ @@ -298,9 +299,8 @@ static int adm1026_attach_adapter(struct i2c_adapter *adapter); static int adm1026_detect(struct i2c_adapter *adapter, int address, int kind); static int adm1026_detach_client(struct i2c_client *client); -static int adm1026_read_value(struct i2c_client *client, u8 register); -static int adm1026_write_value(struct i2c_client *client, u8 register, - int value); +static int adm1026_read_value(struct i2c_client *client, u8 reg); +static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); static void adm1026_print_gpio(struct i2c_client *client); static void adm1026_fixup_gpio(struct i2c_client *client); static struct adm1026_data *adm1026_update_device(struct device *dev); @@ -575,7 +575,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) int i; long value, alarms, gpio; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!data->valid || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { /* Things that change quickly */ @@ -710,7 +710,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); data->vid = (data->gpio >> 11) & 0x1f; data->valid = 1; - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -739,10 +739,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = INS_TO_REG(nr, val); adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, @@ -762,10 +762,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = INS_TO_REG(nr, val); adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -813,10 +813,10 @@ static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, c struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf) @@ -831,10 +831,10 @@ static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, c struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -874,11 +874,11 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -939,7 +939,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, if (new_div == 0) { return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); orig_div = data->fan_div[nr]; data->fan_div[nr] = DIV_FROM_REG(new_div); @@ -958,7 +958,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, if (data->fan_div[nr] != orig_div) { fixup_fan_min(dev,nr,orig_div); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1001,11 +1001,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, @@ -1025,11 +1025,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1064,11 +1064,11 @@ static ssize_t set_temp_offset(struct device *dev, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_offset[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], data->temp_offset[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1115,11 +1115,11 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_tmin[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], data->temp_tmin[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1150,11 +1150,11 @@ static ssize_t set_temp_crit_enable(struct device *dev, int val = simple_strtol(buf, NULL, 10); if ((val == 1) || (val==0)) { - down(&data->update_lock); + mutex_lock(&data->update_lock); data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } return count; } @@ -1184,11 +1184,11 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_crit[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], data->temp_crit[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1212,10 +1212,10 @@ static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *a struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->analog_out = DAC_TO_REG(val); adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1267,7 +1267,7 @@ static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, int val = simple_strtol(buf, NULL, 10); unsigned long mask; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->alarm_mask = val & 0x7fffffff; mask = data->alarm_mask | (data->gpio_mask & 0x10000 ? 0x80000000 : 0); @@ -1282,7 +1282,7 @@ static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, mask >>= 8; adm1026_write_value(client, ADM1026_REG_MASK4, mask & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1303,7 +1303,7 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const int val = simple_strtol(buf, NULL, 10); long gpio; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->gpio = val & 0x1ffff; gpio = data->gpio; adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff); @@ -1311,7 +1311,7 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff); gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1331,7 +1331,7 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, int val = simple_strtol(buf, NULL, 10); long mask; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->gpio_mask = val & 0x1ffff; mask = data->gpio_mask; adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff); @@ -1339,7 +1339,7 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff); mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1359,10 +1359,10 @@ static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, co if (data->pwm1.enable == 1) { int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm1.pwm = PWM_TO_REG(val); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } return count; } @@ -1378,14 +1378,14 @@ static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *att struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255); if (data->pwm1.enable == 2) { /* apply immediately */ data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf) @@ -1406,7 +1406,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, int old_enable; if ((val >= 0) && (val < 3)) { - down(&data->update_lock); + mutex_lock(&data->update_lock); old_enable = data->pwm1.enable; data->pwm1.enable = val; data->config1 = (data->config1 & ~CFG1_PWM_AFC) @@ -1424,7 +1424,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); } return count; } @@ -1541,7 +1541,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, /* Fill in the remaining client fields */ data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index d06397966081..3bf2da621aed 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -28,6 +28,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* Following macros takes channel parameter starting from 0 to 2 */ #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) @@ -70,7 +71,7 @@ typedef u8 auto_chan_table_t[8][2]; struct adm1031_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; int chip_type; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -262,10 +263,10 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) old_fan_mode = data->conf1; - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®))) { - up(&data->update_lock); + mutex_unlock(&data->update_lock); return ret; } if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^ @@ -288,7 +289,7 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) } data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -329,11 +330,11 @@ set_auto_temp_min(struct device *dev, const char *buf, size_t count, int nr) struct adm1031_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), data->auto_temp[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr) @@ -349,11 +350,11 @@ set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr) struct adm1031_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]); adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -405,11 +406,11 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr) int val = simple_strtol(buf, NULL, 10); int reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && (((val>>4) & 0xf) != 5)) { /* In automatic mode, the only PWM accepted is 33% */ - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } data->pwm[nr] = PWM_TO_REG(val); @@ -417,7 +418,7 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr) adm1031_write_value(client, ADM1031_REG_PWM, nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) : (data->pwm[nr] & 0xf) | (reg & 0xf0)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -511,7 +512,7 @@ set_fan_min(struct device *dev, const char *buf, size_t count, int nr) struct adm1031_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (val) { data->fan_min[nr] = FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); @@ -519,7 +520,7 @@ set_fan_min(struct device *dev, const char *buf, size_t count, int nr) data->fan_min[nr] = 0xff; } adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t @@ -540,7 +541,7 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) if (tmp == 0xff) return -EINVAL; - down(&data->update_lock); + mutex_lock(&data->update_lock); old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]); new_min = data->fan_min[nr] * old_div / @@ -553,7 +554,7 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) data->fan_div[nr]); adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -627,11 +628,11 @@ set_temp_min(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtol(buf, NULL, 10); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t @@ -643,11 +644,11 @@ set_temp_max(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtol(buf, NULL, 10); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t @@ -659,11 +660,11 @@ set_temp_crit(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtol(buf, NULL, 10); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_crit[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), data->temp_crit[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -778,7 +779,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -891,7 +892,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) struct adm1031_data *data = i2c_get_clientdata(client); int chan; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -965,7 +966,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 5ddc22fea4a3..43f6991b588c 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -49,6 +49,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, @@ -150,7 +151,7 @@ struct adm9240_data { enum chips type; struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; unsigned long last_updated_measure; unsigned long last_updated_config; @@ -195,11 +196,11 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr, struct adm9240_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[attr->index] = TEMP_TO_REG(val); i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index), data->temp_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -246,11 +247,11 @@ static ssize_t set_in_min(struct device *dev, struct adm9240_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[attr->index] = IN_TO_REG(val, attr->index); i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index), data->in_min[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -263,11 +264,11 @@ static ssize_t set_in_max(struct device *dev, struct adm9240_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[attr->index] = IN_TO_REG(val, attr->index); i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index), data->in_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -350,7 +351,7 @@ static ssize_t set_fan_min(struct device *dev, int nr = attr->index; u8 new_div; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!val) { data->fan_min[nr] = 255; @@ -390,7 +391,7 @@ static ssize_t set_fan_min(struct device *dev, i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -439,10 +440,10 @@ static ssize_t set_aout(struct device *dev, struct adm9240_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->aout = AOUT_TO_REG(val); i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); @@ -539,7 +540,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) /* fill in the remaining client fields and attach */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->type = kind; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); if ((err = i2c_attach_client(new_client))) goto exit_free; @@ -691,7 +692,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev) struct adm9240_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); /* minimum measurement cycle: 1.75 seconds */ if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) @@ -771,7 +772,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev) data->last_updated_config = jiffies; data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index ae9de63cf2e0..65b2709f750c 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -44,6 +44,7 @@ #include <linux/err.h> #include <linux/init.h> #include <linux/jiffies.h> +#include <linux/mutex.h> #include "lm75.h" /* @@ -182,10 +183,10 @@ static u8 DIV_TO_REG(long val) struct asb100_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; unsigned long last_updated; /* In jiffies */ /* array of 2 pointers to subclients */ @@ -245,11 +246,11 @@ static ssize_t set_in_##reg(struct device *dev, const char *buf, \ struct asb100_data *data = i2c_get_clientdata(client); \ unsigned long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_##reg[nr] = IN_TO_REG(val); \ asb100_write_value(client, ASB100_REG_IN_##REG(nr), \ data->in_##reg[nr]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -331,10 +332,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct asb100_data *data = i2c_get_clientdata(client); u32 val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -351,7 +352,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long val = simple_strtoul(buf, NULL, 10); int reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -381,7 +382,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -461,7 +462,7 @@ static ssize_t set_##reg(struct device *dev, const char *buf, \ struct asb100_data *data = i2c_get_clientdata(client); \ unsigned long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ switch (nr) { \ case 1: case 2: \ data->reg[nr] = LM75_TEMP_TO_REG(val); \ @@ -472,7 +473,7 @@ static ssize_t set_##reg(struct device *dev, const char *buf, \ } \ asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \ data->reg[nr]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -574,11 +575,11 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const struct asb100_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm &= 0x80; /* keep the enable bit */ data->pwm |= (0x0f & ASB100_PWM_TO_REG(val)); asb100_write_value(client, ASB100_REG_PWM1, data->pwm); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -595,11 +596,11 @@ static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr struct asb100_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm &= 0x0f; /* keep the duty cycle bits */ data->pwm |= (val ? 0x80 : 0x00); asb100_write_value(client, ASB100_REG_PWM1, data->pwm); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -729,7 +730,7 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) } new_client = &data->client; - init_MUTEX(&data->lock); + mutex_init(&data->lock); i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; @@ -789,7 +790,7 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -885,7 +886,7 @@ static int asb100_read_value(struct i2c_client *client, u16 reg) struct i2c_client *cl; int res, bank; - down(&data->lock); + mutex_lock(&data->lock); bank = (reg >> 8) & 0x0f; if (bank > 2) @@ -919,7 +920,7 @@ static int asb100_read_value(struct i2c_client *client, u16 reg) if (bank > 2) i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -930,7 +931,7 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value) struct i2c_client *cl; int bank; - down(&data->lock); + mutex_lock(&data->lock); bank = (reg >> 8) & 0x0f; if (bank > 2) @@ -960,7 +961,7 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value) if (bank > 2) i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); - up(&data->lock); + mutex_unlock(&data->lock); } static void asb100_init_client(struct i2c_client *client) @@ -984,7 +985,7 @@ static struct asb100_data *asb100_update_device(struct device *dev) struct asb100_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1042,7 +1043,7 @@ static struct asb100_data *asb100_update_device(struct device *dev) dev_dbg(&client->dev, "... device update complete\n"); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index b0c490073c8e..728a1e8b9190 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -26,6 +26,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); @@ -60,7 +61,7 @@ static struct i2c_driver atxp1_driver = { struct atxp1_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; unsigned long last_updated; u8 valid; struct { @@ -80,7 +81,7 @@ static struct atxp1_data * atxp1_update_device(struct device *dev) client = to_i2c_client(dev); data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { @@ -93,7 +94,7 @@ static struct atxp1_data * atxp1_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return(data); } @@ -309,7 +310,7 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); err = i2c_attach_client(new_client); diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 203f9c7abb20..478eb4bb8570 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -28,6 +28,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> #include "lm75.h" /* Addresses to scan */ @@ -72,7 +73,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low") struct ds1621_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -156,10 +157,10 @@ static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *at struct ds1621_data *data = ds1621_update_client(dev); \ u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = val; \ ds1621_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -242,7 +243,7 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, /* Fill in remaining client fields and put it into the global list */ strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -297,7 +298,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev) struct ds1621_data *data = i2c_get_clientdata(client); u8 new_conf; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -327,7 +328,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index e029e0a94ecc..885465df6e6a 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -30,6 +30,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/io.h> static struct platform_device *pdev; @@ -131,10 +132,10 @@ static struct resource f71805f_resource __initdata = { struct f71805f_data { unsigned short addr; const char *name; - struct semaphore lock; + struct mutex lock; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ unsigned long last_limits; /* In jiffies */ @@ -224,20 +225,20 @@ static u8 f71805f_read8(struct f71805f_data *data, u8 reg) { u8 val; - down(&data->lock); + mutex_lock(&data->lock); outb(reg, data->addr + ADDR_REG_OFFSET); val = inb(data->addr + DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return val; } static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) { - down(&data->lock); + mutex_lock(&data->lock); outb(reg, data->addr + ADDR_REG_OFFSET); outb(val, data->addr + DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); } /* It is important to read the MSB first, because doing so latches the @@ -246,24 +247,24 @@ static u16 f71805f_read16(struct f71805f_data *data, u8 reg) { u16 val; - down(&data->lock); + mutex_lock(&data->lock); outb(reg, data->addr + ADDR_REG_OFFSET); val = inb(data->addr + DATA_REG_OFFSET) << 8; outb(++reg, data->addr + ADDR_REG_OFFSET); val |= inb(data->addr + DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return val; } static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) { - down(&data->lock); + mutex_lock(&data->lock); outb(reg, data->addr + ADDR_REG_OFFSET); outb(val >> 8, data->addr + DATA_REG_OFFSET); outb(++reg, data->addr + ADDR_REG_OFFSET); outb(val & 0xff, data->addr + DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); } static struct f71805f_data *f71805f_update_device(struct device *dev) @@ -271,7 +272,7 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) struct f71805f_data *data = dev_get_drvdata(dev); int nr; - down(&data->update_lock); + mutex_lock(&data->update_lock); /* Limit registers cache is refreshed after 60 seconds */ if (time_after(jiffies, data->last_updated + 60 * HZ) @@ -323,7 +324,7 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -362,10 +363,10 @@ static ssize_t set_in0_max(struct device *dev, struct device_attribute struct f71805f_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + 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]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -376,18 +377,14 @@ static ssize_t set_in0_min(struct device *dev, struct device_attribute struct f71805f_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + 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]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -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 ssize_t show_in(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -426,10 +423,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_high[nr] = in_to_reg(val); f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -442,31 +439,14 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_low[nr] = in_to_reg(val); f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define sysfs_in(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset) - -sysfs_in(1); -sysfs_in(2); -sysfs_in(3); -sysfs_in(4); -sysfs_in(5); -sysfs_in(6); -sysfs_in(7); -sysfs_in(8); - static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -495,24 +475,14 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_low[nr] = fan_to_reg(val); f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define sysfs_fan(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1) - -sysfs_fan(1); -sysfs_fan(2); -sysfs_fan(3); - static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -562,10 +532,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_high[nr] = temp_to_reg(val); f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -578,28 +548,14 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst[nr] = temp_to_reg(val); f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define sysfs_temp(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_hyst, set_temp_hyst, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \ - show_temp_type, NULL, offset - 1) - -sysfs_temp(1); -sysfs_temp(2); -sysfs_temp(3); - static ssize_t show_alarms_in(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -625,10 +581,6 @@ static ssize_t show_alarms_temp(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07); } -static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL); -static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL); -static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL); - static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -637,7 +589,89 @@ static ssize_t show_name(struct device *dev, struct device_attribute return sprintf(buf, "%s\n", data->name); } -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +static struct device_attribute f71805f_dev_attr[] = { + __ATTR(in0_input, S_IRUGO, show_in0, NULL), + __ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max), + __ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min), + __ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL), + __ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL), + __ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL), + __ATTR(name, S_IRUGO, show_name, NULL), +}; + +static struct sensor_device_attribute f71805f_sensor_attr[] = { + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 1), + SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 2), + SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 3), + SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 4), + SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 5), + SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 6), + SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 7), + SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), + SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 8), + SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 8), + + SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), + SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 0), + SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, + show_temp_hyst, set_temp_hyst, 0), + SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), + SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), + SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 1), + SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, + show_temp_hyst, set_temp_hyst, 1), + SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), + SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), + SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 2), + SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, + show_temp_hyst, set_temp_hyst, 2), + SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), +}; + +static struct sensor_device_attribute f71805f_fan_attr[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR, + show_fan_min, set_fan_min, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR, + show_fan_min, set_fan_min, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR, + show_fan_min, set_fan_min, 2), +}; /* * Device registration and initialization @@ -668,7 +702,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev) { struct f71805f_data *data; struct resource *res; - int err; + int i, err; if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) { err = -ENOMEM; @@ -678,9 +712,9 @@ static int __devinit f71805f_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_IO, 0); data->addr = res->start; - init_MUTEX(&data->lock); + mutex_init(&data->lock); data->name = "f71805f"; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); platform_set_drvdata(pdev, data); @@ -695,76 +729,31 @@ static int __devinit f71805f_probe(struct platform_device *pdev) f71805f_init_device(data); /* Register sysfs interface files */ - device_create_file(&pdev->dev, &dev_attr_in0_input); - device_create_file(&pdev->dev, &dev_attr_in0_max); - device_create_file(&pdev->dev, &dev_attr_in0_min); - device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr); - if (data->fan_enabled & (1 << 0)) { - device_create_file(&pdev->dev, - &sensor_dev_attr_fan1_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_fan1_min.dev_attr); + for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) { + err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]); + if (err) + goto exit_class; } - if (data->fan_enabled & (1 << 1)) { - device_create_file(&pdev->dev, - &sensor_dev_attr_fan2_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_fan2_min.dev_attr); + for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) { + err = device_create_file(&pdev->dev, + &f71805f_sensor_attr[i].dev_attr); + if (err) + goto exit_class; } - if (data->fan_enabled & (1 << 2)) { - device_create_file(&pdev->dev, - &sensor_dev_attr_fan3_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_fan3_min.dev_attr); + for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) { + if (!(data->fan_enabled & (1 << (i / 2)))) + continue; + err = device_create_file(&pdev->dev, + &f71805f_fan_attr[i].dev_attr); + if (err) + goto exit_class; } - device_create_file(&pdev->dev, - &sensor_dev_attr_temp1_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp2_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp3_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp1_max_hyst.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp2_max_hyst.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp3_max_hyst.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr); - device_create_file(&pdev->dev, &dev_attr_alarms_in); - device_create_file(&pdev->dev, &dev_attr_alarms_fan); - device_create_file(&pdev->dev, &dev_attr_alarms_temp); - device_create_file(&pdev->dev, &dev_attr_name); return 0; +exit_class: + dev_err(&pdev->dev, "Sysfs interface creation failed\n"); + hwmon_device_unregister(data->class_dev); exit_free: kfree(data); exit: diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c index 25409181d1eb..6bc76b407636 100644 --- a/drivers/hwmon/fscher.c +++ b/drivers/hwmon/fscher.c @@ -33,6 +33,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* * Addresses to scan @@ -133,7 +134,7 @@ static struct i2c_driver fscher_driver = { struct fscher_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -332,7 +333,7 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) * global list */ strlcpy(new_client->name, "fscher", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -417,7 +418,7 @@ static struct fscher_data *fscher_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct fscher_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { @@ -457,7 +458,7 @@ static struct fscher_data *fscher_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -472,10 +473,10 @@ static ssize_t set_fan_status(struct i2c_client *client, struct fscher_data *dat /* bits 0..1, 3..7 reserved => mask with 0x04 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v; fscher_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -490,10 +491,10 @@ static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data, { unsigned long v = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -518,14 +519,14 @@ static ssize_t set_fan_div(struct i2c_client *client, struct fscher_data *data, return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); /* bits 2..7 reserved => mask with 0x03 */ data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03; data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v; fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -552,10 +553,10 @@ static ssize_t set_temp_status(struct i2c_client *client, struct fscher_data *da /* bits 2..7 reserved, 0 read only => mask with 0x02 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v; fscher_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -609,10 +610,10 @@ static ssize_t set_control(struct i2c_client *client, struct fscher_data *data, /* bits 1..7 reserved => mask with 0x01 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->global_control &= ~v; fscher_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -631,11 +632,11 @@ static ssize_t set_watchdog_control(struct i2c_client *client, struct /* bits 0..3 reserved => mask with 0xf0 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->watchdog[2] &= ~0xf0; data->watchdog[2] |= v; fscher_write_value(client, reg, data->watchdog[2]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -651,10 +652,10 @@ static ssize_t set_watchdog_status(struct i2c_client *client, struct fscher_data /* bits 0, 2..7 reserved => mask with 0x02 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->watchdog[1] &= ~v; fscher_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -669,10 +670,10 @@ static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data { unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->watchdog[0] = v; fscher_write_value(client, reg, data->watchdog[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index 6d0146b57020..6dc4846b9eeb 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c @@ -37,6 +37,7 @@ #include <linux/init.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* * Addresses to scan @@ -89,8 +90,8 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter); static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind); static int fscpos_detach_client(struct i2c_client *client); -static int fscpos_read_value(struct i2c_client *client, u8 register); -static int fscpos_write_value(struct i2c_client *client, u8 register, u8 value); +static int fscpos_read_value(struct i2c_client *client, u8 reg); +static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); static struct fscpos_data *fscpos_update_device(struct device *dev); static void fscpos_init_client(struct i2c_client *client); @@ -114,7 +115,7 @@ static struct i2c_driver fscpos_driver = { struct fscpos_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* 0 until following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -208,13 +209,13 @@ static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); /* bits 2..7 reserved => mask with 0x03 */ data->fan_ripple[nr - 1] &= ~0x03; data->fan_ripple[nr - 1] |= v; fscpos_write_value(client, reg, data->fan_ripple[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -232,10 +233,10 @@ static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data, if (v < 0) v = 0; if (v > 255) v = 255; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr - 1] = v; fscpos_write_value(client, reg, data->pwm[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -278,11 +279,11 @@ static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data /* bits 0..3 reserved => mask with 0xf0 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->wdog_control &= ~0xf0; data->wdog_control |= v; fscpos_write_value(client, reg, data->wdog_control); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -304,10 +305,10 @@ static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); data->wdog_state &= ~v; fscpos_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -321,10 +322,10 @@ static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data { unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->wdog_preset = v; fscpos_write_value(client, reg, data->wdog_preset); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -483,7 +484,7 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -579,7 +580,7 @@ static struct fscpos_data *fscpos_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct fscpos_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { int i; @@ -625,7 +626,7 @@ static struct fscpos_data *fscpos_update_device(struct device *dev) data->last_updated = jiffies; data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 9e685e3a3bc9..6606aabdb49d 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -43,6 +43,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; @@ -120,7 +121,7 @@ struct gl518_data { struct class_device *class_dev; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -212,10 +213,10 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c struct gl518_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = type##_TO_REG(val); \ gl518_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -228,12 +229,12 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c int regvalue; \ unsigned long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ regvalue = gl518_read_value(client, reg); \ data->value = type##_TO_REG(val); \ regvalue = (regvalue & ~mask) | (data->value << shift); \ gl518_write_value(client, reg, regvalue); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -265,7 +266,7 @@ static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, c int regvalue; unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); data->fan_min[0] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[0])); @@ -280,7 +281,7 @@ static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, c data->beep_mask &= data->alarm_mask; gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -291,7 +292,7 @@ static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, c int regvalue; unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); data->fan_min[1] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[1])); @@ -306,7 +307,7 @@ static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, c data->beep_mask &= data->alarm_mask; gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -407,7 +408,7 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -525,7 +526,7 @@ static struct gl518_data *gl518_update_device(struct device *dev) struct gl518_data *data = i2c_get_clientdata(client); int val; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -586,7 +587,7 @@ static struct gl518_data *gl518_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index baee60e44b52..47b4d49f75c6 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -29,6 +29,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> /* Type of the extra sensor */ static unsigned short extra_sensor_type; @@ -121,7 +122,7 @@ static struct i2c_driver gl520_driver = { struct gl520_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until the following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -303,7 +304,7 @@ static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, co long v = simple_strtol(buf, NULL, 10); u8 r; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (n == 0) r = VDD_TO_REG(v); @@ -317,7 +318,7 @@ static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, co else gl520_write_value(client, reg, r); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -331,7 +332,7 @@ static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, co else r = IN_TO_REG(v); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[n] = r; @@ -340,7 +341,7 @@ static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, co else gl520_write_value(client, reg, r); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -373,7 +374,7 @@ static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, c unsigned long v = simple_strtoul(buf, NULL, 10); u8 r; - down(&data->update_lock); + mutex_lock(&data->update_lock); r = FAN_TO_REG(v, data->fan_div[n - 1]); data->fan_min[n - 1] = r; @@ -390,7 +391,7 @@ static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, c data->beep_mask &= data->alarm_mask; gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -409,7 +410,7 @@ static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, c return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_div[n - 1] = r; if (n == 1) @@ -417,7 +418,7 @@ static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, c else gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -425,10 +426,10 @@ static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, c { u8 r = simple_strtoul(buf, NULL, 10)?1:0; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_off = r; gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -454,10 +455,10 @@ static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, { long v = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[n - 1] = TEMP_TO_REG(v);; gl520_write_value(client, reg, data->temp_max[n - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -465,10 +466,10 @@ static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *d { long v = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max_hyst[n - 1] = TEMP_TO_REG(v); gl520_write_value(client, reg, data->temp_max_hyst[n - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -491,10 +492,10 @@ static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *dat { u8 r = simple_strtoul(buf, NULL, 10)?0:1; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->beep_enable = !r; gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -502,11 +503,11 @@ static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, { u8 r = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); r &= data->alarm_mask; data->beep_mask = r; gl520_write_value(client, reg, r); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -561,7 +562,7 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields */ strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -685,7 +686,7 @@ static struct gl520_data *gl520_update_device(struct device *dev) struct gl520_data *data = i2c_get_clientdata(client); int val; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { @@ -750,7 +751,7 @@ static struct gl520_data *gl520_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 23a9e1ea8e32..7636c1a58f9c 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -33,6 +33,7 @@ #include <linux/module.h> #include <linux/timer.h> #include <linux/dmi.h> +#include <linux/mutex.h> #include <asm/io.h> #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ @@ -70,10 +71,10 @@ static u8 km_activity; static int rest_x; static int rest_y; -static DECLARE_MUTEX(hdaps_sem); +static DEFINE_MUTEX(hdaps_mutex); /* - * __get_latch - Get the value from a given port. Callers must hold hdaps_sem. + * __get_latch - Get the value from a given port. Callers must hold hdaps_mutex. */ static inline u8 __get_latch(u16 port) { @@ -82,7 +83,7 @@ static inline u8 __get_latch(u16 port) /* * __check_latch - Check a port latch for a given value. Returns zero if the - * port contains the given value. Callers must hold hdaps_sem. + * port contains the given value. Callers must hold hdaps_mutex. */ static inline int __check_latch(u16 port, u8 val) { @@ -93,7 +94,7 @@ static inline int __check_latch(u16 port, u8 val) /* * __wait_latch - Wait up to 100us for a port latch to get a certain value, - * returning zero if the value is obtained. Callers must hold hdaps_sem. + * returning zero if the value is obtained. Callers must hold hdaps_mutex. */ static int __wait_latch(u16 port, u8 val) { @@ -110,7 +111,7 @@ static int __wait_latch(u16 port, u8 val) /* * __device_refresh - request a refresh from the accelerometer. Does not wait - * for refresh to complete. Callers must hold hdaps_sem. + * for refresh to complete. Callers must hold hdaps_mutex. */ static void __device_refresh(void) { @@ -124,7 +125,7 @@ static void __device_refresh(void) /* * __device_refresh_sync - request a synchronous refresh from the * accelerometer. We wait for the refresh to complete. Returns zero if - * successful and nonzero on error. Callers must hold hdaps_sem. + * successful and nonzero on error. Callers must hold hdaps_mutex. */ static int __device_refresh_sync(void) { @@ -134,7 +135,7 @@ static int __device_refresh_sync(void) /* * __device_complete - indicate to the accelerometer that we are done reading - * data, and then initiate an async refresh. Callers must hold hdaps_sem. + * data, and then initiate an async refresh. Callers must hold hdaps_mutex. */ static inline void __device_complete(void) { @@ -152,7 +153,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val) { int ret; - down(&hdaps_sem); + mutex_lock(&hdaps_mutex); /* do a sync refresh -- we need to be sure that we read fresh data */ ret = __device_refresh_sync(); @@ -163,7 +164,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val) __device_complete(); out: - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); return ret; } @@ -198,9 +199,9 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2, { int ret; - down(&hdaps_sem); + mutex_lock(&hdaps_mutex); ret = __hdaps_read_pair(port1, port2, val1, val2); - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); return ret; } @@ -213,7 +214,7 @@ static int hdaps_device_init(void) { int total, ret = -ENXIO; - down(&hdaps_sem); + mutex_lock(&hdaps_mutex); outb(0x13, 0x1610); outb(0x01, 0x161f); @@ -279,7 +280,7 @@ static int hdaps_device_init(void) } out: - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); return ret; } @@ -313,7 +314,7 @@ static struct platform_driver hdaps_driver = { }; /* - * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. + * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mutex. */ static void hdaps_calibrate(void) { @@ -325,7 +326,7 @@ static void hdaps_mousedev_poll(unsigned long unused) int x, y; /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ - if (down_trylock(&hdaps_sem)) { + if (!mutex_trylock(&hdaps_mutex)) { mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); return; } @@ -340,7 +341,7 @@ static void hdaps_mousedev_poll(unsigned long unused) mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); out: - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); } @@ -420,9 +421,9 @@ static ssize_t hdaps_calibrate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - down(&hdaps_sem); + mutex_lock(&hdaps_mutex); hdaps_calibrate(); - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); return count; } diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index e497274916ce..a74a44f16f51 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -54,6 +54,10 @@ (IMVP-II). You can find more information in the datasheet of Max1718 http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452 + The 13 specification corresponds to the Intel Pentium M series. There + doesn't seem to be any named specification for these. The conversion + tables are detailed directly in the various Pentium M datasheets: + http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm */ /* vrm is the VRM/VRD document version multiplied by 10. @@ -100,6 +104,8 @@ int vid_from_reg(int val, u8 vrm) case 17: /* Intel IMVP-II */ return(val & 0x10 ? 975 - (val & 0xF) * 25 : 1750 - val * 50); + case 13: + return(1708 - (val & 0x3f) * 16); default: /* report 0 for unknown */ printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n"); return 0; @@ -129,8 +135,9 @@ struct vrm_model { static struct vrm_model vrm_models[] = { {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */ {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */ - {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85}, /* 0.13um too */ + {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */ {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */ + {X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */ {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index dddd3eb9b387..106fa01cdb60 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -17,6 +17,7 @@ #include <linux/idr.h> #include <linux/hwmon.h> #include <linux/gfp.h> +#include <linux/spinlock.h> #define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" @@ -24,6 +25,7 @@ static struct class *hwmon_class; static DEFINE_IDR(hwmon_idr); +static DEFINE_SPINLOCK(idr_lock); /** * hwmon_device_register - register w/ hwmon sysfs class @@ -37,20 +39,30 @@ static DEFINE_IDR(hwmon_idr); struct class_device *hwmon_device_register(struct device *dev) { struct class_device *cdev; - int id; + int id, err; - if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0) +again: + if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)) return ERR_PTR(-ENOMEM); - if (idr_get_new(&hwmon_idr, NULL, &id) < 0) - return ERR_PTR(-ENOMEM); + spin_lock(&idr_lock); + err = idr_get_new(&hwmon_idr, NULL, &id); + spin_unlock(&idr_lock); + + if (unlikely(err == -EAGAIN)) + goto again; + else if (unlikely(err)) + return ERR_PTR(err); id = id & MAX_ID_MASK; cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev, HWMON_ID_FORMAT, id); - if (IS_ERR(cdev)) + if (IS_ERR(cdev)) { + spin_lock(&idr_lock); idr_remove(&hwmon_idr, id); + spin_unlock(&idr_lock); + } return cdev; } @@ -64,9 +76,11 @@ void hwmon_device_unregister(struct class_device *cdev) { int id; - if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) { + if (likely(sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1)) { class_device_unregister(cdev); + spin_lock(&idr_lock); idr_remove(&hwmon_idr, id); + spin_unlock(&idr_lock); } else dev_dbg(cdev->dev, "hwmon_device_unregister() failed: bad class ID!\n"); diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index d7a9401600bb..06df92b3ee49 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -41,6 +41,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/io.h> @@ -194,10 +195,10 @@ static int DIV_TO_REG(int val) struct it87_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -224,9 +225,8 @@ 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_detach_client(struct i2c_client *client); -static int it87_read_value(struct i2c_client *client, u8 register); -static int it87_write_value(struct i2c_client *client, u8 register, - u8 value); +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 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); @@ -290,11 +290,11 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val); it87_write_value(client, IT87_REG_VIN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, @@ -307,11 +307,11 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val); it87_write_value(client, IT87_REG_VIN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -381,10 +381,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_high[nr] = TEMP_TO_REG(val); it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, @@ -397,10 +397,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_low[nr] = TEMP_TO_REG(val); it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_temp_offset(offset) \ @@ -440,7 +440,7 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->sensor &= ~(1 << nr); data->sensor &= ~(8 << nr); @@ -450,11 +450,11 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, else if (val == 2) data->sensor |= 8 << nr; else if (val != 0) { - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_sensor_offset(offset) \ @@ -524,7 +524,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, int val = simple_strtol(buf, NULL, 10); u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (nr) { case 0: data->fan_div[nr] = reg & 0x07; break; case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; @@ -533,7 +533,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, @@ -548,7 +548,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, int i, min[3]; u8 old; - down(&data->update_lock); + mutex_lock(&data->update_lock); old = it87_read_value(client, IT87_REG_FAN_DIV); for (i = 0; i < 3; i++) @@ -576,7 +576,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i])); it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_pwm_enable(struct device *dev, @@ -589,7 +589,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (val == 0) { int tmp; @@ -606,11 +606,11 @@ static ssize_t set_pwm_enable(struct device *dev, /* set saved pwm value, clear FAN_CTLX PWM mode bit */ it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); } else { - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, @@ -626,11 +626,11 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, if (val < 0 || val > 255) return -EINVAL; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->manual_pwm_ctl[nr] = val; if (data->fan_main_ctrl & (1 << nr)) it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -776,7 +776,7 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) new_client = &data->client; if (is_isa) - init_MUTEX(&data->lock); + mutex_init(&data->lock); i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; @@ -823,7 +823,7 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -950,10 +950,10 @@ static int it87_read_value(struct i2c_client *client, u8 reg) int res; if (i2c_is_isa_client(client)) { - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); res = inb_p(client->addr + IT87_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return res; } else return i2c_smbus_read_byte_data(client, reg); @@ -969,10 +969,10 @@ static int 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)) { - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); outb_p(value, client->addr + IT87_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return 0; } else return i2c_smbus_write_byte_data(client, reg, value); @@ -1098,7 +1098,7 @@ static struct it87_data *it87_update_device(struct device *dev) struct it87_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1160,7 +1160,7 @@ static struct it87_data *it87_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 6b1aa7ef552e..071f0fc6adec 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -45,6 +45,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* * Addresses to scan @@ -153,7 +154,7 @@ static struct i2c_driver lm63_driver = { struct lm63_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -192,13 +193,13 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *dummy, struct lm63_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan[1] = FAN_TO_REG(val); i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, data->fan[1] & 0xFF); i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, data->fan[1] >> 8); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -222,12 +223,12 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy, return -EPERM; val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm1_value = val <= 0 ? 0 : val >= 255 ? 2 * data->pwm1_freq : (val * data->pwm1_freq * 2 + 127) / 255; i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -253,10 +254,10 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy, struct lm63_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp8[1] = TEMP8_TO_REG(val); i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -284,13 +285,13 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, long val = simple_strtol(buf, NULL, 10); int nr = attr->index; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp11[nr] = TEMP11_TO_REG(val); i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], data->temp11[nr] >> 8); i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], data->temp11[nr] & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -314,11 +315,11 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute * long val = simple_strtol(buf, NULL, 10); long hyst; - down(&data->update_lock); + mutex_lock(&data->update_lock); hyst = TEMP8_FROM_REG(data->temp8[2]) - val; i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, HYST_TO_REG(hyst)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -427,7 +428,7 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -530,7 +531,7 @@ static struct lm63_data *lm63_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm63_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { if (data->config & 0x04) { /* tachometer enabled */ @@ -582,7 +583,7 @@ static struct lm63_data *lm63_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 74ca2c8c61c3..fc25b90ec24a 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -25,6 +25,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> #include "lm75.h" @@ -47,7 +48,7 @@ I2C_CLIENT_INSMOD_1(lm75); struct lm75_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ u16 temp_input; /* Register values */ @@ -91,10 +92,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct lm75_data *data = i2c_get_clientdata(client); \ int temp = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = LM75_TEMP_TO_REG(temp); \ lm75_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } set(temp_max, LM75_REG_TEMP_OS); @@ -188,7 +189,7 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -264,7 +265,7 @@ static struct lm75_data *lm75_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm75_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -277,7 +278,7 @@ static struct lm75_data *lm75_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index df9e02aaa70a..459cc977380a 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -32,6 +32,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END }; @@ -51,7 +52,7 @@ I2C_CLIENT_INSMOD_1(lm77); struct lm77_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; unsigned long last_updated; /* In jiffies */ int temp_input; /* Temperatures */ @@ -139,10 +140,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct lm77_data *data = i2c_get_clientdata(client); \ long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = val; \ lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value)); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -157,11 +158,11 @@ static ssize_t set_temp_crit_hyst(struct device *dev, struct device_attribute *a struct lm77_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst = data->temp_crit - val; lm77_write_value(client, LM77_REG_TEMP_HYST, LM77_TEMP_TO_REG(data->temp_hyst)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -173,7 +174,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, long val = simple_strtoul(buf, NULL, 10); int oldcrithyst; - down(&data->update_lock); + mutex_lock(&data->update_lock); oldcrithyst = data->temp_crit - data->temp_hyst; data->temp_crit = val; data->temp_hyst = data->temp_crit - oldcrithyst; @@ -181,7 +182,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, LM77_TEMP_TO_REG(data->temp_crit)); lm77_write_value(client, LM77_REG_TEMP_HYST, LM77_TEMP_TO_REG(data->temp_hyst)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -306,7 +307,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -380,7 +381,7 @@ static struct lm77_data *lm77_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm77_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -406,7 +407,7 @@ static struct lm77_data *lm77_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index e404001e20da..94be3d797e61 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -27,6 +27,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/io.h> /* Addresses to scan */ @@ -131,10 +132,10 @@ static inline int TEMP_FROM_REG(s8 val) struct lm78_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -157,8 +158,8 @@ static int lm78_isa_attach_adapter(struct i2c_adapter *adapter); static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); static int lm78_detach_client(struct i2c_client *client); -static int lm78_read_value(struct i2c_client *client, u8 register); -static int lm78_write_value(struct i2c_client *client, u8 register, u8 value); +static int lm78_read_value(struct i2c_client *client, u8 reg); +static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value); static struct lm78_data *lm78_update_device(struct device *dev); static void lm78_init_client(struct i2c_client *client); @@ -207,10 +208,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf, struct lm78_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val); lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -221,10 +222,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf, struct lm78_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val); lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -288,10 +289,10 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, struct lm78_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_over = TEMP_TO_REG(val); lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -307,10 +308,10 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, struct lm78_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst = TEMP_TO_REG(val); lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -342,10 +343,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct lm78_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -368,7 +369,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long min; u8 reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -380,7 +381,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, default: dev_err(&client->dev, "fan_div value %ld not " "supported. Choose one of 1, 2, 4 or 8!\n", val); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -398,7 +399,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -548,7 +549,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) new_client = &data->client; if (is_isa) - init_MUTEX(&data->lock); + mutex_init(&data->lock); i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; @@ -598,7 +599,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -697,10 +698,10 @@ static int lm78_read_value(struct i2c_client *client, u8 reg) int res; if (i2c_is_isa_client(client)) { struct lm78_data *data = i2c_get_clientdata(client); - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); res = inb_p(client->addr + LM78_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return res; } else return i2c_smbus_read_byte_data(client, reg); @@ -717,10 +718,10 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) { if (i2c_is_isa_client(client)) { struct lm78_data *data = i2c_get_clientdata(client); - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); outb_p(value, client->addr + LM78_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return 0; } else return i2c_smbus_write_byte_data(client, reg, value); @@ -742,7 +743,7 @@ static struct lm78_data *lm78_update_device(struct device *dev) struct lm78_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -786,7 +787,7 @@ static struct lm78_data *lm78_update_device(struct device *dev) data->fan_div[2] = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index c9a7cdea7bd7..f72120d08c4c 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -28,6 +28,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, @@ -108,7 +109,7 @@ static inline long TEMP_FROM_REG(u16 temp) struct lm80_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -191,10 +192,10 @@ static ssize_t set_in_##suffix(struct device *dev, struct device_attribute *attr struct lm80_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock);\ + mutex_lock(&data->update_lock);\ data->value = IN_TO_REG(val); \ lm80_write_value(client, reg, data->value); \ - up(&data->update_lock);\ + mutex_unlock(&data->update_lock);\ return count; \ } set_in(min0, in_min[0], LM80_REG_IN_MIN(0)); @@ -241,10 +242,10 @@ static ssize_t set_fan_##suffix(struct device *dev, struct device_attribute *att struct lm80_data *data = i2c_get_clientdata(client); \ long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock);\ + mutex_lock(&data->update_lock);\ data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \ lm80_write_value(client, reg, data->value); \ - up(&data->update_lock);\ + mutex_unlock(&data->update_lock);\ return count; \ } set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]); @@ -263,7 +264,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, u8 reg; /* Save fan_min */ - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -275,7 +276,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, default: dev_err(&client->dev, "fan_div value %ld not " "supported. Choose one of 1, 2, 4 or 8!\n", val); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -286,7 +287,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, /* Restore fan_min */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -325,10 +326,10 @@ static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *at struct lm80_data *data = i2c_get_clientdata(client); \ long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = TEMP_LIMIT_TO_REG(val); \ lm80_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX); @@ -437,7 +438,7 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -545,7 +546,7 @@ static struct lm80_data *lm80_update_device(struct device *dev) struct lm80_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { dev_dbg(&client->dev, "Starting lm80 update\n"); @@ -585,7 +586,7 @@ static struct lm80_data *lm80_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index 26dfa9e216c2..aac4ec2bf694 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -35,6 +35,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* * Addresses to scan @@ -139,7 +140,7 @@ static struct i2c_driver lm83_driver = { struct lm83_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -171,11 +172,11 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, long val = simple_strtol(buf, NULL, 10); int nr = attr->index; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp[nr] = TEMP_TO_REG(val); i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4], data->temp[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -300,7 +301,7 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -373,7 +374,7 @@ static struct lm83_data *lm83_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm83_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { int nr; @@ -393,7 +394,7 @@ static struct lm83_data *lm83_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 7389a0127547..342e9663119d 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -31,6 +31,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; @@ -331,10 +332,10 @@ struct lm85_autofan { struct lm85_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; int valid; /* !=0 if following fields are valid */ unsigned long last_reading; /* In jiffies */ unsigned long last_config; /* In jiffies */ @@ -373,8 +374,8 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, int kind); static int lm85_detach_client(struct i2c_client *client); -static int lm85_read_value(struct i2c_client *client, u8 register); -static int lm85_write_value(struct i2c_client *client, u8 register, int value); +static int lm85_read_value(struct i2c_client *client, u8 reg); +static int lm85_write_value(struct i2c_client *client, u8 reg, int value); static struct lm85_data *lm85_update_device(struct device *dev); static void lm85_init_client(struct i2c_client *client); @@ -407,10 +408,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val); lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -499,10 +500,10 @@ static ssize_t set_pwm(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr] = PWM_TO_REG(val); lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr) @@ -559,10 +560,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = INS_TO_REG(nr, val); lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_in_max(struct device *dev, char *buf, int nr) @@ -577,10 +578,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = INS_TO_REG(nr, val); lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_in_reg(offset) \ @@ -640,10 +641,10 @@ static ssize_t set_temp_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_max(struct device *dev, char *buf, int nr) @@ -658,10 +659,10 @@ static ssize_t set_temp_max(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_temp_reg(offset) \ @@ -713,12 +714,12 @@ static ssize_t set_pwm_auto_channels(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->autofan[nr].config = (data->autofan[nr].config & (~0xe0)) | ZONE_TO_REG(val) ; lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), data->autofan[nr].config); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_pwm_auto_pwm_min(struct device *dev, char *buf, int nr) @@ -733,11 +734,11 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->autofan[nr].min_pwm = PWM_TO_REG(val); lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr), data->autofan[nr].min_pwm); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, char *buf, int nr) @@ -752,7 +753,7 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->autofan[nr].min_off = val; lm85_write_value(client, LM85_REG_AFAN_SPIKE1, data->smooth[0] | data->syncpwm3 @@ -760,7 +761,7 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf, | (data->autofan[1].min_off ? 0x40 : 0) | (data->autofan[2].min_off ? 0x80 : 0) ); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_pwm_auto_pwm_freq(struct device *dev, char *buf, int nr) @@ -775,13 +776,13 @@ static ssize_t set_pwm_auto_pwm_freq(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->autofan[nr].freq = FREQ_TO_REG(val); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), (data->zone[nr].range << 4) | data->autofan[nr].freq ); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define pwm_auto(offset) \ @@ -857,7 +858,7 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf, int min; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); min = TEMP_FROM_REG(data->zone[nr].limit); data->zone[nr].off_desired = TEMP_TO_REG(val); data->zone[nr].hyst = HYST_TO_REG(min - val); @@ -871,7 +872,7 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf, (data->zone[2].hyst << 4) ); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_auto_temp_min(struct device *dev, char *buf, int nr) @@ -886,7 +887,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->zone[nr].limit = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr), data->zone[nr].limit); @@ -913,7 +914,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf, (data->zone[2].hyst << 4) ); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_auto_temp_max(struct device *dev, char *buf, int nr) @@ -930,7 +931,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf, int min; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); min = TEMP_FROM_REG(data->zone[nr].limit); data->zone[nr].max_desired = TEMP_TO_REG(val); data->zone[nr].range = RANGE_TO_REG( @@ -938,7 +939,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf, lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), ((data->zone[nr].range & 0x0f) << 4) | (data->autofan[nr].freq & 0x07)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_auto_temp_crit(struct device *dev, char *buf, int nr) @@ -953,11 +954,11 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->zone[nr].critical = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr), data->zone[nr].critical); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define temp_auto(offset) \ @@ -1149,7 +1150,7 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, /* Fill in the remaining client fields */ data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -1368,7 +1369,7 @@ static struct lm85_data *lm85_update_device(struct device *dev) struct lm85_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if ( !data->valid || time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL) ) { @@ -1571,7 +1572,7 @@ static struct lm85_data *lm85_update_device(struct device *dev) data->valid = 1; - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 6ba34c302d8d..e229daf666de 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -60,6 +60,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> /* * Addresses to scan @@ -176,7 +177,7 @@ static struct i2c_driver lm87_driver = { struct lm87_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -253,11 +254,11 @@ static void set_in_min(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val, data->in_scale[nr]); lm87_write_value(client, nr<6 ? LM87_REG_IN_MIN(nr) : LM87_REG_AIN_MIN(nr-6), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static void set_in_max(struct device *dev, const char *buf, int nr) @@ -266,11 +267,11 @@ static void set_in_max(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val, data->in_scale[nr]); lm87_write_value(client, nr<6 ? LM87_REG_IN_MAX(nr) : LM87_REG_AIN_MAX(nr-6), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } #define set_in(offset) \ @@ -327,10 +328,10 @@ static void set_temp_low(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_low[nr] = TEMP_TO_REG(val); lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static void set_temp_high(struct device *dev, const char *buf, int nr) @@ -339,10 +340,10 @@ static void set_temp_high(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_high[nr] = TEMP_TO_REG(val); lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } #define set_temp(offset) \ @@ -411,11 +412,11 @@ static void set_fan_min(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } /* Note: we save and restore the fan minimum here, because its value is @@ -431,7 +432,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long min; u8 reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], FAN_DIV_FROM_REG(data->fan_div[nr])); @@ -441,7 +442,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -459,7 +460,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, data->fan_min[nr] = FAN_TO_REG(min, val); lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -522,10 +523,10 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->aout = AOUT_TO_REG(val); lm87_write_value(client, LM87_REG_AOUT, data->aout); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); @@ -589,7 +590,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields */ strlcpy(new_client->name, "lm87", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -744,7 +745,7 @@ static struct lm87_data *lm87_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm87_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { int i, j; @@ -813,7 +814,7 @@ static struct lm87_data *lm87_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 5679464447cc..d9eeaf7585bd 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -78,6 +78,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* * Addresses to scan @@ -201,7 +202,7 @@ static struct i2c_driver lm90_driver = { struct lm90_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ int kind; @@ -247,13 +248,13 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, long val = simple_strtol(buf, NULL, 10); int nr = attr->index; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (data->kind == adt7461) data->temp8[nr] = TEMP1_TO_REG_ADT7461(val); else data->temp8[nr] = TEMP1_TO_REG(val); i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -281,7 +282,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, long val = simple_strtol(buf, NULL, 10); int nr = attr->index; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (data->kind == adt7461) data->temp11[nr] = TEMP2_TO_REG_ADT7461(val); else @@ -290,7 +291,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, data->temp11[nr] >> 8); i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], data->temp11[nr] & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -311,11 +312,11 @@ static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy, long val = simple_strtol(buf, NULL, 10); long hyst; - down(&data->update_lock); + mutex_lock(&data->update_lock); hyst = TEMP1_FROM_REG(data->temp8[3]) - val; i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, HYST_TO_REG(hyst)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -558,7 +559,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; data->kind = kind; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -646,7 +647,7 @@ static struct lm90_data *lm90_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm90_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { u8 oldh, newh, l; @@ -692,7 +693,7 @@ static struct lm90_data *lm90_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index b0c4cb730a7e..197f77226dc4 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -46,6 +46,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> /* The LM92 and MAX6635 have 2 two-state pins for address selection, resulting in 4 possible addresses. */ @@ -96,7 +97,7 @@ static struct i2c_driver lm92_driver; struct lm92_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -114,7 +115,7 @@ static struct lm92_data *lm92_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm92_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { @@ -134,7 +135,7 @@ static struct lm92_data *lm92_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -158,10 +159,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct lm92_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = TEMP_TO_REG(val); \ i2c_smbus_write_word_data(client, reg, swab16(data->value)); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } set_temp(temp1_crit, LM92_REG_TEMP_CRIT); @@ -194,11 +195,11 @@ static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute * struct lm92_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val; i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST, swab16(TEMP_TO_REG(data->temp1_hyst))); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -348,7 +349,7 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the i2c subsystem a new client has arrived */ if ((err = i2c_attach_client(new_client))) diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 3abe330b22ce..b4135b5971f4 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -33,6 +33,7 @@ #include <linux/i2c.h> #include <linux/hwmon.h> #include <linux/err.h> +#include <linux/mutex.h> static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, @@ -104,7 +105,7 @@ static struct i2c_driver max1619_driver = { struct max1619_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -141,10 +142,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct max1619_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -262,7 +263,7 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -330,7 +331,7 @@ static struct max1619_data *max1619_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct max1619_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { dev_dbg(&client->dev, "Updating max1619 data.\n"); @@ -353,7 +354,7 @@ static struct max1619_data *max1619_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index f161e88e3bb6..ae05e483a778 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -43,6 +43,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/io.h> static u8 devid; @@ -183,8 +184,8 @@ static inline u8 PWM_TO_REG(int val, int inv) struct pc87360_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; - struct semaphore update_lock; + struct mutex lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -283,7 +284,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, struct pc87360_data *data = i2c_get_clientdata(client); long fan_min = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index])); /* If it wouldn't fit, change clock divisor */ @@ -300,23 +301,31 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, /* Write new divider, preserve alarm bits */ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index), data->fan_status[attr->index] & 0xF9); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define show_and_set_fan(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan_input, NULL, offset-1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \ - show_fan_min, set_fan_min, offset-1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ - show_fan_div, NULL, offset-1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \ - show_fan_status, NULL, offset-1); -show_and_set_fan(1) -show_and_set_fan(2) -show_and_set_fan(3) +static struct sensor_device_attribute fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2), +}; +static struct sensor_device_attribute fan_status[] = { + SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0), + SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1), + SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2), +}; +static struct sensor_device_attribute fan_div[] = { + SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), + SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), + SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), +}; +static struct sensor_device_attribute fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1), + SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), +}; static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -335,21 +344,20 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, con struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[attr->index] = PWM_TO_REG(val, FAN_CONFIG_INVERT(data->fan_conf, attr->index)); pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index), data->pwm[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define show_and_set_pwm(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \ - show_pwm, set_pwm, offset-1); -show_and_set_pwm(1) -show_and_set_pwm(2) -show_and_set_pwm(3) +static struct sensor_device_attribute pwm[] = { + SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0), + SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1), + SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), +}; static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -386,11 +394,11 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN, data->in_min[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -401,35 +409,67 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX, data->in_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define show_and_set_in(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in_input, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \ - show_in_max, set_in_max, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \ - show_in_status, NULL, offset); -show_and_set_in(0) -show_and_set_in(1) -show_and_set_in(2) -show_and_set_in(3) -show_and_set_in(4) -show_and_set_in(5) -show_and_set_in(6) -show_and_set_in(7) -show_and_set_in(8) -show_and_set_in(9) -show_and_set_in(10) +static struct sensor_device_attribute in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8), + SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9), + SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10), +}; +static struct sensor_device_attribute in_status[] = { + SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0), + SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1), + SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2), + SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3), + SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4), + SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5), + SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6), + SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7), + SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8), + SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9), + SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10), +}; +static struct sensor_device_attribute in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2), + SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3), + SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4), + SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5), + SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6), + SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7), + SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8), + SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9), + SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10), +}; +static struct sensor_device_attribute in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2), + SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3), + SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4), + SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5), + SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6), + SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7), + SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8), + SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9), + SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), +}; static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -473,11 +513,11 @@ static ssize_t set_therm_min(struct device *dev, struct device_attribute *devatt struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN, data->in_min[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -488,11 +528,11 @@ static ssize_t set_therm_max(struct device *dev, struct device_attribute *devatt struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX, data->in_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -503,28 +543,51 @@ static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devat struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT, data->in_crit[attr->index-11]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define show_and_set_therm(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_therm_input, NULL, 11+offset-4); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ - show_therm_min, set_therm_min, 11+offset-4); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ - show_therm_max, set_therm_max, 11+offset-4); \ -static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ - show_therm_crit, set_therm_crit, 11+offset-4); \ -static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ - show_therm_status, NULL, 11+offset-4); -show_and_set_therm(4) -show_and_set_therm(5) -show_and_set_therm(6) +/* the +11 term below reflects the fact that VLM units 11,12,13 are + used in the chip to measure voltage across the thermistors +*/ +static struct sensor_device_attribute therm_input[] = { + SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11), + SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11), + SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11), +}; +static struct sensor_device_attribute therm_status[] = { + SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11), + SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11), + SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11), +}; +static struct sensor_device_attribute therm_min[] = { + SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR, + show_therm_min, set_therm_min, 0+11), + SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR, + show_therm_min, set_therm_min, 1+11), + SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR, + show_therm_min, set_therm_min, 2+11), +}; +static struct sensor_device_attribute therm_max[] = { + SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, + show_therm_max, set_therm_max, 0+11), + SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, + show_therm_max, set_therm_max, 1+11), + SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, + show_therm_max, set_therm_max, 2+11), +}; +static struct sensor_device_attribute therm_crit[] = { + SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR, + show_therm_crit, set_therm_crit, 0+11), + SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR, + show_therm_crit, set_therm_crit, 1+11), + SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR, + show_therm_crit, set_therm_crit, 2+11), +}; static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) { @@ -592,11 +655,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[attr->index] = TEMP_TO_REG(val); pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN, data->temp_min[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -607,11 +670,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[attr->index] = TEMP_TO_REG(val); pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX, data->temp_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -622,28 +685,48 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devatt struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_crit[attr->index] = TEMP_TO_REG(val); pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT, data->temp_crit[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define show_and_set_temp(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp_input, NULL, offset-1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ - show_temp_min, set_temp_min, offset-1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ - show_temp_max, set_temp_max, offset-1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ - show_temp_crit, set_temp_crit, offset-1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ - show_temp_status, NULL, offset-1); -show_and_set_temp(1) -show_and_set_temp(2) -show_and_set_temp(3) +static struct sensor_device_attribute temp_input[] = { + SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0), + SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1), + SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2), +}; +static struct sensor_device_attribute temp_status[] = { + SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0), + SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1), + SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2), +}; +static struct sensor_device_attribute temp_min[] = { + SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR, + show_temp_min, set_temp_min, 0), + SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR, + show_temp_min, set_temp_min, 1), + SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR, + show_temp_min, set_temp_min, 2), +}; +static struct sensor_device_attribute temp_max[] = { + SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 0), + SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 1), + SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 2), +}; +static struct sensor_device_attribute temp_crit[] = { + SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR, + show_temp_crit, set_temp_crit, 0), + SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR, + show_temp_crit, set_temp_crit, 1), + SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR, + show_temp_crit, set_temp_crit, 2), +}; static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf) { @@ -749,22 +832,24 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses static int pc87360_detect(struct i2c_adapter *adapter) { int i; - struct i2c_client *new_client; + struct i2c_client *client; struct pc87360_data *data; int err = 0; const char *name = "pc87360"; int use_thermistors = 0; + struct device *dev; if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) return -ENOMEM; - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - init_MUTEX(&data->lock); - new_client->adapter = adapter; - new_client->driver = &pc87360_driver; - new_client->flags = 0; + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + mutex_init(&data->lock); + client->adapter = adapter; + client->driver = &pc87360_driver; + client->flags = 0; data->fannr = 2; data->innr = 0; @@ -792,15 +877,15 @@ static int pc87360_detect(struct i2c_adapter *adapter) break; } - strcpy(new_client->name, name); + strlcpy(client->name, name, sizeof(client->name)); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); for (i = 0; i < 3; i++) { if (((data->address[i] = extra_isa[i])) && !request_region(extra_isa[i], PC87360_EXTENT, pc87360_driver.driver.name)) { - dev_err(&new_client->dev, "Region 0x%x-0x%x already " + dev_err(&client->dev, "Region 0x%x-0x%x already " "in use!\n", extra_isa[i], extra_isa[i]+PC87360_EXTENT-1); for (i--; i >= 0; i--) @@ -814,7 +899,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) if (data->fannr) data->fan_conf = confreg[0] | (confreg[1] << 8); - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto ERROR2; /* Use the correct reference voltage @@ -828,7 +913,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) PC87365_REG_TEMP_CONFIG); } data->in_vref = (i&0x02) ? 3025 : 2966; - dev_dbg(&new_client->dev, "Using %s reference voltage\n", + dev_dbg(&client->dev, "Using %s reference voltage\n", (i&0x02) ? "external" : "internal"); data->vid_conf = confreg[3]; @@ -847,154 +932,64 @@ static int pc87360_detect(struct i2c_adapter *adapter) if (devid == 0xe9 && data->address[1]) /* PC87366 */ use_thermistors = confreg[2] & 0x40; - pc87360_init_client(new_client, use_thermistors); + pc87360_init_client(client, use_thermistors); } /* Register sysfs hooks */ - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto ERROR3; } if (data->innr) { - device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr); - - device_create_file(&new_client->dev, &dev_attr_cpu0_vid); - device_create_file(&new_client->dev, &dev_attr_vrm); - device_create_file(&new_client->dev, &dev_attr_alarms_in); + for (i = 0; i < 11; i++) { + device_create_file(dev, &in_input[i].dev_attr); + device_create_file(dev, &in_min[i].dev_attr); + device_create_file(dev, &in_max[i].dev_attr); + device_create_file(dev, &in_status[i].dev_attr); + } + device_create_file(dev, &dev_attr_cpu0_vid); + device_create_file(dev, &dev_attr_vrm); + device_create_file(dev, &dev_attr_alarms_in); } if (data->tempnr) { - device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp1_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr); - - device_create_file(&new_client->dev, &dev_attr_alarms_temp); - } - if (data->tempnr == 3) { - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr); - } - if (data->innr == 14) { - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr); - } - - if (data->fannr) { - if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) { - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_min.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_div.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_status.dev_attr); + for (i = 0; i < data->tempnr; i++) { + device_create_file(dev, &temp_input[i].dev_attr); + device_create_file(dev, &temp_min[i].dev_attr); + device_create_file(dev, &temp_max[i].dev_attr); + device_create_file(dev, &temp_crit[i].dev_attr); + device_create_file(dev, &temp_status[i].dev_attr); } + device_create_file(dev, &dev_attr_alarms_temp); + } - if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) { - device_create_file(&new_client->dev, - &sensor_dev_attr_fan2_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan2_min.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan2_div.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan2_status.dev_attr); + if (data->innr == 14) { + for (i = 0; i < 3; i++) { + device_create_file(dev, &therm_input[i].dev_attr); + device_create_file(dev, &therm_min[i].dev_attr); + device_create_file(dev, &therm_max[i].dev_attr); + device_create_file(dev, &therm_crit[i].dev_attr); + device_create_file(dev, &therm_status[i].dev_attr); } - - if (FAN_CONFIG_CONTROL(data->fan_conf, 0)) - device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr); - if (FAN_CONFIG_CONTROL(data->fan_conf, 1)) - device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr); } - if (data->fannr == 3) { - if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) { - device_create_file(&new_client->dev, - &sensor_dev_attr_fan3_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan3_min.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan3_div.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan3_status.dev_attr); - } - if (FAN_CONFIG_CONTROL(data->fan_conf, 2)) - device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr); + for (i = 0; i < data->fannr; i++) { + if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { + device_create_file(dev, &fan_input[i].dev_attr); + device_create_file(dev, &fan_min[i].dev_attr); + device_create_file(dev, &fan_div[i].dev_attr); + device_create_file(dev, &fan_status[i].dev_attr); + } + if (FAN_CONFIG_CONTROL(data->fan_conf, i)) + device_create_file(dev, &pwm[i].dev_attr); } return 0; ERROR3: - i2c_detach_client(new_client); + i2c_detach_client(client); ERROR2: for (i = 0; i < 3; i++) { if (data->address[i]) { @@ -1033,11 +1028,11 @@ static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, { int res; - down(&(data->lock)); + mutex_lock(&(data->lock)); if (bank != NO_BANK) outb_p(bank, data->address[ldi] + PC87365_REG_BANK); res = inb_p(data->address[ldi] + reg); - up(&(data->lock)); + mutex_unlock(&(data->lock)); return res; } @@ -1045,11 +1040,11 @@ static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, u8 reg, u8 value) { - down(&(data->lock)); + mutex_lock(&(data->lock)); if (bank != NO_BANK) outb_p(bank, data->address[ldi] + PC87365_REG_BANK); outb_p(value, data->address[ldi] + reg); - up(&(data->lock)); + mutex_unlock(&(data->lock)); } static void pc87360_init_client(struct i2c_client *client, int use_thermistors) @@ -1071,7 +1066,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) } nr = data->innr < 11 ? data->innr : 11; - for (i=0; i<nr; i++) { + for (i = 0; i < nr; i++) { if (init >= init_in[i]) { /* Forcibly enable voltage channel */ reg = pc87360_read_value(data, LD_IN, i, @@ -1088,14 +1083,14 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) /* We can't blindly trust the Super-I/O space configuration bit, most BIOS won't set it properly */ - for (i=11; i<data->innr; i++) { + for (i = 11; i < data->innr; i++) { reg = pc87360_read_value(data, LD_IN, i, PC87365_REG_TEMP_STATUS); use_thermistors = use_thermistors || (reg & 0x01); } i = use_thermistors ? 2 : 0; - for (; i<data->tempnr; i++) { + for (; i < data->tempnr; i++) { if (init >= init_temp[i]) { /* Forcibly enable temperature channel */ reg = pc87360_read_value(data, LD_TEMP, i, @@ -1111,7 +1106,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) } if (use_thermistors) { - for (i=11; i<data->innr; i++) { + for (i = 11; i < data->innr; i++) { if (init >= init_in[i]) { /* The pin may already be used by thermal diodes */ @@ -1221,7 +1216,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) struct pc87360_data *data = i2c_get_clientdata(client); u8 i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { dev_dbg(&client->dev, "Data update\n"); @@ -1321,7 +1316,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 8be5189d9bd9..6f3fda73f70c 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -60,6 +60,7 @@ #include <linux/err.h> #include <linux/init.h> #include <linux/jiffies.h> +#include <linux/mutex.h> #include <asm/io.h> @@ -167,9 +168,9 @@ static inline u8 DIV_TO_REG(int val) struct sis5595_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ char maxins; /* == 3 if temp enabled, otherwise == 4 */ @@ -192,8 +193,8 @@ static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */ static int sis5595_detect(struct i2c_adapter *adapter); static int sis5595_detach_client(struct i2c_client *client); -static int sis5595_read_value(struct i2c_client *client, u8 register); -static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value); +static int sis5595_read_value(struct i2c_client *client, u8 reg); +static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value); static struct sis5595_data *sis5595_update_device(struct device *dev); static void sis5595_init_client(struct i2c_client *client); @@ -231,10 +232,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf, struct sis5595_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val); sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -245,10 +246,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf, struct sis5595_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val); sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -310,10 +311,10 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, struct sis5595_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_over = TEMP_TO_REG(val); sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -329,10 +330,10 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, struct sis5595_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst = TEMP_TO_REG(val); sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -364,10 +365,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct sis5595_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -390,7 +391,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long val = simple_strtoul(buf, NULL, 10); int reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); reg = sis5595_read_value(client, SIS5595_REG_FANDIV); @@ -403,7 +404,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, default: dev_err(&client->dev, "fan_div value %ld not " "supported. Choose one of 1, 2, 4 or 8!\n", val); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -419,7 +420,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -527,7 +528,7 @@ static int sis5595_detect(struct i2c_adapter *adapter) new_client = &data->client; new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); i2c_set_clientdata(new_client, data); new_client->adapter = adapter; new_client->driver = &sis5595_driver; @@ -548,7 +549,7 @@ static int sis5595_detect(struct i2c_adapter *adapter) strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -635,20 +636,20 @@ static int sis5595_read_value(struct i2c_client *client, u8 reg) int res; struct sis5595_data *data = i2c_get_clientdata(client); - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return res; } static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value) { struct sis5595_data *data = i2c_get_clientdata(client); - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return 0; } @@ -667,7 +668,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) struct sis5595_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -707,7 +708,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 8663bbbe97f5..b6086186d225 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -35,6 +35,7 @@ #include <linux/hwmon.h> #include <linux/err.h> #include <linux/init.h> +#include <linux/mutex.h> #include <asm/io.h> /* Address is autodetected, there is no default value */ @@ -92,9 +93,9 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80}; struct smsc47b397_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; - struct semaphore update_lock; + struct mutex update_lock; unsigned long last_updated; /* in jiffies */ int valid; @@ -108,10 +109,10 @@ static int smsc47b397_read_value(struct i2c_client *client, u8 reg) struct smsc47b397_data *data = i2c_get_clientdata(client); int res; - down(&data->lock); + mutex_lock(&data->lock); outb(reg, client->addr); res = inb_p(client->addr + 1); - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -121,7 +122,7 @@ static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) struct smsc47b397_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { dev_dbg(&client->dev, "starting device update...\n"); @@ -144,7 +145,7 @@ static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) dev_dbg(&client->dev, "... device update complete\n"); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -254,14 +255,14 @@ static int smsc47b397_detect(struct i2c_adapter *adapter) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = &smsc47b397_driver; new_client->flags = 0; strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); if ((err = i2c_attach_client(new_client))) goto error_free; diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index d1e3ec0fe4df..7732aec54594 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -34,6 +34,7 @@ #include <linux/hwmon.h> #include <linux/err.h> #include <linux/init.h> +#include <linux/mutex.h> #include <asm/io.h> /* Address is autodetected, there is no default value */ @@ -102,9 +103,9 @@ superio_exit(void) struct smsc47m1_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; - struct semaphore update_lock; + struct mutex update_lock; unsigned long last_updated; /* In jiffies */ u8 fan[2]; /* Register value */ @@ -188,18 +189,18 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct smsc47m1_data *data = i2c_get_clientdata(client); long rpmdiv, val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]); if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) { - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), data->fan_preload[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -220,14 +221,14 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, if (new_div == old_div) /* No change */ return count; - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (new_div) { case 1: data->fan_div[nr] = 0; break; case 2: data->fan_div[nr] = 1; break; case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -241,7 +242,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), data->fan_preload[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -257,12 +258,12 @@ static ssize_t set_pwm(struct device *dev, const char *buf, if (val < 0 || val > 255) return -EINVAL; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr] &= 0x81; /* Preserve additional bits */ data->pwm[nr] |= PWM_TO_REG(val); smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), data->pwm[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -278,12 +279,12 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, if (val != 0 && val != 1) return -EINVAL; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr] &= 0xFE; /* preserve the other bits */ data->pwm[nr] |= !val; smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), data->pwm[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -408,13 +409,13 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = &smsc47m1_driver; new_client->flags = 0; strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* If no function is properly configured, there's no point in actually registering the chip. */ @@ -512,17 +513,17 @@ static int smsc47m1_read_value(struct i2c_client *client, u8 reg) { int res; - down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); res = inb_p(client->addr + reg); - up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); return res; } static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value) { - down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); outb_p(value, client->addr + reg); - up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); } static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, @@ -531,7 +532,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smsc47m1_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { int i; @@ -558,7 +559,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, data->last_updated = jiffies; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index cb01848729b5..166298f1f190 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -39,6 +39,7 @@ #include <linux/hwmon.h> #include <linux/err.h> #include <linux/init.h> +#include <linux/mutex.h> #include <asm/io.h> @@ -296,7 +297,7 @@ static inline long TEMP_FROM_REG10(u16 val) struct via686a_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -355,11 +356,11 @@ static ssize_t set_in_min(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val, nr); via686a_write_value(client, VIA686A_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_in_max(struct device *dev, const char *buf, @@ -368,11 +369,11 @@ static ssize_t set_in_max(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val, nr); via686a_write_value(client, VIA686A_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_in_offset(offset) \ @@ -432,11 +433,11 @@ static ssize_t set_temp_over(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_over[nr] = TEMP_TO_REG(val); via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr], data->temp_over[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_hyst(struct device *dev, const char *buf, @@ -445,11 +446,11 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst[nr] = TEMP_TO_REG(val); via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr], data->temp_hyst[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_temp_offset(offset) \ @@ -508,10 +509,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_fan_div(struct device *dev, const char *buf, @@ -521,12 +522,12 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, int val = simple_strtol(buf, NULL, 10); int old; - down(&data->update_lock); + mutex_lock(&data->update_lock); old = via686a_read_value(client, VIA686A_REG_FANDIV); data->fan_div[nr] = DIV_TO_REG(val); old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); via686a_write_value(client, VIA686A_REG_FANDIV, old); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -639,7 +640,7 @@ static int via686a_detect(struct i2c_adapter *adapter) strlcpy(new_client->name, client_name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) goto exit_free; @@ -733,7 +734,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) struct via686a_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -788,7 +789,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 271e9cb9532c..686f3deb3093 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -35,6 +35,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/io.h> static int force_addr; @@ -148,7 +149,7 @@ static inline u8 FAN_TO_REG(long rpm, int div) struct vt8231_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; struct class_device *class_dev; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -223,10 +224,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -239,10 +240,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -281,11 +282,11 @@ static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, 0, 255); vt8231_write_value(client, regvoltmin[5], data->in_min[5]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -296,11 +297,11 @@ static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, 0, 255); vt8231_write_value(client, regvoltmax[5], data->in_max[5]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -351,10 +352,10 @@ static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); vt8231_write_value(client, regtempmax[0], data->temp_max[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, @@ -364,10 +365,10 @@ static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); vt8231_write_value(client, regtempmin[0], data->temp_min[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -407,10 +408,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, @@ -422,10 +423,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -520,10 +521,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -539,7 +540,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, long min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (val) { case 1: data->fan_div[nr] = 0; break; case 2: data->fan_div[nr] = 1; break; @@ -548,7 +549,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, default: dev_err(&client->dev, "fan_div value %ld not supported." "Choose one of 1, 2, 4 or 8!\n", val); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -558,7 +559,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); vt8231_write_value(client, VT8231_REG_FANDIV, old); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -660,7 +661,7 @@ int vt8231_detect(struct i2c_adapter *adapter) /* Fill in the remaining client fields and put into the global list */ strlcpy(client->name, "vt8231", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(client))) @@ -745,7 +746,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev) int i; u16 low; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -804,7 +805,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 12d79f5e4900..b6bd5685fd38 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -42,7 +42,9 @@ #include <linux/i2c.h> #include <linux/i2c-isa.h> #include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/io.h> #include "lm75.h" @@ -177,9 +179,9 @@ temp1_to_reg(int temp) struct w83627ehf_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -230,7 +232,7 @@ static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg) struct w83627ehf_data *data = i2c_get_clientdata(client); int res, word_sized = is_word_sized(reg); - down(&data->lock); + mutex_lock(&data->lock); w83627ehf_set_bank(client, reg); outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); @@ -242,7 +244,7 @@ static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg) } w83627ehf_reset_bank(client, reg); - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -252,7 +254,7 @@ static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value) struct w83627ehf_data *data = i2c_get_clientdata(client); int word_sized = is_word_sized(reg); - down(&data->lock); + mutex_lock(&data->lock); w83627ehf_set_bank(client, reg); outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); @@ -264,7 +266,7 @@ static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value) outb_p(value & 0xff, client->addr + DATA_REG_OFFSET); w83627ehf_reset_bank(client, reg); - up(&data->lock); + mutex_unlock(&data->lock); return 0; } @@ -322,7 +324,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) struct w83627ehf_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { @@ -397,7 +399,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -407,9 +409,12 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) #define show_fan_reg(reg) \ static ssize_t \ -show_##reg(struct device *dev, char *buf, int nr) \ +show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ struct w83627ehf_data *data = w83627ehf_update_device(dev); \ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + int nr = sensor_attr->index; \ return sprintf(buf, "%d\n", \ fan_from_reg(data->reg[nr], \ div_from_reg(data->fan_div[nr]))); \ @@ -418,23 +423,28 @@ show_fan_reg(fan); show_fan_reg(fan_min); static ssize_t -show_fan_div(struct device *dev, char *buf, int nr) +show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) { struct w83627ehf_data *data = w83627ehf_update_device(dev); - return sprintf(buf, "%u\n", - div_from_reg(data->fan_div[nr])); + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr])); } static ssize_t -store_fan_min(struct device *dev, const char *buf, size_t count, int nr) +store_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct w83627ehf_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; unsigned int val = simple_strtoul(buf, NULL, 10); unsigned int reg; u8 new_div; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!val) { /* No min limit, alarm disabled */ data->fan_min[nr] = 255; @@ -482,63 +492,46 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) } w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr], data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } -#define sysfs_fan_offset(offset) \ -static ssize_t \ -show_reg_fan_##offset(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_fan(dev, buf, offset-1); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_reg_fan_##offset, NULL); +static struct sensor_device_attribute sda_fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), + SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), +}; -#define sysfs_fan_min_offset(offset) \ -static ssize_t \ -show_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_fan_min(dev, buf, offset-1); \ -} \ -static ssize_t \ -store_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return store_fan_min(dev, buf, count, offset-1); \ -} \ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_reg_fan##offset##_min, \ - store_reg_fan##offset##_min); +static struct sensor_device_attribute sda_fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, + store_fan_min, 0), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, + store_fan_min, 1), + SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, + store_fan_min, 2), + SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, + store_fan_min, 3), + SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, + store_fan_min, 4), +}; -#define sysfs_fan_div_offset(offset) \ -static ssize_t \ -show_reg_fan##offset##_div(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_fan_div(dev, buf, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ - show_reg_fan##offset##_div, NULL); - -sysfs_fan_offset(1); -sysfs_fan_min_offset(1); -sysfs_fan_div_offset(1); -sysfs_fan_offset(2); -sysfs_fan_min_offset(2); -sysfs_fan_div_offset(2); -sysfs_fan_offset(3); -sysfs_fan_min_offset(3); -sysfs_fan_div_offset(3); -sysfs_fan_offset(4); -sysfs_fan_min_offset(4); -sysfs_fan_div_offset(4); -sysfs_fan_offset(5); -sysfs_fan_min_offset(5); -sysfs_fan_div_offset(5); +static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), + SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), + SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), + SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3), + SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), +}; + +static void device_create_file_fan(struct device *dev, int i) +{ + device_create_file(dev, &sda_fan_input[i].dev_attr); + device_create_file(dev, &sda_fan_div[i].dev_attr); + device_create_file(dev, &sda_fan_min[i].dev_attr); +} #define show_temp1_reg(reg) \ static ssize_t \ @@ -561,27 +554,24 @@ store_temp1_##reg(struct device *dev, struct device_attribute *attr, \ struct w83627ehf_data *data = i2c_get_clientdata(client); \ u32 val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->temp1_##reg = temp1_to_reg(val); \ w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ data->temp1_##reg); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_temp1_reg(OVER, max); store_temp1_reg(HYST, max_hyst); -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL); -static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR, - show_temp1_max, store_temp1_max); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR, - show_temp1_max_hyst, store_temp1_max_hyst); - #define show_temp_reg(reg) \ static ssize_t \ -show_##reg (struct device *dev, char *buf, int nr) \ +show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ struct w83627ehf_data *data = w83627ehf_update_device(dev); \ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + int nr = sensor_attr->index; \ return sprintf(buf, "%d\n", \ LM75_TEMP_FROM_REG(data->reg[nr])); \ } @@ -591,55 +581,42 @@ show_temp_reg(temp_max_hyst); #define store_temp_reg(REG, reg) \ static ssize_t \ -store_##reg (struct device *dev, const char *buf, size_t count, int nr) \ +store_##reg(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct w83627ehf_data *data = i2c_get_clientdata(client); \ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + int nr = sensor_attr->index; \ u32 val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->reg[nr] = LM75_TEMP_TO_REG(val); \ w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \ data->reg[nr]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_temp_reg(OVER, temp_max); store_temp_reg(HYST, temp_max_hyst); -#define sysfs_temp_offset(offset) \ -static ssize_t \ -show_reg_temp##offset (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_temp(dev, buf, offset - 2); \ -} \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_reg_temp##offset, NULL); - -#define sysfs_temp_reg_offset(reg, offset) \ -static ssize_t \ -show_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_temp_##reg(dev, buf, offset - 2); \ -} \ -static ssize_t \ -store_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return store_temp_##reg(dev, buf, count, offset - 2); \ -} \ -static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \ - show_reg_temp##offset##_##reg, \ - store_reg_temp##offset##_##reg); - -sysfs_temp_offset(2); -sysfs_temp_reg_offset(max, 2); -sysfs_temp_reg_offset(max_hyst, 2); -sysfs_temp_offset(3); -sysfs_temp_reg_offset(max, 3); -sysfs_temp_reg_offset(max_hyst, 3); +static struct sensor_device_attribute sda_temp[] = { + SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0), + SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0), + SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1), + SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max, + store_temp1_max, 0), + SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, + store_temp_max, 0), + SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, + store_temp_max, 1), + SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst, + store_temp1_max_hyst, 0), + SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 0), + SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 1), +}; /* * Driver and client management @@ -673,6 +650,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) { struct i2c_client *client; struct w83627ehf_data *data; + struct device *dev; int i, err = 0; if (!request_region(address + REGION_OFFSET, REGION_LENGTH, @@ -689,14 +667,15 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) client = &data->client; i2c_set_clientdata(client, data); client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); client->adapter = adapter; client->driver = &w83627ehf_driver; client->flags = 0; + dev = &client->dev; strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the i2c layer a new client has arrived */ if ((err = i2c_attach_client(client))) @@ -720,42 +699,18 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) data->has_fan |= (1 << 4); /* Register sysfs hooks */ - data->class_dev = hwmon_device_register(&client->dev); + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto exit_detach; } - device_create_file(&client->dev, &dev_attr_fan1_input); - device_create_file(&client->dev, &dev_attr_fan1_min); - device_create_file(&client->dev, &dev_attr_fan1_div); - device_create_file(&client->dev, &dev_attr_fan2_input); - device_create_file(&client->dev, &dev_attr_fan2_min); - device_create_file(&client->dev, &dev_attr_fan2_div); - device_create_file(&client->dev, &dev_attr_fan3_input); - device_create_file(&client->dev, &dev_attr_fan3_min); - device_create_file(&client->dev, &dev_attr_fan3_div); - - if (data->has_fan & (1 << 3)) { - device_create_file(&client->dev, &dev_attr_fan4_input); - device_create_file(&client->dev, &dev_attr_fan4_min); - device_create_file(&client->dev, &dev_attr_fan4_div); - } - if (data->has_fan & (1 << 4)) { - device_create_file(&client->dev, &dev_attr_fan5_input); - device_create_file(&client->dev, &dev_attr_fan5_min); - device_create_file(&client->dev, &dev_attr_fan5_div); + for (i = 0; i < 5; i++) { + if (data->has_fan & (1 << i)) + device_create_file_fan(dev, i); } - - device_create_file(&client->dev, &dev_attr_temp1_input); - device_create_file(&client->dev, &dev_attr_temp1_max); - device_create_file(&client->dev, &dev_attr_temp1_max_hyst); - device_create_file(&client->dev, &dev_attr_temp2_input); - device_create_file(&client->dev, &dev_attr_temp2_max); - device_create_file(&client->dev, &dev_attr_temp2_max_hyst); - device_create_file(&client->dev, &dev_attr_temp3_input); - device_create_file(&client->dev, &dev_attr_temp3_max); - device_create_file(&client->dev, &dev_attr_temp3_max_hyst); + for (i = 0; i < ARRAY_SIZE(sda_temp); i++) + device_create_file(dev, &sda_temp[i].dev_attr); return 0; diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 7ea441d4da63..71fb7f1af8f5 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -28,6 +28,7 @@ w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) + w83687thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) For other winbond chips, and for i2c support in the above chips, @@ -46,6 +47,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/io.h> #include "lm75.h" @@ -62,7 +64,7 @@ MODULE_PARM_DESC(force_i2c, static unsigned short address; /* Insmod parameters */ -enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf }; +enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; static int reset; module_param(reset, bool, 0); @@ -100,6 +102,10 @@ static int VAL; /* The value to read/write */ #define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ #define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ +#define W83687THF_VID_EN 0x29 /* w83687thf only */ +#define W83687THF_VID_CFG 0xF0 /* w83687thf only */ +#define W83687THF_VID_DATA 0xF1 /* w83687thf only */ + static inline void superio_outb(int reg, int val) { @@ -138,6 +144,7 @@ superio_exit(void) #define W627THF_DEVID 0x82 #define W697_DEVID 0x60 #define W637_DEVID 0x70 +#define W687THF_DEVID 0x85 #define WINB_ACT_REG 0x30 #define WINB_BASE_REG 0x60 /* Constants specified below */ @@ -201,11 +208,11 @@ superio_exit(void) #define W83627HF_REG_PWM1 0x5A #define W83627HF_REG_PWM2 0x5B -#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */ -#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */ -#define W83627THF_REG_PWM3 0x11 /* 637HF too */ +#define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ +#define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ +#define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ -#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too */ +#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF/687THF too */ static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, @@ -285,10 +292,10 @@ static inline u8 DIV_TO_REG(long val) struct w83627hf_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -318,16 +325,15 @@ struct w83627hf_data { Default = 3435. Other Betas unimplemented */ u8 vrm; - u8 vrm_ovt; /* Register value, 627thf & 637hf only */ + u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ }; static int w83627hf_detect(struct i2c_adapter *adapter); static int w83627hf_detach_client(struct i2c_client *client); -static int w83627hf_read_value(struct i2c_client *client, u16 register); -static int w83627hf_write_value(struct i2c_client *client, u16 register, - u16 value); +static int w83627hf_read_value(struct i2c_client *client, u16 reg); +static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value); static struct w83627hf_data *w83627hf_update_device(struct device *dev); static void w83627hf_init_client(struct i2c_client *client); @@ -360,12 +366,12 @@ store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ \ val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_##reg[nr] = IN_TO_REG(val); \ w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \ data->in_##reg[nr]); \ \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_in_reg(MIN, min) @@ -413,7 +419,8 @@ static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg) long in0; if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type)) + (w83627thf == data->type || w83637hf == data->type + || w83687thf == data->type)) /* use VRM9 calculation */ in0 = (long)((reg * 488 + 70000 + 50) / 100); @@ -451,10 +458,11 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type)) + (w83627thf == data->type || w83637hf == data->type + || w83687thf == data->type)) /* use VRM9 calculation */ data->in_min[0] = @@ -465,7 +473,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a data->in_min[0] = IN_TO_REG(val); w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -478,10 +486,11 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type)) + (w83627thf == data->type || w83637hf == data->type + || w83687thf == data->type)) /* use VRM9 calculation */ data->in_max[0] = @@ -492,7 +501,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a data->in_max[0] = IN_TO_REG(val); w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -529,13 +538,13 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr - 1] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr), data->fan_min[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -597,7 +606,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ \ val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ \ if (nr >= 2) { /* TEMP2 and TEMP3 */ \ data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ @@ -609,7 +618,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ data->temp_##reg); \ } \ \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_temp_reg(OVER, max); @@ -718,7 +727,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ data->beep_mask = BEEP_MASK_TO_REG(val); @@ -736,7 +745,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, val2 | data->beep_enable << 7); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -783,7 +792,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) u8 reg; unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); /* Save fan_min */ min = FAN_FROM_REG(data->fan_min[nr], @@ -805,7 +814,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -848,7 +857,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (data->type == w83627thf) { /* bits 0-3 are reserved in 627THF */ @@ -865,7 +874,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) data->pwm[nr - 1]); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -907,7 +916,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (val) { case 1: /* PII/Celeron diode */ @@ -941,7 +950,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) break; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -980,7 +989,8 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr) if(val != W627_DEVID && val != W627THF_DEVID && val != W697_DEVID && - val != W637_DEVID) { + val != W637_DEVID && + val != W687THF_DEVID) { superio_exit(); return -ENODEV; } @@ -1034,6 +1044,8 @@ static int w83627hf_detect(struct i2c_adapter *adapter) kind = w83627thf; else if(val == W637_DEVID) kind = w83637hf; + else if (val == W687THF_DEVID) + kind = w83687thf; else { dev_info(&adapter->dev, "Unsupported chip (dev_id=0x%02X).\n", val); @@ -1057,7 +1069,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = &w83627hf_driver; new_client->flags = 0; @@ -1071,13 +1083,15 @@ static int w83627hf_detect(struct i2c_adapter *adapter) client_name = "w83697hf"; } else if (kind == w83637hf) { client_name = "w83637hf"; + } else if (kind == w83687thf) { + client_name = "w83687thf"; } /* Fill in the remaining client fields and put into the global list */ strlcpy(new_client->name, client_name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -1106,7 +1120,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) device_create_file_in(new_client, 2); device_create_file_in(new_client, 3); device_create_file_in(new_client, 4); - if (kind != w83627thf && kind != w83637hf) { + if (kind == w83627hf || kind == w83697hf) { device_create_file_in(new_client, 5); device_create_file_in(new_client, 6); } @@ -1139,7 +1153,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) device_create_file_pwm(new_client, 1); device_create_file_pwm(new_client, 2); - if (kind == w83627thf || kind == w83637hf) + if (kind == w83627thf || kind == w83637hf || kind == w83687thf) device_create_file_pwm(new_client, 3); device_create_file_sensor(new_client, 1); @@ -1187,7 +1201,7 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg) struct w83627hf_data *data = i2c_get_clientdata(client); int res, word_sized; - down(&data->lock); + mutex_lock(&data->lock); word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) && (((reg & 0x00ff) == 0x50) @@ -1213,7 +1227,7 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg) client->addr + W83781D_ADDR_REG_OFFSET); outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); } - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -1247,12 +1261,39 @@ exit: return res; } +static int w83687thf_read_vid(struct i2c_client *client) +{ + int res = 0xff; + + superio_enter(); + superio_select(W83627HF_LD_HWM); + + /* Make sure these GPIO pins are enabled */ + if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { + dev_dbg(&client->dev, "VID disabled, no VID function\n"); + goto exit; + } + + /* Make sure the pins are configured for input */ + if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { + dev_dbg(&client->dev, "VID configured as output, " + "no VID function\n"); + goto exit; + } + + res = superio_inb(W83687THF_VID_DATA) & 0x3f; + +exit: + superio_exit(); + return res; +} + static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) { struct w83627hf_data *data = i2c_get_clientdata(client); int word_sized; - down(&data->lock); + mutex_lock(&data->lock); word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) && (((reg & 0x00ff) == 0x53) @@ -1277,7 +1318,7 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) client->addr + W83781D_ADDR_REG_OFFSET); outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); } - up(&data->lock); + mutex_unlock(&data->lock); return 0; } @@ -1324,10 +1365,13 @@ static void w83627hf_init_client(struct i2c_client *client) data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); } else if (w83627thf == data->type) { data->vid = w83627thf_read_gpio5(client); + } else if (w83687thf == data->type) { + data->vid = w83687thf_read_vid(client); } /* Read VRM & OVT Config only once */ - if (w83627thf == data->type || w83637hf == data->type) { + if (w83627thf == data->type || w83637hf == data->type + || w83687thf == data->type) { data->vrm_ovt = w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); } @@ -1387,14 +1431,14 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) struct w83627hf_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { for (i = 0; i <= 8; i++) { /* skip missing sensors */ if (((data->type == w83697hf) && (i == 1)) || - ((data->type == w83627thf || data->type == w83637hf) + ((data->type != w83627hf && data->type != w83697hf) && (i == 5 || i == 6))) continue; data->in[i] = @@ -1470,7 +1514,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 64c1f8af5bb2..e4c700356c44 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -42,6 +42,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-vid.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/io.h> #include "lm75.h" @@ -56,6 +57,10 @@ I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f); 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 one to reset chip on load"); + static int init = 1; module_param(init, bool, 0); MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); @@ -226,10 +231,10 @@ DIV_TO_REG(long val, enum chips type) struct w83781d_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -267,9 +272,8 @@ static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter); static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); static int w83781d_detach_client(struct i2c_client *client); -static int w83781d_read_value(struct i2c_client *client, u16 register); -static int w83781d_write_value(struct i2c_client *client, u16 register, - u16 value); +static int w83781d_read_value(struct i2c_client *client, u16 reg); +static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value); static struct w83781d_data *w83781d_update_device(struct device *dev); static void w83781d_init_client(struct i2c_client *client); @@ -311,11 +315,11 @@ static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count \ val = simple_strtoul(buf, NULL, 10) / 10; \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_##reg[nr] = IN_TO_REG(val); \ w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_in_reg(MIN, min); @@ -381,13 +385,13 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr - 1] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); w83781d_write_value(client, W83781D_REG_FAN_MIN(nr), data->fan_min[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -446,7 +450,7 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou \ val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ \ if (nr >= 2) { /* TEMP2 and TEMP3 */ \ data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ @@ -458,7 +462,7 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou data->temp_##reg); \ } \ \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_temp_reg(OVER, max); @@ -571,7 +575,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ data->beep_mask = BEEP_MASK_TO_REG(val, data->type); @@ -592,7 +596,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, w83781d_write_value(client, W83781D_REG_BEEP_INTS2, val2 | data->beep_enable << 7); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -637,7 +641,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) u8 reg; unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); /* Save fan_min */ min = FAN_FROM_REG(data->fan_min[nr], @@ -662,7 +666,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -709,10 +713,10 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr - 1] = PWM_TO_REG(val); w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -725,7 +729,7 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (val) { case 0: @@ -742,11 +746,11 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) break; default: - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -808,7 +812,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (val) { case 1: /* PII/Celeron diode */ @@ -841,7 +845,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) break; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1073,7 +1077,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; new_client->flags = 0; @@ -1178,7 +1182,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -1325,7 +1329,7 @@ w83781d_read_value(struct i2c_client *client, u16 reg) int res, word_sized, bank; struct i2c_client *cl; - down(&data->lock); + mutex_lock(&data->lock); if (i2c_is_isa_client(client)) { word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) @@ -1383,7 +1387,7 @@ w83781d_read_value(struct i2c_client *client, u16 reg) if (bank > 2) i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); } - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -1394,7 +1398,7 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) int word_sized, bank; struct i2c_client *cl; - down(&data->lock); + mutex_lock(&data->lock); if (i2c_is_isa_client(client)) { word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) @@ -1447,7 +1451,7 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) if (bank > 2) i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); } - up(&data->lock); + mutex_unlock(&data->lock); return 0; } @@ -1459,8 +1463,17 @@ w83781d_init_client(struct i2c_client *client) int type = data->type; u8 tmp; - if (init && type != as99127f) { /* this resets registers we don't have + if (reset && type != as99127f) { /* this resets registers we don't have documentation for on the as99127f */ + /* Resetting the chip has been the default for a long time, + but it causes the BIOS initializations (fan clock dividers, + thermal sensor types...) to be lost, so it is now optional. + It might even go away if nobody reports it as being useful, + as I see very little reason why this would be needed at + all. */ + dev_info(&client->dev, "If reset=1 solved a problem you were " + "having, please report!\n"); + /* save these registers */ i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); p = w83781d_read_value(client, W83781D_REG_PWMCLK12); @@ -1477,6 +1490,13 @@ w83781d_init_client(struct i2c_client *client) w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); } + /* Disable power-on abnormal beep, as advised by the datasheet. + Already done if reset=1. */ + if (init && !reset && type != as99127f) { + i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); + w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); + } + data->vrm = vid_which_vrm(); if ((type != w83781d) && (type != as99127f)) { @@ -1533,7 +1553,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) struct w83781d_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1641,7 +1661,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index a2f6bb676235..6865c64d8a51 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -43,6 +43,7 @@ #include <linux/hwmon.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 }; @@ -271,7 +272,7 @@ struct w83792d_data { struct class_device *class_dev; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -382,30 +383,40 @@ static ssize_t store_in_##reg (struct device *dev, \ store_in_reg(MIN, min); store_in_reg(MAX, max); -#define sysfs_in_reg(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \ - NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, store_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, store_in_max, offset); - -sysfs_in_reg(0); -sysfs_in_reg(1); -sysfs_in_reg(2); -sysfs_in_reg(3); -sysfs_in_reg(4); -sysfs_in_reg(5); -sysfs_in_reg(6); -sysfs_in_reg(7); -sysfs_in_reg(8); - -#define device_create_file_in(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \ -} while (0) +static struct sensor_device_attribute sda_in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), +}; +static struct sensor_device_attribute sda_in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), + SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), + SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), + SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), + SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), + SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), + SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), +}; +static struct sensor_device_attribute sda_in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), + SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), + SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), + SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), + SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), + SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), + SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), +}; + #define show_fan_reg(reg) \ static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ @@ -486,28 +497,33 @@ store_fan_div(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_fan(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ - offset); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, store_fan_div, offset); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, store_fan_min, offset); - -sysfs_fan(1); -sysfs_fan(2); -sysfs_fan(3); -sysfs_fan(4); -sysfs_fan(5); -sysfs_fan(6); -sysfs_fan(7); - -#define device_create_file_fan(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \ -} while (0) +static struct sensor_device_attribute sda_fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3), + SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4), + SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5), + SENSOR_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6), + SENSOR_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7), +}; +static struct sensor_device_attribute sda_fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2), + SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3), + SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4), + SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 5), + SENSOR_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 6), + SENSOR_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 7), +}; +static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1), + SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2), + SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3), + SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4), + SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 5), + SENSOR_ATTR(fan6_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 6), + SENSOR_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7), +}; /* read/write the temperature1, includes measured value and limits */ @@ -539,21 +555,6 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, return count; } - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1, - store_temp1, 1); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, - store_temp1, 2); - -#define device_create_file_temp1(client) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \ -} while (0) - - /* read/write the temperature2-3, includes measured value and limits */ static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, @@ -590,25 +591,23 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_temp23(name,idx) \ -static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \ - idx, 0); \ -static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \ - show_temp23, store_temp23, idx, 2); \ -static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp23, store_temp23, idx, 4); - -sysfs_temp23(temp2,0) -sysfs_temp23(temp3,1) +static struct sensor_device_attribute_2 sda_temp_input[] = { + SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), + SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), + SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0), +}; -#define device_create_file_temp_add(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \ -device_create_file(&client->dev, \ -&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \ -} while (0) +static struct sensor_device_attribute_2 sda_temp_max[] = { + SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 1), + SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 2), + SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2), +}; +static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { + SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 2), + SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 4), + SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4), +}; /* get reatime status of all sensors items: voltage, temp, fan */ static ssize_t @@ -620,10 +619,6 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); -#define device_create_file_alarms(client) \ -device_create_file(&client->dev, &dev_attr_alarms); - - static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, @@ -711,26 +706,19 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_pwm(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_pwm, store_pwm, offset); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ - show_pwmenable, store_pwmenable, offset); \ - -sysfs_pwm(1); -sysfs_pwm(2); -sysfs_pwm(3); - - -#define device_create_file_pwm(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \ -} while (0) - -#define device_create_file_pwmenable(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \ -} while (0) +static struct sensor_device_attribute sda_pwm[] = { + SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), + SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), + SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3), +}; +static struct sensor_device_attribute sda_pwm_enable[] = { + SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, + show_pwmenable, store_pwmenable, 1), + SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, + show_pwmenable, store_pwmenable, 2), + SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, + show_pwmenable, store_pwmenable, 3), +}; static ssize_t @@ -764,18 +752,14 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_pwm_mode(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \ - show_pwm_mode, store_pwm_mode, offset); - -sysfs_pwm_mode(1); -sysfs_pwm_mode(2); -sysfs_pwm_mode(3); - -#define device_create_file_pwm_mode(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \ -} while (0) +static struct sensor_device_attribute sda_pwm_mode[] = { + SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, + show_pwm_mode, store_pwm_mode, 1), + SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, + show_pwm_mode, store_pwm_mode, 2), + SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, + show_pwm_mode, store_pwm_mode, 3), +}; static ssize_t @@ -788,12 +772,6 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); -#define device_create_file_chassis(client) \ -do { \ -device_create_file(&client->dev, &dev_attr_chassis); \ -} while (0) - - static ssize_t show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) { @@ -824,13 +802,6 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, show_chassis_clear, store_chassis_clear); -#define device_create_file_chassis_clear(client) \ -do { \ -device_create_file(&client->dev, &dev_attr_chassis_clear); \ -} while (0) - - - /* For Smart Fan I / Thermal Cruise */ static ssize_t show_thermal_cruise(struct device *dev, struct device_attribute *attr, @@ -864,20 +835,14 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_thermal_cruise(offset) \ -static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \ - show_thermal_cruise, store_thermal_cruise, offset); - -sysfs_thermal_cruise(1); -sysfs_thermal_cruise(2); -sysfs_thermal_cruise(3); - -#define device_create_file_thermal_cruise(client, offset) \ -do { \ -device_create_file(&client->dev, \ -&sensor_dev_attr_thermal_cruise##offset.dev_attr); \ -} while (0) - +static struct sensor_device_attribute sda_thermal_cruise[] = { + SENSOR_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO, + show_thermal_cruise, store_thermal_cruise, 1), + SENSOR_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO, + show_thermal_cruise, store_thermal_cruise, 2), + SENSOR_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO, + show_thermal_cruise, store_thermal_cruise, 3), +}; /* For Smart Fan I/Thermal Cruise and Smart Fan II */ static ssize_t @@ -916,19 +881,14 @@ store_tolerance(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_tolerance(offset) \ -static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \ - show_tolerance, store_tolerance, offset); - -sysfs_tolerance(1); -sysfs_tolerance(2); -sysfs_tolerance(3); - -#define device_create_file_tolerance(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \ -} while (0) - +static struct sensor_device_attribute sda_tolerance[] = { + SENSOR_ATTR(tolerance1, S_IWUSR | S_IRUGO, + show_tolerance, store_tolerance, 1), + SENSOR_ATTR(tolerance2, S_IWUSR | S_IRUGO, + show_tolerance, store_tolerance, 2), + SENSOR_ATTR(tolerance3, S_IWUSR | S_IRUGO, + show_tolerance, store_tolerance, 3), +}; /* For Smart Fan II */ static ssize_t @@ -964,28 +924,34 @@ store_sf2_point(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_sf2_point(offset, index) \ -static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \ - show_sf2_point, store_sf2_point, offset, index); - -sysfs_sf2_point(1, 1); /* Fan1 */ -sysfs_sf2_point(2, 1); /* Fan1 */ -sysfs_sf2_point(3, 1); /* Fan1 */ -sysfs_sf2_point(4, 1); /* Fan1 */ -sysfs_sf2_point(1, 2); /* Fan2 */ -sysfs_sf2_point(2, 2); /* Fan2 */ -sysfs_sf2_point(3, 2); /* Fan2 */ -sysfs_sf2_point(4, 2); /* Fan2 */ -sysfs_sf2_point(1, 3); /* Fan3 */ -sysfs_sf2_point(2, 3); /* Fan3 */ -sysfs_sf2_point(3, 3); /* Fan3 */ -sysfs_sf2_point(4, 3); /* Fan3 */ - -#define device_create_file_sf2_point(client, offset, index) \ -do { \ -device_create_file(&client->dev, \ -&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \ -} while (0) +static struct sensor_device_attribute_2 sda_sf2_point[] = { + SENSOR_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 1, 1), + SENSOR_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 2, 1), + SENSOR_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 3, 1), + SENSOR_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 4, 1), + + SENSOR_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 1, 2), + SENSOR_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 2, 2), + SENSOR_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 3, 2), + SENSOR_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 4, 2), + + SENSOR_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 1, 3), + SENSOR_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 2, 3), + SENSOR_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 3, 3), + SENSOR_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 4, 3), +}; static ssize_t @@ -1026,26 +992,28 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_sf2_level(offset, index) \ -static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \ - show_sf2_level, store_sf2_level, offset, index); - -sysfs_sf2_level(1, 1); /* Fan1 */ -sysfs_sf2_level(2, 1); /* Fan1 */ -sysfs_sf2_level(3, 1); /* Fan1 */ -sysfs_sf2_level(1, 2); /* Fan2 */ -sysfs_sf2_level(2, 2); /* Fan2 */ -sysfs_sf2_level(3, 2); /* Fan2 */ -sysfs_sf2_level(1, 3); /* Fan3 */ -sysfs_sf2_level(2, 3); /* Fan3 */ -sysfs_sf2_level(3, 3); /* Fan3 */ - -#define device_create_file_sf2_level(client, offset, index) \ -do { \ -device_create_file(&client->dev, \ -&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \ -} while (0) - +static struct sensor_device_attribute_2 sda_sf2_level[] = { + SENSOR_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 1, 1), + SENSOR_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 2, 1), + SENSOR_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 3, 1), + + SENSOR_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 1, 2), + SENSOR_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 2, 2), + SENSOR_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 3, 2), + + SENSOR_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 1, 3), + SENSOR_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 2, 3), + SENSOR_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 3, 3), +}; /* This function is called when: * w83792d_driver is inserted (when this module is loaded), for each @@ -1147,12 +1115,19 @@ ERROR_SC_0: return err; } +static void device_create_file_fan(struct device *dev, int i) +{ + device_create_file(dev, &sda_fan_input[i].dev_attr); + device_create_file(dev, &sda_fan_div[i].dev_attr); + device_create_file(dev, &sda_fan_min[i].dev_attr); +} static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind) { int i = 0, val1 = 0, val2; - struct i2c_client *new_client; + struct i2c_client *client; + struct device *dev; struct w83792d_data *data; int err = 0; const char *client_name = ""; @@ -1170,12 +1145,13 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) goto ERROR0; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &w83792d_driver; - new_client->flags = 0; + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83792d_driver; + client->flags = 0; /* Now, we do the remaining detection. */ @@ -1184,13 +1160,12 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) force_*=... parameter, and the Winbond will be reset to the right bank. */ if (kind < 0) { - if (w83792d_read_value(new_client, W83792D_REG_CONFIG) & 0x80) { - dev_warn(&new_client->dev, "Detection failed at step " - "3\n"); + if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { + dev_warn(dev, "Detection failed at step 3\n"); goto ERROR1; } - val1 = w83792d_read_value(new_client, W83792D_REG_BANK); - val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); + val1 = w83792d_read_value(client, W83792D_REG_BANK); + val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); /* Check for Winbond ID if in bank 0 */ if (!(val1 & 0x07)) { /* is Bank0 */ if (((!(val1 & 0x80)) && (val2 != 0xa3)) || @@ -1200,34 +1175,33 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) } /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR should match */ - if (w83792d_read_value(new_client, + if (w83792d_read_value(client, W83792D_REG_I2C_ADDR) != address) { - dev_warn(&new_client->dev, "Detection failed " - "at step 5\n"); + dev_warn(dev, "Detection failed at step 5\n"); goto ERROR1; } } /* We have either had a force parameter, or we have already detected the Winbond. Put it now into bank 0 and Vendor ID High Byte */ - w83792d_write_value(new_client, + w83792d_write_value(client, W83792D_REG_BANK, - (w83792d_read_value(new_client, + (w83792d_read_value(client, W83792D_REG_BANK) & 0x78) | 0x80); /* Determine the chip type. */ if (kind <= 0) { /* get vendor ID */ - val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); + val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); if (val2 != 0x5c) { /* the vendor is NOT Winbond */ goto ERROR1; } - val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID); + val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); if (val1 == 0x7a) { kind = w83792d; } else { if (kind == 0) - dev_warn(&new_client->dev, + dev_warn(dev, "w83792d: Ignoring 'force' parameter for" " unknown chip at adapter %d, address" " 0x%02x\n", i2c_adapter_id(adapter), @@ -1239,120 +1213,86 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) if (kind == w83792d) { client_name = "w83792d"; } else { - dev_err(&new_client->dev, "w83792d: Internal error: unknown" + dev_err(dev, "w83792d: Internal error: unknown" " kind (%d)?!?", kind); goto ERROR1; } /* Fill in the remaining client fields and put into the global list */ - strlcpy(new_client->name, client_name, I2C_NAME_SIZE); + strlcpy(client->name, client_name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto ERROR1; if ((err = w83792d_detect_subclients(adapter, address, - kind, new_client))) + kind, client))) goto ERROR2; /* Initialize the chip */ - w83792d_init_client(new_client); + w83792d_init_client(client); /* A few vars need to be filled upon startup */ for (i = 0; i < 7; i++) { - data->fan_min[i] = w83792d_read_value(new_client, + data->fan_min[i] = w83792d_read_value(client, W83792D_REG_FAN_MIN[i]); } /* Register sysfs hooks */ - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto ERROR3; } - device_create_file_in(new_client, 0); - device_create_file_in(new_client, 1); - device_create_file_in(new_client, 2); - device_create_file_in(new_client, 3); - device_create_file_in(new_client, 4); - device_create_file_in(new_client, 5); - device_create_file_in(new_client, 6); - device_create_file_in(new_client, 7); - device_create_file_in(new_client, 8); - - device_create_file_fan(new_client, 1); - device_create_file_fan(new_client, 2); - device_create_file_fan(new_client, 3); + for (i = 0; i < 9; i++) { + device_create_file(dev, &sda_in_input[i].dev_attr); + device_create_file(dev, &sda_in_max[i].dev_attr); + device_create_file(dev, &sda_in_min[i].dev_attr); + } + for (i = 0; i < 3; i++) + device_create_file_fan(dev, i); /* Read GPIO enable register to check if pins for fan 4,5 are used as GPIO */ - val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN); + val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); if (!(val1 & 0x40)) - device_create_file_fan(new_client, 4); + device_create_file_fan(dev, 3); if (!(val1 & 0x20)) - device_create_file_fan(new_client, 5); + device_create_file_fan(dev, 4); - val1 = w83792d_read_value(new_client, W83792D_REG_PIN); + val1 = w83792d_read_value(client, W83792D_REG_PIN); if (val1 & 0x40) - device_create_file_fan(new_client, 6); + device_create_file_fan(dev, 5); if (val1 & 0x04) - device_create_file_fan(new_client, 7); - - device_create_file_temp1(new_client); /* Temp1 */ - device_create_file_temp_add(new_client, 2); /* Temp2 */ - device_create_file_temp_add(new_client, 3); /* Temp3 */ - - device_create_file_alarms(new_client); - - device_create_file_pwm(new_client, 1); - device_create_file_pwm(new_client, 2); - device_create_file_pwm(new_client, 3); - - device_create_file_pwmenable(new_client, 1); - device_create_file_pwmenable(new_client, 2); - device_create_file_pwmenable(new_client, 3); - - device_create_file_pwm_mode(new_client, 1); - device_create_file_pwm_mode(new_client, 2); - device_create_file_pwm_mode(new_client, 3); - - device_create_file_chassis(new_client); - device_create_file_chassis_clear(new_client); - - device_create_file_thermal_cruise(new_client, 1); - device_create_file_thermal_cruise(new_client, 2); - device_create_file_thermal_cruise(new_client, 3); - - device_create_file_tolerance(new_client, 1); - device_create_file_tolerance(new_client, 2); - device_create_file_tolerance(new_client, 3); - - device_create_file_sf2_point(new_client, 1, 1); /* Fan1 */ - device_create_file_sf2_point(new_client, 2, 1); /* Fan1 */ - device_create_file_sf2_point(new_client, 3, 1); /* Fan1 */ - device_create_file_sf2_point(new_client, 4, 1); /* Fan1 */ - device_create_file_sf2_point(new_client, 1, 2); /* Fan2 */ - device_create_file_sf2_point(new_client, 2, 2); /* Fan2 */ - device_create_file_sf2_point(new_client, 3, 2); /* Fan2 */ - device_create_file_sf2_point(new_client, 4, 2); /* Fan2 */ - device_create_file_sf2_point(new_client, 1, 3); /* Fan3 */ - device_create_file_sf2_point(new_client, 2, 3); /* Fan3 */ - device_create_file_sf2_point(new_client, 3, 3); /* Fan3 */ - device_create_file_sf2_point(new_client, 4, 3); /* Fan3 */ - - device_create_file_sf2_level(new_client, 1, 1); /* Fan1 */ - device_create_file_sf2_level(new_client, 2, 1); /* Fan1 */ - device_create_file_sf2_level(new_client, 3, 1); /* Fan1 */ - device_create_file_sf2_level(new_client, 1, 2); /* Fan2 */ - device_create_file_sf2_level(new_client, 2, 2); /* Fan2 */ - device_create_file_sf2_level(new_client, 3, 2); /* Fan2 */ - device_create_file_sf2_level(new_client, 1, 3); /* Fan3 */ - device_create_file_sf2_level(new_client, 2, 3); /* Fan3 */ - device_create_file_sf2_level(new_client, 3, 3); /* Fan3 */ + device_create_file_fan(dev, 6); + + for (i = 0; i < 3; i++) { + device_create_file(dev, &sda_temp_input[i].dev_attr); + device_create_file(dev, &sda_temp_max[i].dev_attr); + device_create_file(dev, &sda_temp_max_hyst[i].dev_attr); + device_create_file(dev, &sda_thermal_cruise[i].dev_attr); + device_create_file(dev, &sda_tolerance[i].dev_attr); + } + + for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) { + device_create_file(dev, &sda_pwm[i].dev_attr); + device_create_file(dev, &sda_pwm_enable[i].dev_attr); + device_create_file(dev, &sda_pwm_mode[i].dev_attr); + } + + device_create_file(dev, &dev_attr_alarms); + device_create_file(dev, &dev_attr_chassis); + device_create_file(dev, &dev_attr_chassis_clear); + + for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++) + device_create_file(dev, &sda_sf2_point[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(sda_sf2_level); i++) + device_create_file(dev, &sda_sf2_level[i].dev_attr); return 0; @@ -1366,7 +1306,7 @@ ERROR3: kfree(data->lm75[1]); } ERROR2: - i2c_detach_client(new_client); + i2c_detach_client(client); ERROR1: kfree(data); ERROR0: @@ -1434,7 +1374,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) int i, j; u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after (jiffies - data->last_updated, (unsigned long) (HZ * 3)) @@ -1545,7 +1485,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); #ifdef DEBUG w83792d_print_debug(data, dev); diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index f66c0cfdeda7..3f2bac125fb1 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -39,6 +39,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> +#include <linux/mutex.h> /* How many retries on register read error */ #define MAX_RETRIES 5 @@ -107,7 +108,7 @@ static struct i2c_driver w83l785ts_driver = { struct w83l785ts_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -221,7 +222,7 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields. */ strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Default values in case the first read fails (unlikely). */ data->temp[1] = data->temp[0] = 0; @@ -299,7 +300,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct w83l785ts_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) { dev_dbg(&client->dev, "Updating w83l785ts data.\n"); @@ -312,7 +313,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ff92735c7c85..089c6f5b24de 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -168,12 +168,14 @@ config I2C_PIIX4 help If you say yes to this option, support will be included for the Intel PIIX4 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported: + versions of the chipset are supported (note that Serverworks is part + of Broadcom): Intel PIIX4 Intel 440MX Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 + Serverworks HT-1000 SMSC Victory66 This driver can also be built as a module. If so, the module @@ -389,10 +391,11 @@ config SCx200_I2C_SDA also be specified with a module parameter. config SCx200_ACB - tristate "NatSemi SCx200 ACCESS.bus" - depends on I2C && PCI + tristate "Geode ACCESS.bus support" + depends on X86_32 && I2C && PCI help - Enable the use of the ACCESS.bus controllers of a SCx200 processor. + Enable the use of the ACCESS.bus controllers on the Geode SCx200 and + SC1100 processors and the CS5535 and CS5536 Geode companion devices. If you don't know what to do here, say N. diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 3eb47890db40..d3ef46aeeb3c 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -63,7 +63,6 @@ #include <linux/i2c.h> #include <linux/init.h> #include <asm/io.h> -#include <asm/semaphore.h> /* ALI1535 SMBus address offsets */ @@ -136,7 +135,6 @@ static struct pci_driver ali1535_driver; static unsigned short ali1535_smba; -static DECLARE_MUTEX(i2c_ali1535_sem); /* Detect whether a ALI1535 can be found, and initialize it, where necessary. Note the differences between kernels with the old PCI BIOS interface and @@ -345,7 +343,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, int timeout; s32 result = 0; - down(&i2c_ali1535_sem); /* make sure SMBus is idle */ temp = inb_p(SMBHSTSTS); for (timeout = 0; @@ -460,7 +457,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, break; } EXIT: - up(&i2c_ali1535_sem); return result; } diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 56c7d987590f..08e915730caf 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -38,6 +38,7 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/mutex.h> extern struct i2c_adapter amd756_smbus; @@ -45,7 +46,7 @@ static struct i2c_adapter *s4882_adapter; static struct i2c_algorithm *s4882_algo; /* Wrapper access functions for multiplexed SMBus */ -static struct semaphore amd756_lock; +static DEFINE_MUTEX(amd756_lock); static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, @@ -59,12 +60,12 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, || addr == 0x18) return -1; - down(&amd756_lock); + mutex_lock(&amd756_lock); error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, command, size, data); - up(&amd756_lock); + mutex_unlock(&amd756_lock); return error; } @@ -87,7 +88,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) return -1; - down(&amd756_lock); + mutex_lock(&amd756_lock); if (last_channels != channels) { union i2c_smbus_data mplxdata; @@ -105,7 +106,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, command, size, data); UNLOCK: - up(&amd756_lock); + mutex_unlock(&amd756_lock); return error; } @@ -166,8 +167,6 @@ static int __init amd756_s4882_init(void) } printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); - init_MUTEX(&amd756_lock); - /* Define the 5 virtual adapters and algorithms structures */ if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL))) { diff --git a/drivers/i2c/busses/i2c-frodo.c b/drivers/i2c/busses/i2c-frodo.c deleted file mode 100644 index b6f52f5a4138..000000000000 --- a/drivers/i2c/busses/i2c-frodo.c +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * linux/drivers/i2c/i2c-frodo.c - * - * Author: Abraham van der Merwe <abraham@2d3d.co.za> - * - * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 - * Development board (Frodo). - * - * This source code 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. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <asm/hardware.h> - - -static void frodo_setsda (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; -} - -static void frodo_setscl (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; -} - -static int frodo_getsda (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); -} - -static int frodo_getscl (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); -} - -static struct i2c_algo_bit_data bit_frodo_data = { - .setsda = frodo_setsda, - .setscl = frodo_setscl, - .getsda = frodo_getsda, - .getscl = frodo_getscl, - .udelay = 80, - .mdelay = 80, - .timeout = HZ -}; - -static struct i2c_adapter frodo_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_FRODO, - .algo_data = &bit_frodo_data, - .dev = { - .name = "Frodo adapter driver", - }, -}; - -static int __init i2c_frodo_init (void) -{ - return i2c_bit_add_bus(&frodo_ops); -} - -static void __exit i2c_frodo_exit (void) -{ - i2c_bit_del_bus(&frodo_ops); -} - -MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>"); -MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); -MODULE_LICENSE ("GPL"); - -module_init (i2c_frodo_init); -module_exit (i2c_frodo_exit); - diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c index 4344ae6b1fcb..c3e1d3e888d7 100644 --- a/drivers/i2c/busses/i2c-isa.c +++ b/drivers/i2c/busses/i2c-isa.c @@ -125,7 +125,7 @@ int i2c_isa_del_driver(struct i2c_driver *driver) static int __init i2c_isa_init(void) { - init_MUTEX(&isa_adapter.clist_lock); + mutex_init(&isa_adapter.clist_lock); INIT_LIST_HEAD(&isa_adapter.clients); isa_adapter.nr = ANY_I2C_ISA_BUS; diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c index 5f5d2944808b..d82e6dae8407 100644 --- a/drivers/i2c/busses/i2c-ite.c +++ b/drivers/i2c/busses/i2c-ite.c @@ -200,9 +200,7 @@ static struct i2c_adapter iic_ite_ops = { .owner = THIS_MODULE, .id = I2C_HW_I_IIC, .algo_data = &iic_ite_data, - .dev = { - .name = "ITE IIC adapter", - }, + .name = "ITE IIC adapter", }; /* Called when the module is loaded. This function starts the diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index e422d8b2d4d6..2ed07112d683 100644 --- a/drivers/i2c/busses/i2c-ixp4xx.c +++ b/drivers/i2c/busses/i2c-ixp4xx.c @@ -126,6 +126,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev) drv_data->algo_data.timeout = 100; drv_data->adapter.id = I2C_HW_B_IXP4XX; + drv_data->adapter.class = I2C_CLASS_HWMON; strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, I2C_NAME_SIZE); drv_data->adapter.algo_data = &drv_data->algo_data; diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 692f47345481..d9c7c00e71f9 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -22,7 +22,7 @@ /* Supports: Intel PIIX4, 440MX - Serverworks OSB4, CSB5, CSB6 + Serverworks OSB4, CSB5, CSB6, HT-1000 SMSC Victory66 Note: we assume there can only be one device, with one SMBus interface. @@ -419,6 +419,8 @@ static struct pci_device_id piix4_ids[] = { .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB), + .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), .driver_data = 3 }, { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 7579f4b256a8..5155010b455e 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -647,7 +647,7 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) } /* - * We are protected by the adapter bus semaphore. + * We are protected by the adapter bus mutex. */ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) { diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index d3478e084522..8bd305e47f0d 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -1,27 +1,26 @@ -/* linux/drivers/i2c/scx200_acb.c - +/* Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> National Semiconductor SCx200 ACCESS.bus support - + Also supports the AMD CS5535 and AMD CS5536 + Based on i2c-keywest.c which is: Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ #include <linux/module.h> @@ -32,7 +31,9 @@ #include <linux/smp_lock.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/mutex.h> #include <asm/io.h> +#include <asm/msr.h> #include <linux/scx200.h> @@ -47,16 +48,7 @@ static int base[MAX_DEVICES] = { 0x820, 0x840 }; module_param_array(base, int, NULL, 0); MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); -#ifdef DEBUG -#define DBG(x...) printk(KERN_DEBUG NAME ": " x) -#else -#define DBG(x...) -#endif - -/* The hardware supports interrupt driven mode too, but I haven't - implemented that. */ -#define POLLED_MODE 1 -#define POLL_TIMEOUT (HZ) +#define POLL_TIMEOUT (HZ/5) enum scx200_acb_state { state_idle, @@ -79,12 +71,11 @@ static const char *scx200_acb_state_name[] = { }; /* Physical interface */ -struct scx200_acb_iface -{ +struct scx200_acb_iface { struct scx200_acb_iface *next; struct i2c_adapter adapter; unsigned base; - struct semaphore sem; + struct mutex mutex; /* State machine data */ enum scx200_acb_state state; @@ -100,7 +91,7 @@ struct scx200_acb_iface #define ACBSDA (iface->base + 0) #define ACBST (iface->base + 1) #define ACBST_SDAST 0x40 /* SDA Status */ -#define ACBST_BER 0x20 +#define ACBST_BER 0x20 #define ACBST_NEGACK 0x10 /* Negative Acknowledge */ #define ACBST_STASTR 0x08 /* Stall After Start */ #define ACBST_MASTER 0x02 @@ -109,9 +100,9 @@ struct scx200_acb_iface #define ACBCTL1 (iface->base + 3) #define ACBCTL1_STASTRE 0x80 #define ACBCTL1_NMINTE 0x40 -#define ACBCTL1_ACK 0x10 -#define ACBCTL1_STOP 0x02 -#define ACBCTL1_START 0x01 +#define ACBCTL1_ACK 0x10 +#define ACBCTL1_STOP 0x02 +#define ACBCTL1_START 0x01 #define ACBADDR (iface->base + 4) #define ACBCTL2 (iface->base + 5) #define ACBCTL2_ENABLE 0x01 @@ -122,8 +113,8 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) { const char *errmsg; - DBG("state %s, status = 0x%02x\n", - scx200_acb_state_name[iface->state], status); + dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n", + scx200_acb_state_name[iface->state], status); if (status & ACBST_BER) { errmsg = "bus error"; @@ -133,8 +124,17 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) errmsg = "not master"; goto error; } - if (status & ACBST_NEGACK) - goto negack; + if (status & ACBST_NEGACK) { + dev_dbg(&iface->adapter.dev, "negative ack in state %s\n", + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -ENXIO; + + outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); + outb(ACBST_STASTR | ACBST_NEGACK, ACBST); + return; + } switch (iface->state) { case state_idle: @@ -160,10 +160,10 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) case state_repeat_start: outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); /* fallthrough */ - + case state_quick: if (iface->address_byte & 1) { - if (iface->len == 1) + if (iface->len == 1) outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); else outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); @@ -202,26 +202,15 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); break; } - + outb(*iface->ptr++, ACBSDA); --iface->len; - + break; } return; - negack: - DBG("negative acknowledge in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -ENXIO; - - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - outb(ACBST_STASTR | ACBST_NEGACK, ACBST); - return; - error: dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, scx200_acb_state_name[iface->state]); @@ -231,20 +220,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) iface->needs_reset = 1; } -static void scx200_acb_timeout(struct scx200_acb_iface *iface) -{ - dev_err(&iface->adapter.dev, "timeout in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -EIO; - iface->needs_reset = 1; -} - -#ifdef POLLED_MODE static void scx200_acb_poll(struct scx200_acb_iface *iface) { - u8 status = 0; + u8 status; unsigned long timeout; timeout = jiffies + POLL_TIMEOUT; @@ -254,17 +232,21 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) scx200_acb_machine(iface, status); return; } - msleep(10); + yield(); } - scx200_acb_timeout(iface); + dev_err(&iface->adapter.dev, "timeout in state %s\n", + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -EIO; + iface->needs_reset = 1; } -#endif /* POLLED_MODE */ static void scx200_acb_reset(struct scx200_acb_iface *iface) { /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ + frequency: 16 clock cycles */ outb(0x70, ACBCTL2); /* Polling mode */ outb(0, ACBCTL1); @@ -283,9 +265,9 @@ static void scx200_acb_reset(struct scx200_acb_iface *iface) } static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, - u16 address, unsigned short flags, - char rw, u8 command, int size, - union i2c_smbus_data *data) + u16 address, unsigned short flags, + char rw, u8 command, int size, + union i2c_smbus_data *data) { struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); int len; @@ -295,53 +277,47 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, switch (size) { case I2C_SMBUS_QUICK: - len = 0; - buffer = NULL; - break; + len = 0; + buffer = NULL; + break; + case I2C_SMBUS_BYTE: - if (rw == I2C_SMBUS_READ) { - len = 1; - buffer = &data->byte; - } else { - len = 1; - buffer = &command; - } - break; + len = 1; + buffer = rw ? &data->byte : &command; + break; + case I2C_SMBUS_BYTE_DATA: - len = 1; - buffer = &data->byte; - break; + len = 1; + buffer = &data->byte; + break; + case I2C_SMBUS_WORD_DATA: len = 2; - cur_word = cpu_to_le16(data->word); - buffer = (u8 *)&cur_word; + cur_word = cpu_to_le16(data->word); + buffer = (u8 *)&cur_word; break; + case I2C_SMBUS_BLOCK_DATA: - len = data->block[0]; - buffer = &data->block[1]; + len = data->block[0]; + buffer = &data->block[1]; break; + default: - return -EINVAL; + return -EINVAL; } - DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", - size, address, command, len, rw == I2C_SMBUS_READ); + dev_dbg(&adapter->dev, + "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", + size, address, command, len, rw); if (!len && rw == I2C_SMBUS_READ) { - dev_warn(&adapter->dev, "zero length read\n"); + dev_dbg(&adapter->dev, "zero length read\n"); return -EINVAL; } - if (len && !buffer) { - dev_warn(&adapter->dev, "nonzero length but no buffer\n"); - return -EFAULT; - } - - down(&iface->sem); + mutex_lock(&iface->mutex); - iface->address_byte = address<<1; - if (rw == I2C_SMBUS_READ) - iface->address_byte |= 1; + iface->address_byte = (address << 1) | rw; iface->command = command; iface->ptr = buffer; iface->len = len; @@ -355,25 +331,21 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, else iface->state = state_address; -#ifdef POLLED_MODE while (iface->state != state_idle) scx200_acb_poll(iface); -#else /* POLLED_MODE */ -#error Interrupt driven mode not implemented -#endif /* POLLED_MODE */ if (iface->needs_reset) scx200_acb_reset(iface); rc = iface->result; - up(&iface->sem); + mutex_unlock(&iface->mutex); if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) - data->word = le16_to_cpu(cur_word); + data->word = le16_to_cpu(cur_word); #ifdef DEBUG - DBG(": transfer done, result: %d", rc); + dev_dbg(&adapter->dev, "transfer done, result: %d", rc); if (buffer) { int i; printk(" data:"); @@ -400,17 +372,18 @@ static struct i2c_algorithm scx200_acb_algorithm = { }; static struct scx200_acb_iface *scx200_acb_list; +static DECLARE_MUTEX(scx200_acb_list_mutex); static int scx200_acb_probe(struct scx200_acb_iface *iface) { u8 val; /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ + frequency: 16 clock cycles */ outb(0x70, ACBCTL2); if (inb(ACBCTL2) != 0x70) { - DBG("ACBCTL2 readback failed\n"); + pr_debug(NAME ": ACBCTL2 readback failed\n"); return -ENXIO; } @@ -418,7 +391,8 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) val = inb(ACBCTL1); if (val) { - DBG("disabled, but ACBCTL1=0x%02x\n", val); + pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n", + val); return -ENXIO; } @@ -428,18 +402,19 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) val = inb(ACBCTL1); if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { - DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); + pr_debug(NAME ": enabled, but NMINTE won't be set, " + "ACBCTL1=0x%02x\n", val); return -ENXIO; } return 0; } -static int __init scx200_acb_create(int base, int index) +static int __init scx200_acb_create(const char *text, int base, int index) { struct scx200_acb_iface *iface; struct i2c_adapter *adapter; - int rc = 0; + int rc; char description[64]; iface = kzalloc(sizeof(*iface), GFP_KERNEL); @@ -451,50 +426,51 @@ static int __init scx200_acb_create(int base, int index) adapter = &iface->adapter; i2c_set_adapdata(adapter, iface); - snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index); + snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index); adapter->owner = THIS_MODULE; adapter->id = I2C_HW_SMBUS_SCX200; adapter->algo = &scx200_acb_algorithm; adapter->class = I2C_CLASS_HWMON; - init_MUTEX(&iface->sem); + mutex_init(&iface->mutex); + + snprintf(description, sizeof(description), "%s ACCESS.bus [%s]", + text, adapter->name); - snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); if (request_region(base, 8, description) == 0) { - dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", + printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", base, base + 8-1); rc = -EBUSY; - goto errout; + goto errout_free; } iface->base = base; rc = scx200_acb_probe(iface); if (rc) { - dev_warn(&adapter->dev, "probe failed\n"); - goto errout; + printk(KERN_WARNING NAME ": probe failed\n"); + goto errout_release; } scx200_acb_reset(iface); if (i2c_add_adapter(adapter) < 0) { - dev_err(&adapter->dev, "failed to register\n"); + printk(KERN_ERR NAME ": failed to register\n"); rc = -ENODEV; - goto errout; + goto errout_release; } - lock_kernel(); + down(&scx200_acb_list_mutex); iface->next = scx200_acb_list; scx200_acb_list = iface; - unlock_kernel(); + up(&scx200_acb_list_mutex); return 0; + errout_release: + release_region(iface->base, 8); + errout_free: + kfree(iface); errout: - if (iface) { - if (iface->base) - release_region(iface->base, 8); - kfree(iface); - } return rc; } @@ -504,50 +480,69 @@ static struct pci_device_id scx200[] = { { }, }; +static struct pci_device_id divil_pci[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, + { } /* NULL entry */ +}; + +#define MSR_LBAR_SMB 0x5140000B + +static int scx200_add_cs553x(void) +{ + u32 low, hi; + u32 smb_base; + + /* Grab & reserve the SMB I/O range */ + rdmsr(MSR_LBAR_SMB, low, hi); + + /* Check the IO mask and whether SMB is enabled */ + if (hi != 0x0000F001) { + printk(KERN_WARNING NAME ": SMBus not enabled\n"); + return -ENODEV; + } + + /* SMBus IO size is 8 bytes */ + smb_base = low & 0x0000FFF8; + + return scx200_acb_create("CS5535", smb_base, 0); +} + static int __init scx200_acb_init(void) { int i; - int rc; + int rc = -ENODEV; pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); /* Verify that this really is a SCx200 processor */ - if (pci_dev_present(scx200) == 0) - return -ENODEV; + if (pci_dev_present(scx200)) { + for (i = 0; i < MAX_DEVICES; ++i) { + if (base[i] > 0) + rc = scx200_acb_create("SCx200", base[i], i); + } + } else if (pci_dev_present(divil_pci)) + rc = scx200_add_cs553x(); - rc = -ENXIO; - for (i = 0; i < MAX_DEVICES; ++i) { - if (base[i] > 0) - rc = scx200_acb_create(base[i], i); - } - if (scx200_acb_list) - return 0; return rc; } static void __exit scx200_acb_cleanup(void) { struct scx200_acb_iface *iface; - lock_kernel(); + + down(&scx200_acb_list_mutex); while ((iface = scx200_acb_list) != NULL) { scx200_acb_list = iface->next; - unlock_kernel(); + up(&scx200_acb_list_mutex); i2c_del_adapter(&iface->adapter); release_region(iface->base, 8); kfree(iface); - lock_kernel(); + down(&scx200_acb_list_mutex); } - unlock_kernel(); + up(&scx200_acb_list_mutex); } module_init(scx200_acb_init); module_exit(scx200_acb_cleanup); - -/* - Local variables: - compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" - c-basic-offset: 8 - End: -*/ - diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c index 0710b9da9d54..03d09ed5ec2c 100644 --- a/drivers/i2c/chips/ds1374.c +++ b/drivers/i2c/chips/ds1374.c @@ -26,6 +26,7 @@ #include <linux/i2c.h> #include <linux/rtc.h> #include <linux/bcd.h> +#include <linux/mutex.h> #define DS1374_REG_TOD0 0x00 #define DS1374_REG_TOD1 0x01 @@ -41,7 +42,7 @@ #define DS1374_DRV_NAME "ds1374" -static DECLARE_MUTEX(ds1374_mutex); +static DEFINE_MUTEX(ds1374_mutex); static struct i2c_driver ds1374_driver; static struct i2c_client *save_client; @@ -114,7 +115,7 @@ ulong ds1374_get_rtc_time(void) ulong t1, t2; int limit = 10; /* arbitrary retry limit */ - down(&ds1374_mutex); + mutex_lock(&ds1374_mutex); /* * Since the reads are being performed one byte at a time using @@ -127,7 +128,7 @@ ulong ds1374_get_rtc_time(void) t2 = ds1374_read_rtc(); } while (t1 != t2 && limit--); - up(&ds1374_mutex); + mutex_unlock(&ds1374_mutex); if (t1 != t2) { dev_warn(&save_client->dev, @@ -145,7 +146,7 @@ static void ds1374_set_tlet(ulong arg) t1 = *(ulong *) arg; - down(&ds1374_mutex); + mutex_lock(&ds1374_mutex); /* * Since the writes are being performed one byte at a time using @@ -158,7 +159,7 @@ static void ds1374_set_tlet(ulong arg) t2 = ds1374_read_rtc(); } while (t1 != t2 && limit--); - up(&ds1374_mutex); + mutex_unlock(&ds1374_mutex); if (t1 != t2) dev_warn(&save_client->dev, diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 41116b7947f6..13c108269a6d 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -33,6 +33,7 @@ #include <linux/sched.h> #include <linux/jiffies.h> #include <linux/i2c.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, @@ -54,7 +55,7 @@ enum eeprom_nature { /* Each client has this additional data */ struct eeprom_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u8 valid; /* bitfield, bit!=0 if slice is valid */ unsigned long last_updated[8]; /* In jiffies, 8 slices */ u8 data[EEPROM_SIZE]; /* Register values */ @@ -81,7 +82,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) struct eeprom_data *data = i2c_get_clientdata(client); int i, j; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!(data->valid & (1 << slice)) || time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { @@ -107,7 +108,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) data->valid |= (1 << slice); } exit: - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count) @@ -187,7 +188,7 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields */ strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); data->nature = UNKNOWN; /* Tell the I2C layer a new client has arrived */ diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index 1251c7fc18d5..e6f1ab7b913c 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -1635,8 +1635,6 @@ static struct i2c_driver isp1301_driver = { .driver = { .name = "isp1301_omap", }, - .id = 1301, /* FIXME "official", i2c-ids.h */ - .class = I2C_CLASS_HWMON, .attach_adapter = isp1301_scan_bus, .detach_client = isp1301_detach_client, }; diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index 2dc3d48375fc..b5aabe7cf792 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c @@ -24,13 +24,14 @@ #include <linux/i2c.h> #include <linux/rtc.h> #include <linux/bcd.h> +#include <linux/mutex.h> #include <asm/time.h> #include <asm/rtc.h> #define M41T00_DRV_NAME "m41t00" -static DECLARE_MUTEX(m41t00_mutex); +static DEFINE_MUTEX(m41t00_mutex); static struct i2c_driver m41t00_driver; static struct i2c_client *save_client; @@ -54,7 +55,7 @@ m41t00_get_rtc_time(void) sec = min = hour = day = mon = year = 0; sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; - down(&m41t00_mutex); + mutex_lock(&m41t00_mutex); do { if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) && ((min = i2c_smbus_read_byte_data(save_client, 1)) @@ -80,7 +81,7 @@ m41t00_get_rtc_time(void) mon1 = mon; year1 = year; } while (--limit > 0); - up(&m41t00_mutex); + mutex_unlock(&m41t00_mutex); if (limit == 0) { dev_warn(&save_client->dev, @@ -125,7 +126,7 @@ m41t00_set_tlet(ulong arg) BIN_TO_BCD(tm.tm_mday); BIN_TO_BCD(tm.tm_year); - down(&m41t00_mutex); + mutex_lock(&m41t00_mutex); if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) < 0) @@ -140,7 +141,7 @@ m41t00_set_tlet(ulong arg) dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); - up(&m41t00_mutex); + mutex_unlock(&m41t00_mutex); return; } diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index 6d3ff584155e..88d2ddee4490 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c @@ -31,7 +31,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> -#include <asm/semaphore.h> +#include <linux/mutex.h> /* Do not scan - the MAX6875 access method will write to some EEPROM chips */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; @@ -54,7 +54,7 @@ I2C_CLIENT_INSMOD_1(max6875); /* Each client has this additional data */ struct max6875_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u32 valid; u8 data[USER_EEPROM_SIZE]; @@ -83,7 +83,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice) if (slice >= USER_EEPROM_SLICES) return; - down(&data->update_lock); + mutex_lock(&data->update_lock); buf = &data->data[slice << SLICE_BITS]; @@ -122,7 +122,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice) data->valid |= (1 << slice); } exit_up: - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, @@ -196,7 +196,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) real_client->driver = &max6875_driver; real_client->flags = 0; strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Init fake client data */ /* set the client data to the i2c_client so that it will get freed */ diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index 36cff09c678d..925a6b371fd2 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/i2c.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, @@ -74,7 +75,7 @@ MODULE_PARM_DESC(input_mode, struct pcf8591_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u8 control; u8 aout; @@ -144,13 +145,13 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr struct pcf8591_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (val) data->control |= PCF8591_CONTROL_AOEF; else data->control &= ~PCF8591_CONTROL_AOEF; i2c_smbus_write_byte(client, data->control); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -200,7 +201,7 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -265,7 +266,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) struct i2c_client *client = to_i2c_client(dev); struct pcf8591_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) @@ -278,7 +279,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) } value = i2c_smbus_read_byte(client); - up(&data->update_lock); + mutex_unlock(&data->update_lock); if ((channel == 2 && input_mode == 2) || (channel != 3 && (input_mode == 1 || input_mode == 3))) diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index 1af3dfbb8086..179b1e022d80 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c @@ -32,6 +32,7 @@ #include <linux/suspend.h> #include <linux/debugfs.h> #include <linux/seq_file.h> +#include <linux/mutex.h> #include <asm/irq.h> #include <asm/mach-types.h> @@ -81,7 +82,7 @@ enum tps_model { struct tps65010 { struct i2c_client client; - struct semaphore lock; + struct mutex lock; int irq; struct work_struct work; struct dentry *file; @@ -218,7 +219,7 @@ static int dbg_show(struct seq_file *s, void *_) seq_printf(s, "driver %s\nversion %s\nchip %s\n\n", DRIVER_NAME, DRIVER_VERSION, chip); - down(&tps->lock); + mutex_lock(&tps->lock); /* FIXME how can we tell whether a battery is present? * likely involves a charge gauging chip (like BQ26501). @@ -300,7 +301,7 @@ static int dbg_show(struct seq_file *s, void *_) (v2 & (1 << (4 + i))) ? "rising" : "falling"); } - up(&tps->lock); + mutex_unlock(&tps->lock); return 0; } @@ -416,7 +417,7 @@ static void tps65010_work(void *_tps) { struct tps65010 *tps = _tps; - down(&tps->lock); + mutex_lock(&tps->lock); tps65010_interrupt(tps); @@ -444,7 +445,7 @@ static void tps65010_work(void *_tps) if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags)) enable_irq(tps->irq); - up(&tps->lock); + mutex_unlock(&tps->lock); } static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs) @@ -505,7 +506,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) if (!tps) return 0; - init_MUTEX(&tps->lock); + mutex_init(&tps->lock); INIT_WORK(&tps->work, tps65010_work, tps); tps->irq = -1; tps->client.addr = address; @@ -695,7 +696,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) if ((gpio < GPIO1) || (gpio > GPIO4)) return -EINVAL; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO); @@ -720,7 +721,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) gpio, value ? "high" : "low", i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } EXPORT_SYMBOL(tps65010_set_gpio_out_value); @@ -745,7 +746,7 @@ int tps65010_set_led(unsigned led, unsigned mode) led = LED2; } - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led, i2c_smbus_read_byte_data(&the_tps->client, @@ -771,7 +772,7 @@ int tps65010_set_led(unsigned led, unsigned mode) default: printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n", DRIVER_NAME); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return -EINVAL; } @@ -781,7 +782,7 @@ int tps65010_set_led(unsigned led, unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write led%i_on register\n", DRIVER_NAME, led); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -794,7 +795,7 @@ int tps65010_set_led(unsigned led, unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write led%i_per register\n", DRIVER_NAME, led); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -802,7 +803,7 @@ int tps65010_set_led(unsigned led, unsigned mode) i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -820,7 +821,7 @@ int tps65010_set_vib(unsigned value) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2); vdcdc2 &= ~(1 << 1); @@ -831,7 +832,7 @@ int tps65010_set_vib(unsigned value) pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off"); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } EXPORT_SYMBOL(tps65010_set_vib); @@ -848,7 +849,7 @@ int tps65010_set_low_pwr(unsigned mode) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME, mode ? "enable" : "disable", @@ -876,7 +877,7 @@ int tps65010_set_low_pwr(unsigned mode) pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -894,7 +895,7 @@ int tps65010_config_vregs1(unsigned value) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); @@ -909,7 +910,7 @@ int tps65010_config_vregs1(unsigned value) pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -931,7 +932,7 @@ int tps65013_set_low_pwr(unsigned mode) if (!the_tps || the_tps->por) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n", DRIVER_NAME, @@ -959,7 +960,7 @@ int tps65013_set_low_pwr(unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write chconfig register\n", DRIVER_NAME); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -977,7 +978,7 @@ int tps65013_set_low_pwr(unsigned mode) pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 1a2c9ab5d9e3..45e2cdf54736 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -31,12 +31,13 @@ #include <linux/idr.h> #include <linux/seq_file.h> #include <linux/platform_device.h> +#include <linux/mutex.h> #include <asm/uaccess.h> static LIST_HEAD(adapters); static LIST_HEAD(drivers); -static DECLARE_MUTEX(core_lists); +static DEFINE_MUTEX(core_lists); static DEFINE_IDR(i2c_adapter_idr); /* match always succeeds, as we want the probe() to tell if we really accept this match */ @@ -153,7 +154,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) struct list_head *item; struct i2c_driver *driver; - down(&core_lists); + mutex_lock(&core_lists); if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { res = -ENOMEM; @@ -168,8 +169,8 @@ int i2c_add_adapter(struct i2c_adapter *adap) } adap->nr = id & MAX_ID_MASK; - init_MUTEX(&adap->bus_lock); - init_MUTEX(&adap->clist_lock); + mutex_init(&adap->bus_lock); + mutex_init(&adap->clist_lock); list_add_tail(&adap->list,&adapters); INIT_LIST_HEAD(&adap->clients); @@ -203,7 +204,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) } out_unlock: - up(&core_lists); + mutex_unlock(&core_lists); return res; } @@ -216,7 +217,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) struct i2c_client *client; int res = 0; - down(&core_lists); + mutex_lock(&core_lists); /* First make sure that this adapter was ever added */ list_for_each_entry(adap_from_list, &adapters, list) { @@ -272,7 +273,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); out_unlock: - up(&core_lists); + mutex_unlock(&core_lists); return res; } @@ -287,9 +288,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) { struct list_head *item; struct i2c_adapter *adapter; - int res = 0; - - down(&core_lists); + int res; /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; @@ -297,8 +296,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) res = driver_register(&driver->driver); if (res) - goto out_unlock; + return res; + mutex_lock(&core_lists); + list_add_tail(&driver->list,&drivers); pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); @@ -310,9 +311,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) } } - out_unlock: - up(&core_lists); - return res; + mutex_unlock(&core_lists); + return 0; } EXPORT_SYMBOL(i2c_register_driver); @@ -324,7 +324,7 @@ int i2c_del_driver(struct i2c_driver *driver) int res = 0; - down(&core_lists); + mutex_lock(&core_lists); /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver @@ -363,7 +363,7 @@ int i2c_del_driver(struct i2c_driver *driver) pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); out_unlock: - up(&core_lists); + mutex_unlock(&core_lists); return 0; } @@ -384,9 +384,9 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) { int rval; - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); rval = __i2c_check_addr(adapter, addr); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); return rval; } @@ -395,13 +395,13 @@ int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); if (__i2c_check_addr(client->adapter, client->addr)) { - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); return -EBUSY; } list_add_tail(&client->list,&adapter->clients); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); if (adapter->client_register) { if (adapter->client_register(client)) { @@ -450,12 +450,12 @@ int i2c_detach_client(struct i2c_client *client) } } - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); list_del(&client->list); init_completion(&client->released); device_remove_file(&client->dev, &dev_attr_client_name); device_unregister(&client->dev); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); wait_for_completion(&client->released); out: @@ -513,19 +513,19 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) struct list_head *item; struct i2c_client *client; - down(&adap->clist_lock); + mutex_lock(&adap->clist_lock); list_for_each(item,&adap->clients) { client = list_entry(item, struct i2c_client, list); if (!try_module_get(client->driver->driver.owner)) continue; if (NULL != client->driver->command) { - up(&adap->clist_lock); + mutex_unlock(&adap->clist_lock); client->driver->command(client,cmd,arg); - down(&adap->clist_lock); + mutex_lock(&adap->clist_lock); } module_put(client->driver->driver.owner); } - up(&adap->clist_lock); + mutex_unlock(&adap->clist_lock); } static int __init i2c_init(void) @@ -569,9 +569,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) } #endif - down(&adap->bus_lock); + mutex_lock(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); - up(&adap->bus_lock); + mutex_unlock(&adap->bus_lock); return ret; } else { @@ -779,12 +779,12 @@ struct i2c_adapter* i2c_get_adapter(int id) { struct i2c_adapter *adapter; - down(&core_lists); + mutex_lock(&core_lists); adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); if (adapter && !try_module_get(adapter->owner)) adapter = NULL; - up(&core_lists); + mutex_unlock(&core_lists); return adapter; } @@ -919,12 +919,11 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values) { union i2c_smbus_data data; - int i; + if (length > I2C_SMBUS_BLOCK_MAX) length = I2C_SMBUS_BLOCK_MAX; - for (i = 1; i <= length; i++) - data.block[i] = values[i-1]; data.block[0] = length; + memcpy(&data.block[1], values, length); return i2c_smbus_xfer(client->adapter,client->addr,client->flags, I2C_SMBUS_WRITE,command, I2C_SMBUS_BLOCK_DATA,&data); @@ -934,16 +933,14 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) { union i2c_smbus_data data; - int i; + if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, I2C_SMBUS_READ,command, I2C_SMBUS_I2C_BLOCK_DATA,&data)) return -1; - else { - for (i = 1; i <= data.block[0]; i++) - values[i-1] = data.block[i]; - return data.block[0]; - } + + memcpy(values, &data.block[1], data.block[0]); + return data.block[0]; } s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, @@ -1118,10 +1115,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, flags &= I2C_M_TEN | I2C_CLIENT_PEC; if (adapter->algo->smbus_xfer) { - down(&adapter->bus_lock); + mutex_lock(&adapter->bus_lock); res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, command,size,data); - up(&adapter->bus_lock); + mutex_unlock(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, command,size,data); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 26b08ee425c7..8c82373f7ff3 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -17,6 +17,7 @@ #include <linux/mempool.h> #include <linux/slab.h> #include <linux/idr.h> +#include <linux/blktrace_api.h> static const char *_name = DM_NAME; @@ -334,6 +335,8 @@ static void dec_pending(struct dm_io *io, int error) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); + blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE); + bio_endio(io->bio, io->bio->bi_size, io->error); free_io(io->md, io); } @@ -392,6 +395,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, struct target_io *tio) { int r; + sector_t sector; /* * Sanity checks. @@ -407,10 +411,17 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, * this io. */ atomic_inc(&tio->io->io_count); + sector = clone->bi_sector; r = ti->type->map(ti, clone, &tio->info); - if (r > 0) + if (r > 0) { /* the bio has been remapped so dispatch it */ + + blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone, + tio->io->bio->bi_bdev->bd_dev, sector, + clone->bi_sector); + generic_make_request(clone); + } else if (r < 0) { /* error the io and bail out */ diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 4ce07ae62dac..671e36db224d 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -53,7 +53,6 @@ MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(x) (x)->name @@ -125,24 +124,21 @@ adv7170_write_block (struct i2c_client *client, if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct adv7170 *encoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = + block_data[block_len++] = encoder->reg[reg++] = data[1]; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 4e218f22b214..085e8863cacb 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -49,7 +49,6 @@ MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(s) (s)->name @@ -68,8 +67,6 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct adv7175 { - unsigned char reg[128]; - int norm; int input; int enable; @@ -95,9 +92,6 @@ adv7175_write (struct i2c_client *client, u8 reg, u8 value) { - struct adv7175 *encoder = i2c_get_clientdata(client); - - encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } @@ -120,25 +114,21 @@ adv7175_write_block (struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct adv7175 *encoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = - encoder->reg[reg++] = data[1]; + block_data[block_len++] = data[1]; + reg++; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { @@ -171,24 +161,6 @@ set_subcarrier_freq (struct i2c_client *client, adv7175_write(client, 0x05, 0x25); } -#ifdef ENCODER_DUMP -static void -dump (struct i2c_client *client) -{ - struct adv7175 *encoder = i2c_get_clientdata(client); - int i, j; - - printk(KERN_INFO "%s: registry dump\n", I2C_NAME(client)); - for (i = 0; i < 182 / 8; i++) { - printk("%s: 0x%02x -", I2C_NAME(client), i * 8); - for (j = 0; j < 8; j++) { - printk(" 0x%02x", encoder->reg[i * 8 + j]); - } - printk("\n"); - } -} -#endif - /* ----------------------------------------------------------------------- */ // Output filter: S-Video Composite @@ -407,14 +379,6 @@ adv7175_command (struct i2c_client *client, } break; -#ifdef ENCODER_DUMP - case ENCODER_DUMP: - { - dump(client); - } - break; -#endif - default: return -EINVAL; } diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index d6447791d0e5..d8a18a6a5bee 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -53,7 +53,6 @@ MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(s) (s)->name @@ -141,24 +140,21 @@ bt819_write_block (struct i2c_client *client, if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct bt819 *decoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = + block_data[block_len++] = decoder->reg[reg++] = data[1]; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 909b593530ed..4d47a0a0e974 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -53,7 +53,6 @@ MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(s) (s)->name @@ -71,17 +70,14 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ -#define REG_OFFSET 0xCE +#define REG_OFFSET 0xDA +#define BT856_NR_REG 6 struct bt856 { - unsigned char reg[32]; + unsigned char reg[BT856_NR_REG]; int norm; int enable; - int bright; - int contrast; - int hue; - int sat; }; #define I2C_BT856 0x88 @@ -120,8 +116,8 @@ bt856_dump (struct i2c_client *client) struct bt856 *encoder = i2c_get_clientdata(client); printk(KERN_INFO "%s: register dump:", I2C_NAME(client)); - for (i = 0xd6; i <= 0xde; i += 2) - printk(" %02x", encoder->reg[i - REG_OFFSET]); + for (i = 0; i < BT856_NR_REG; i += 2) + printk(" %02x", encoder->reg[i]); printk("\n"); } diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index d93a561e6b80..3cebfa91ca14 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -58,7 +58,7 @@ static int video_nr = -1; #ifdef MODULE module_param(video_nr, int, 0); -MODULE_AUTHOR("Scott J. Bertin <sbertin@securenym.net> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <johannes@erdfeld.com>"); +MODULE_AUTHOR("Scott J. Bertin <sbertin@securenym.net> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <johannes@erdfelt.com>"); MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("video"); diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 7bb85a7b326e..e18ea268384b 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -39,7 +39,6 @@ MODULE_AUTHOR("Pauline Middelink"); MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(s) (s)->name @@ -108,13 +107,8 @@ saa7110_write_block (struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { struct saa7110 *decoder = i2c_get_clientdata(client); - struct i2c_msg msg; - msg.len = len; - msg.buf = (char *) data; - msg.addr = client->addr; - msg.flags = 0; - ret = i2c_transfer(client->adapter, &msg, 1); + ret = i2c_master_send(client, data, len); /* Cache the written data */ memcpy(decoder->reg + reg, data + 1, len - 1); @@ -432,15 +426,13 @@ saa7110_command (struct i2c_client *client, break; case DECODER_DUMP: - for (v = 0; v < 0x34; v += 16) { + for (v = 0; v < SAA7110_NR_REG; v += 16) { int j; - dprintk(1, KERN_INFO "%s: %03x\n", I2C_NAME(client), + dprintk(1, KERN_DEBUG "%s: %02x:", I2C_NAME(client), v); - for (j = 0; j < 16; j++) { - dprintk(1, KERN_INFO " %02x", - decoder->reg[v + j]); - } - dprintk(1, KERN_INFO "\n"); + for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++) + dprintk(1, " %02x", decoder->reg[v + j]); + dprintk(1, "\n"); } break; diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 8c06592b37ff..f9ba0c943adf 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -52,7 +52,6 @@ MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(s) (s)->name @@ -70,8 +69,10 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ +#define SAA7111_NR_REG 0x18 + struct saa7111 { - unsigned char reg[32]; + unsigned char reg[SAA7111_NR_REG]; int norm; int input; @@ -110,24 +111,21 @@ saa7111_write_block (struct i2c_client *client, if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct saa7111 *decoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = + block_data[block_len++] = decoder->reg[reg++] = data[1]; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { @@ -210,6 +208,7 @@ saa7111_command (struct i2c_client *client, switch (cmd) { case 0: + break; case DECODER_INIT: { struct video_decoder_init *init = arg; @@ -227,11 +226,11 @@ saa7111_command (struct i2c_client *client, { int i; - for (i = 0; i < 32; i += 16) { + for (i = 0; i < SAA7111_NR_REG; i += 16) { int j; printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); - for (j = 0; j < 16; ++j) { + for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { printk(" %02x", saa7111_read(client, i + j)); } diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index fd0a4b4ef014..4a1f841d0c77 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -55,7 +55,6 @@ MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(x) (x)->name @@ -139,9 +138,6 @@ saa7114_write (struct i2c_client *client, u8 reg, u8 value) { - /*struct saa7114 *decoder = i2c_get_clientdata(client);*/ - - /*decoder->reg[reg] = value;*/ return i2c_smbus_write_byte_data(client, reg, value); } @@ -157,25 +153,21 @@ saa7114_write_block (struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - /*struct saa7114 *decoder = i2c_get_clientdata(client);*/ - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = - /*decoder->reg[reg++] =*/ data[1]; + block_data[block_len++] = data[1]; + reg++; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 6c161f2f5e2c..708fae51e8ee 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -45,7 +45,6 @@ MODULE_AUTHOR("Dave Perks, Jose Ignacio Gijon, Joerg Heckenbach, Mark McClelland MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(s) (s)->name diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 3ed0edb870a4..9f99ee1303e0 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -49,7 +49,6 @@ MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(s) (s)->name @@ -113,24 +112,21 @@ saa7185_write_block (struct i2c_client *client, if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct saa7185 *encoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = + block_data[block_len++] = encoder->reg[reg++] = data[1]; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index d0a1e72ea8c4..4cd579967487 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -30,7 +30,6 @@ #include <asm/uaccess.h> #include <linux/i2c.h> -#include <linux/i2c-dev.h> #define I2C_NAME(x) (x)->name diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 9fe6ad3b6352..ad04a129499d 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -395,7 +395,7 @@ struct zoran { struct videocodec *codec; /* video codec */ struct videocodec *vfe; /* video front end */ - struct semaphore resource_lock; /* prevent evil stuff */ + struct mutex resource_lock; /* prevent evil stuff */ u8 initialized; /* flag if zoran has been correctly initalized */ int user; /* number of current users */ diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index 246e67cd8b51..b22dbb6d18f6 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -47,6 +47,7 @@ #include <linux/interrupt.h> #include <linux/video_decoder.h> #include <linux/video_encoder.h> +#include <linux/mutex.h> #include <asm/io.h> @@ -673,7 +674,7 @@ zoran_i2c_client_register (struct i2c_client *client) KERN_DEBUG "%s: i2c_client_register() - driver id = %d\n", ZR_DEVNAME(zr), client->driver->id); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (zr->user > 0) { /* we're already busy, so we keep a reference to @@ -694,7 +695,7 @@ zoran_i2c_client_register (struct i2c_client *client) } clientreg_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -707,7 +708,7 @@ zoran_i2c_client_unregister (struct i2c_client *client) dprintk(2, KERN_DEBUG "%s: i2c_client_unregister()\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (zr->user > 0) { res = -EBUSY; @@ -722,7 +723,7 @@ zoran_i2c_client_unregister (struct i2c_client *client) snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%d]", zr->id); } clientunreg_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -995,10 +996,7 @@ test_interrupts (struct zoran *zr) static int __devinit zr36057_init (struct zoran *zr) { - u32 *mem; - void *vdev; - unsigned mem_needed; - int j; + int j, err; int two = 2; int zero = 0; @@ -1049,19 +1047,16 @@ zr36057_init (struct zoran *zr) /* allocate memory *before* doing anything to the hardware * in case allocation fails */ - mem_needed = BUZ_NUM_STAT_COM * 4; - mem = kzalloc(mem_needed, GFP_KERNEL); - vdev = (void *) kmalloc(sizeof(struct video_device), GFP_KERNEL); - if (!mem || !vdev) { + zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL); + zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL); + if (!zr->stat_com || !zr->video_dev) { dprintk(1, KERN_ERR "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", ZR_DEVNAME(zr)); - kfree(vdev); - kfree(mem); - return -ENOMEM; + err = -ENOMEM; + goto exit_free; } - zr->stat_com = mem; for (j = 0; j < BUZ_NUM_STAT_COM; j++) { zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ } @@ -1069,16 +1064,11 @@ zr36057_init (struct zoran *zr) /* * Now add the template and register the device unit. */ - zr->video_dev = vdev; memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); - if (video_register_device(zr->video_dev, VFL_TYPE_GRABBER, - video_nr) < 0) { - zoran_unregister_i2c(zr); - kfree((void *) zr->stat_com); - kfree(vdev); - return -1; - } + err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr); + if (err < 0) + goto exit_unregister; zoran_init_hardware(zr); if (*zr_debug > 2) @@ -1092,6 +1082,13 @@ zr36057_init (struct zoran *zr) zr->zoran_proc = NULL; zr->initialized = 1; return 0; + +exit_unregister: + zoran_unregister_i2c(zr); +exit_free: + kfree(zr->stat_com); + kfree(zr->video_dev); + return err; } static void @@ -1121,7 +1118,7 @@ zoran_release (struct zoran *zr) btwrite(0, ZR36057_SPGPPCR); free_irq(zr->pci_dev->irq, zr); /* unmap and free memory */ - kfree((void *) zr->stat_com); + kfree(zr->stat_com); zoran_proc_cleanup(zr); iounmap(zr->zr36057_mem); pci_disable_device(zr->pci_dev); @@ -1206,7 +1203,7 @@ find_zr36057 (void) zr->id = zoran_num; snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); spin_lock_init(&zr->spinlock); - init_MUTEX(&zr->resource_lock); + mutex_init(&zr->resource_lock); if (pci_enable_device(dev)) continue; zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0); diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 485553be190b..b2c6e01e3923 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -81,6 +81,7 @@ #include <linux/video_decoder.h> #include <linux/video_encoder.h> +#include <linux/mutex.h> #include "zoran.h" #include "zoran_device.h" #include "zoran_card.h" @@ -1292,7 +1293,7 @@ zoran_open (struct inode *inode, /* see fs/device.c - the kernel already locks during open(), * so locking ourselves only causes deadlocks */ - /*down(&zr->resource_lock);*/ + /*mutex_lock(&zr->resource_lock);*/ if (!zr->decoder) { dprintk(1, @@ -1371,7 +1372,7 @@ zoran_open (struct inode *inode, if (zr->user++ == 0) first_open = 1; - /*up(&zr->resource_lock);*/ + /*mutex_unlock(&zr->resource_lock);*/ /* default setup - TODO: look at flags */ if (first_open) { /* First device open */ @@ -1401,7 +1402,7 @@ open_unlock_and_return: /* if there's no device found, we didn't obtain the lock either */ if (zr) { - /*up(&zr->resource_lock);*/ + /*mutex_unlock(&zr->resource_lock);*/ } return res; @@ -1419,7 +1420,7 @@ zoran_close (struct inode *inode, /* kernel locks (fs/device.c), so don't do that ourselves * (prevents deadlocks) */ - /*down(&zr->resource_lock);*/ + /*mutex_lock(&zr->resource_lock);*/ zoran_close_end_session(file); @@ -1466,7 +1467,7 @@ zoran_close (struct inode *inode, } module_put(THIS_MODULE); - /*up(&zr->resource_lock);*/ + /*mutex_unlock(&zr->resource_lock);*/ dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr)); @@ -2027,14 +2028,14 @@ zoran_do_ioctl (struct inode *inode, * but moving the free code outside the munmap() handler fixes * all this... If someone knows why, please explain me (Ronald) */ - if (!down_trylock(&zr->resource_lock)) { + if (!!mutex_trylock(&zr->resource_lock)) { /* we obtained it! Let's try to free some things */ if (fh->jpg_buffers.ready_to_be_freed) jpg_fbuffer_free(file); if (fh->v4l_buffers.ready_to_be_freed) v4l_fbuffer_free(file); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } switch (cmd) { @@ -2051,12 +2052,12 @@ zoran_do_ioctl (struct inode *inode, vcap->channels = zr->card.inputs; vcap->audios = 0; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); vcap->maxwidth = BUZ_MAX_WIDTH; vcap->maxheight = BUZ_MAX_HEIGHT; vcap->minwidth = BUZ_MIN_WIDTH; vcap->minheight = BUZ_MIN_HEIGHT; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -2084,9 +2085,9 @@ zoran_do_ioctl (struct inode *inode, vchan->tuners = 0; vchan->flags = 0; vchan->type = VIDEO_TYPE_CAMERA; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); vchan->norm = zr->norm; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); vchan->channel = channel; return 0; @@ -2113,7 +2114,7 @@ zoran_do_ioctl (struct inode *inode, "%s: VIDIOCSCHAN - channel=%d, norm=%d\n", ZR_DEVNAME(zr), vchan->channel, vchan->norm); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if ((res = zoran_set_input(zr, vchan->channel))) goto schan_unlock_and_return; if ((res = zoran_set_norm(zr, vchan->norm))) @@ -2122,7 +2123,7 @@ zoran_do_ioctl (struct inode *inode, /* Make sure the changes come into effect */ res = wait_grab_pending(zr); schan_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -2134,7 +2135,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCGPICT\n", ZR_DEVNAME(zr)); memset(vpict, 0, sizeof(struct video_picture)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); vpict->hue = zr->hue; vpict->brightness = zr->brightness; vpict->contrast = zr->contrast; @@ -2145,7 +2146,7 @@ zoran_do_ioctl (struct inode *inode, } else { vpict->depth = 0; } - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -2180,7 +2181,7 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); decoder_command(zr, DECODER_SET_PICTURE, vpict); @@ -2191,7 +2192,7 @@ zoran_do_ioctl (struct inode *inode, fh->overlay_settings.format = &zoran_formats[i]; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -2204,9 +2205,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCCAPTURE - on=%d\n", ZR_DEVNAME(zr), *on); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_overlay(file, *on); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2219,12 +2220,12 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCGWIN\n", ZR_DEVNAME(zr)); memset(vwin, 0, sizeof(struct video_window)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); vwin->x = fh->overlay_settings.x; vwin->y = fh->overlay_settings.y; vwin->width = fh->overlay_settings.width; vwin->height = fh->overlay_settings.height; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); vwin->clipcount = 0; return 0; } @@ -2241,12 +2242,12 @@ zoran_do_ioctl (struct inode *inode, ZR_DEVNAME(zr), vwin->x, vwin->y, vwin->width, vwin->height, vwin->clipcount); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_window(file, vwin->x, vwin->y, vwin->width, vwin->height, vwin->clips, vwin->clipcount, NULL); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2258,9 +2259,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCGFBUF\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); *vbuf = zr->buffer; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } break; @@ -2287,12 +2288,12 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_fbuffer(file, vbuf->base, &zoran_formats[i], vbuf->width, vbuf->height, vbuf->bytesperline); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2305,9 +2306,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCSYNC - frame=%d\n", ZR_DEVNAME(zr), *frame); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = v4l_sync(file, *frame); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); if (!res) zr->v4l_sync_tail++; return res; @@ -2325,9 +2326,9 @@ zoran_do_ioctl (struct inode *inode, ZR_DEVNAME(zr), vmap->frame, vmap->width, vmap->height, vmap->format); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = v4l_grab(file, vmap); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -2348,7 +2349,7 @@ zoran_do_ioctl (struct inode *inode, i * fh->v4l_buffers.buffer_size; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, @@ -2367,7 +2368,7 @@ zoran_do_ioctl (struct inode *inode, /* The next mmap will map the V4L buffers */ fh->map_mode = ZORAN_MAP_MODE_RAW; v4l1reqbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2421,7 +2422,7 @@ zoran_do_ioctl (struct inode *inode, bparams->major_version = MAJOR_VERSION; bparams->minor_version = MINOR_VERSION; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); bparams->norm = zr->norm; bparams->input = zr->input; @@ -2450,7 +2451,7 @@ zoran_do_ioctl (struct inode *inode, bparams->jpeg_markers = fh->jpg_settings.jpg_comp.jpeg_markers; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); bparams->VFIFO_FB = 0; @@ -2486,7 +2487,7 @@ zoran_do_ioctl (struct inode *inode, sizeof(bparams->COM_data)); settings.jpg_comp.jpeg_markers = bparams->jpeg_markers; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (zr->codec_mode != BUZ_MODE_IDLE) { dprintk(1, @@ -2506,7 +2507,7 @@ zoran_do_ioctl (struct inode *inode, fh->jpg_settings = settings; sparams_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2538,7 +2539,7 @@ zoran_do_ioctl (struct inode *inode, breq->size > MAX_KMALLOC_MEM) breq->size = MAX_KMALLOC_MEM; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, @@ -2561,7 +2562,7 @@ zoran_do_ioctl (struct inode *inode, * also be *_PLAY, but it doesn't matter here */ fh->map_mode = ZORAN_MAP_MODE_JPG_REC; jpgreqbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2574,9 +2575,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_CAPT - frame=%d\n", ZR_DEVNAME(zr), *frame); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_COMPRESS); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2589,9 +2590,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_PLAY - frame=%d\n", ZR_DEVNAME(zr), *frame); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_DECOMPRESS); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2604,9 +2605,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = jpg_sync(file, bsync); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2630,7 +2631,7 @@ zoran_do_ioctl (struct inode *inode, input = zr->card.input[bstat->input].muxsel; norm = VIDEO_MODE_AUTO; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (zr->codec_mode != BUZ_MODE_IDLE) { dprintk(1, @@ -2655,7 +2656,7 @@ zoran_do_ioctl (struct inode *inode, decoder_command(zr, DECODER_SET_INPUT, &input); decoder_command(zr, DECODER_SET_NORM, &zr->norm); gstat_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); if (!res) { bstat->signal = @@ -2763,7 +2764,7 @@ zoran_do_ioctl (struct inode *inode, switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); fmt->fmt.win.w.left = fh->overlay_settings.x; fmt->fmt.win.w.top = fh->overlay_settings.y; @@ -2776,14 +2777,14 @@ zoran_do_ioctl (struct inode *inode, else fmt->fmt.win.field = V4L2_FIELD_TOP; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && fh->map_mode == ZORAN_MAP_MODE_RAW) { @@ -2837,7 +2838,7 @@ zoran_do_ioctl (struct inode *inode, V4L2_COLORSPACE_SMPTE170M; } - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; @@ -2870,7 +2871,7 @@ zoran_do_ioctl (struct inode *inode, fmt->fmt.win.w.height, fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_window(file, fmt->fmt.win.w.left, fmt->fmt.win.w.top, @@ -2880,7 +2881,7 @@ zoran_do_ioctl (struct inode *inode, fmt->fmt.win.clips, fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; break; @@ -2917,7 +2918,7 @@ zoran_do_ioctl (struct inode *inode, } if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) { - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); settings = fh->jpg_settings; @@ -2995,7 +2996,7 @@ zoran_do_ioctl (struct inode *inode, ZORAN_MAP_MODE_JPG_REC : ZORAN_MAP_MODE_JPG_PLAY; sfmtjpg_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } else { for (i = 0; i < zoran_num_formats; i++) if (fmt->fmt.pix.pixelformat == @@ -3010,7 +3011,7 @@ zoran_do_ioctl (struct inode *inode, (char *) &printformat); return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || (fh->v4l_buffers.allocated && fh->v4l_buffers.active != @@ -3052,7 +3053,7 @@ zoran_do_ioctl (struct inode *inode, fh->map_mode = ZORAN_MAP_MODE_RAW; sfmtv4l_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } break; @@ -3077,7 +3078,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_G_FBUF\n", ZR_DEVNAME(zr)); memset(fb, 0, sizeof(*fb)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); fb->base = zr->buffer.base; fb->fmt.width = zr->buffer.width; fb->fmt.height = zr->buffer.height; @@ -3086,7 +3087,7 @@ zoran_do_ioctl (struct inode *inode, fh->overlay_settings.format->fourcc; } fb->fmt.bytesperline = zr->buffer.bytesperline; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; fb->fmt.field = V4L2_FIELD_INTERLACED; fb->flags = V4L2_FBUF_FLAG_OVERLAY; @@ -3121,12 +3122,12 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_fbuffer(file, fb->base, &zoran_formats[i], fb->fmt.width, fb->fmt.height, fb->fmt.bytesperline); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3139,9 +3140,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_PREVIEW - on=%d\n", ZR_DEVNAME(zr), *on); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_overlay(file, *on); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3163,7 +3164,7 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { dprintk(1, @@ -3224,7 +3225,7 @@ zoran_do_ioctl (struct inode *inode, goto v4l2reqbuf_unlock_and_return; } v4l2reqbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -3245,9 +3246,9 @@ zoran_do_ioctl (struct inode *inode, buf->type = type; buf->index = index; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = zoran_v4l2_buffer_status(file, buf, buf->index); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3262,7 +3263,7 @@ zoran_do_ioctl (struct inode *inode, KERN_DEBUG "%s: VIDIOC_QBUF - type=%d, index=%d\n", ZR_DEVNAME(zr), buf->type, buf->index); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: @@ -3322,7 +3323,7 @@ zoran_do_ioctl (struct inode *inode, goto qbuf_unlock_and_return; } qbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3336,7 +3337,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_DQBUF - type=%d\n", ZR_DEVNAME(zr), buf->type); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: @@ -3410,7 +3411,7 @@ zoran_do_ioctl (struct inode *inode, goto dqbuf_unlock_and_return; } dqbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3422,7 +3423,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMON\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* raw capture */ @@ -3470,7 +3471,7 @@ zoran_do_ioctl (struct inode *inode, goto strmon_unlock_and_return; } strmon_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3482,7 +3483,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMOFF\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* raw capture */ @@ -3540,7 +3541,7 @@ zoran_do_ioctl (struct inode *inode, goto strmoff_unlock_and_return; } strmoff_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3600,7 +3601,7 @@ zoran_do_ioctl (struct inode *inode, ctrl->id > V4L2_CID_HUE) return -EINVAL; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ctrl->value = zr->brightness; @@ -3615,7 +3616,7 @@ zoran_do_ioctl (struct inode *inode, ctrl->value = zr->hue; break; } - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -3642,7 +3643,7 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: zr->brightness = ctrl->value; @@ -3664,7 +3665,7 @@ zoran_do_ioctl (struct inode *inode, decoder_command(zr, DECODER_SET_PICTURE, &pict); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -3732,9 +3733,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_G_STD\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); norm = zr->norm; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); switch (norm) { case VIDEO_MODE_PAL: @@ -3776,13 +3777,13 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if ((res = zoran_set_norm(zr, norm))) goto sstd_unlock_and_return; res = wait_grab_pending(zr); sstd_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -3809,9 +3810,9 @@ zoran_do_ioctl (struct inode *inode, inp->std = V4L2_STD_ALL; /* Get status of video decoder */ - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); decoder_command(zr, DECODER_GET_STATUS, &status); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); if (!(status & DECODER_STATUS_GOOD)) { inp->status |= V4L2_IN_ST_NO_POWER; @@ -3830,9 +3831,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_G_INPUT\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); *input = zr->input; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -3845,14 +3846,14 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_S_INPUT - input=%d\n", ZR_DEVNAME(zr), *input); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if ((res = zoran_set_input(zr, *input))) goto sinput_unlock_and_return; /* Make sure the changes come into effect */ res = wait_grab_pending(zr); sinput_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -3914,7 +3915,7 @@ zoran_do_ioctl (struct inode *inode, memset(cropcap, 0, sizeof(*cropcap)); cropcap->type = type; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || @@ -3934,7 +3935,7 @@ zoran_do_ioctl (struct inode *inode, cropcap->defrect.width = BUZ_MIN_WIDTH; cropcap->defrect.height = BUZ_MIN_HEIGHT; cropcap_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -3950,7 +3951,7 @@ zoran_do_ioctl (struct inode *inode, memset(crop, 0, sizeof(*crop)); crop->type = type; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || @@ -3969,7 +3970,7 @@ zoran_do_ioctl (struct inode *inode, crop->c.height = fh->jpg_settings.img_height; gcrop_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3988,7 +3989,7 @@ zoran_do_ioctl (struct inode *inode, ZR_DEVNAME(zr), crop->type, crop->c.left, crop->c.top, crop->c.width, crop->c.height); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, @@ -4024,7 +4025,7 @@ zoran_do_ioctl (struct inode *inode, fh->jpg_settings = settings; scrop_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -4038,7 +4039,7 @@ zoran_do_ioctl (struct inode *inode, memset(params, 0, sizeof(*params)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); params->quality = fh->jpg_settings.jpg_comp.quality; params->APPn = fh->jpg_settings.jpg_comp.APPn; @@ -4053,7 +4054,7 @@ zoran_do_ioctl (struct inode *inode, params->jpeg_markers = fh->jpg_settings.jpg_comp.jpeg_markers; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -4074,7 +4075,7 @@ zoran_do_ioctl (struct inode *inode, settings.jpg_comp = *params; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.active != ZORAN_FREE || fh->jpg_buffers.active != ZORAN_FREE) { @@ -4093,7 +4094,7 @@ zoran_do_ioctl (struct inode *inode, zoran_v4l2_calc_bufsize(&fh->jpg_settings); fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; sjpegc_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -4127,7 +4128,7 @@ zoran_do_ioctl (struct inode *inode, switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH) fmt->fmt.win.w.width = BUZ_MAX_WIDTH; @@ -4138,7 +4139,7 @@ zoran_do_ioctl (struct inode *inode, if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT) fmt->fmt.win.w.height = BUZ_MIN_HEIGHT; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -4146,7 +4147,7 @@ zoran_do_ioctl (struct inode *inode, if (fmt->fmt.pix.bytesperline > 0) return -EINVAL; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) { settings = fh->jpg_settings; @@ -4229,7 +4230,7 @@ zoran_do_ioctl (struct inode *inode, goto tryfmt_unlock_and_return; } tryfmt_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; break; @@ -4280,7 +4281,7 @@ zoran_poll (struct file *file, * if no buffers queued or so, return POLLNVAL */ - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: @@ -4329,7 +4330,7 @@ zoran_poll (struct file *file, } poll_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -4385,7 +4386,7 @@ zoran_vm_close (struct vm_area_struct *vma) if (fh->jpg_buffers.buffer[i].map) break; if (i == fh->jpg_buffers.num_buffers) { - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.active != ZORAN_FREE) { jpg_qbuf(file, -1, zr->codec_mode); @@ -4398,7 +4399,7 @@ zoran_vm_close (struct vm_area_struct *vma) fh->jpg_buffers.allocated = 0; fh->jpg_buffers.ready_to_be_freed = 1; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } break; @@ -4421,7 +4422,7 @@ zoran_vm_close (struct vm_area_struct *vma) if (fh->v4l_buffers.buffer[i].map) break; if (i == fh->v4l_buffers.num_buffers) { - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.active != ZORAN_FREE) { zr36057_set_memgrab(zr, 0); @@ -4434,7 +4435,7 @@ zoran_vm_close (struct vm_area_struct *vma) fh->v4l_buffers.allocated = 0; fh->v4l_buffers.ready_to_be_freed = 1; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } break; @@ -4489,7 +4490,7 @@ zoran_mmap (struct file *file, case ZORAN_MAP_MODE_JPG_PLAY: /* lock */ - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); /* Map the MJPEG buffers */ if (!fh->jpg_buffers.allocated) { @@ -4579,13 +4580,13 @@ zoran_mmap (struct file *file, } jpg_mmap_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; case ZORAN_MAP_MODE_RAW: - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); /* Map the V4L buffers */ if (!fh->v4l_buffers.allocated) { @@ -4657,7 +4658,7 @@ zoran_mmap (struct file *file, break; } v4l_mmap_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 7d213707008a..2671da20a496 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -9,13 +9,54 @@ * Written by: Michael Chan (mchan@broadcom.com) */ +#include <linux/config.h> + +#include <linux/module.h> +#include <linux/moduleparam.h> + +#include <linux/kernel.h> +#include <linux/timer.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/dma-mapping.h> +#include <asm/bitops.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <linux/delay.h> +#include <asm/byteorder.h> +#include <linux/time.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#ifdef NETIF_F_HW_VLAN_TX +#include <linux/if_vlan.h> +#define BCM_VLAN 1 +#endif +#ifdef NETIF_F_TSO +#include <net/ip.h> +#include <net/tcp.h> +#include <net/checksum.h> +#define BCM_TSO 1 +#endif +#include <linux/workqueue.h> +#include <linux/crc32.h> +#include <linux/prefetch.h> +#include <linux/cache.h> + #include "bnx2.h" #include "bnx2_fw.h" #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.38" -#define DRV_MODULE_RELDATE "February 10, 2006" +#define DRV_MODULE_VERSION "1.4.39" +#define DRV_MODULE_RELDATE "March 22, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -313,8 +354,6 @@ bnx2_disable_int(struct bnx2 *bp) static void bnx2_enable_int(struct bnx2 *bp) { - u32 val; - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx); @@ -322,8 +361,7 @@ bnx2_enable_int(struct bnx2 *bp) REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW); + REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); } static void @@ -362,15 +400,11 @@ bnx2_free_mem(struct bnx2 *bp) { int i; - if (bp->stats_blk) { - pci_free_consistent(bp->pdev, sizeof(struct statistics_block), - bp->stats_blk, bp->stats_blk_mapping); - bp->stats_blk = NULL; - } if (bp->status_blk) { - pci_free_consistent(bp->pdev, sizeof(struct status_block), + pci_free_consistent(bp->pdev, bp->status_stats_size, bp->status_blk, bp->status_blk_mapping); bp->status_blk = NULL; + bp->stats_blk = NULL; } if (bp->tx_desc_ring) { pci_free_consistent(bp->pdev, @@ -395,14 +429,13 @@ bnx2_free_mem(struct bnx2 *bp) static int bnx2_alloc_mem(struct bnx2 *bp) { - int i; + int i, status_blk_size; - bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT, - GFP_KERNEL); + bp->tx_buf_ring = kzalloc(sizeof(struct sw_bd) * TX_DESC_CNT, + GFP_KERNEL); if (bp->tx_buf_ring == NULL) return -ENOMEM; - memset(bp->tx_buf_ring, 0, sizeof(struct sw_bd) * TX_DESC_CNT); bp->tx_desc_ring = pci_alloc_consistent(bp->pdev, sizeof(struct tx_bd) * TX_DESC_CNT, @@ -428,21 +461,22 @@ bnx2_alloc_mem(struct bnx2 *bp) } - bp->status_blk = pci_alloc_consistent(bp->pdev, - sizeof(struct status_block), + /* Combine status and statistics blocks into one allocation. */ + status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); + bp->status_stats_size = status_blk_size + + sizeof(struct statistics_block); + + bp->status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size, &bp->status_blk_mapping); if (bp->status_blk == NULL) goto alloc_mem_err; - memset(bp->status_blk, 0, sizeof(struct status_block)); + memset(bp->status_blk, 0, bp->status_stats_size); - bp->stats_blk = pci_alloc_consistent(bp->pdev, - sizeof(struct statistics_block), - &bp->stats_blk_mapping); - if (bp->stats_blk == NULL) - goto alloc_mem_err; + bp->stats_blk = (void *) ((unsigned long) bp->status_blk + + status_blk_size); - memset(bp->stats_blk, 0, sizeof(struct statistics_block)); + bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; return 0; @@ -1926,6 +1960,13 @@ bnx2_poll(struct net_device *dev, int *budget) spin_lock(&bp->phy_lock); bnx2_phy_int(bp); spin_unlock(&bp->phy_lock); + + /* This is needed to take care of transient status + * during link changes. + */ + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); } if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) @@ -3307,6 +3348,8 @@ bnx2_init_chip(struct bnx2 *bp) udelay(20); + bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND); + return rc; } @@ -3746,7 +3789,6 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) struct sk_buff *skb, *rx_skb; unsigned char *packet; u16 rx_start_idx, rx_idx; - u32 val; dma_addr_t map; struct tx_bd *txbd; struct sw_bd *rx_buf; @@ -3777,8 +3819,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) map = pci_map_single(bp->pdev, skb->data, pkt_size, PCI_DMA_TODEVICE); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); udelay(5); @@ -3802,8 +3845,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) udelay(100); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); udelay(5); @@ -3939,7 +3983,6 @@ static int bnx2_test_intr(struct bnx2 *bp) { int i; - u32 val; u16 status_idx; if (!netif_running(bp->dev)) @@ -3948,8 +3991,7 @@ bnx2_test_intr(struct bnx2 *bp) status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff; /* This register is not touched during run-time. */ - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW); + REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); REG_RD(bp, BNX2_HC_COMMAND); for (i = 0; i < 10; i++) { diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index fd4b7f2eb477..b87925f6a228 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -13,46 +13,6 @@ #ifndef BNX2_H #define BNX2_H -#include <linux/config.h> - -#include <linux/module.h> -#include <linux/moduleparam.h> - -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/dma-mapping.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <linux/delay.h> -#include <asm/byteorder.h> -#include <linux/time.h> -#include <linux/ethtool.h> -#include <linux/mii.h> -#ifdef NETIF_F_HW_VLAN_TX -#include <linux/if_vlan.h> -#define BCM_VLAN 1 -#endif -#ifdef NETIF_F_TSO -#include <net/ip.h> -#include <net/tcp.h> -#include <net/checksum.h> -#define BCM_TSO 1 -#endif -#include <linux/workqueue.h> -#include <linux/crc32.h> -#include <linux/prefetch.h> - /* Hardware data structures and register definitions automatically * generated from RTL code. Do not modify. */ @@ -3917,15 +3877,17 @@ struct bnx2 { #define USING_MSI_FLAG 0x20 #define ASF_ENABLE_FLAG 0x40 - struct tx_bd *tx_desc_ring; - struct sw_bd *tx_buf_ring; - u32 tx_prod_bseq; - u16 tx_prod; - u16 tx_cons; - int tx_ring_size; + /* Put tx producer and consumer fields in separate cache lines. */ - u16 hw_tx_cons; - u16 hw_rx_cons; + u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES))); + u16 tx_prod; + + struct tx_bd *tx_desc_ring; + struct sw_bd *tx_buf_ring; + int tx_ring_size; + + u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES))); + u16 hw_tx_cons; #ifdef BCM_VLAN struct vlan_group *vlgrp; @@ -3939,6 +3901,7 @@ struct bnx2 { u32 rx_prod_bseq; u16 rx_prod; u16 rx_cons; + u16 hw_rx_cons; u32 rx_csum; @@ -4038,6 +4001,7 @@ struct bnx2 { struct statistics_block *stats_blk; dma_addr_t stats_blk_mapping; + u32 hc_cmd; u32 rx_mode; u16 req_line_speed; @@ -4082,6 +4046,8 @@ struct bnx2 { struct flash_spec *flash_info; u32 flash_size; + + int status_stats_size; }; static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 4eda81d41b10..35dbf05c7f06 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -44,7 +44,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.4" +#define DRV_VERSION "1.5" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -357,7 +357,7 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev) skge->net_stats.rx_bytes = data[1]; skge->net_stats.tx_packets = data[2] + data[4] + data[6]; skge->net_stats.rx_packets = data[3] + data[5] + data[7]; - skge->net_stats.multicast = data[5] + data[7]; + skge->net_stats.multicast = data[3] + data[5]; skge->net_stats.collisions = data[10]; skge->net_stats.tx_aborted_errors = data[12]; @@ -781,7 +781,7 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, * Note: DMA address is not changed by chip. * MTU not changed while receiver active. */ -static void skge_rx_reuse(struct skge_element *e, unsigned int size) +static inline void skge_rx_reuse(struct skge_element *e, unsigned int size) { struct skge_rx_desc *rd = e->desc; @@ -829,7 +829,7 @@ static int skge_rx_fill(struct skge_port *skge) do { struct sk_buff *skb; - skb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); + skb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_KERNEL); if (!skb) return -ENOMEM; @@ -847,8 +847,7 @@ static void skge_link_up(struct skge_port *skge) LED_BLK_OFF|LED_SYNC_OFF|LED_ON); netif_carrier_on(skge->netdev); - if (skge->tx_avail > MAX_SKB_FRAGS + 1) - netif_wake_queue(skge->netdev); + netif_wake_queue(skge->netdev); if (netif_msg_link(skge)) printk(KERN_INFO PFX @@ -2155,7 +2154,7 @@ static int skge_up(struct net_device *dev) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); if (dev->mtu > RX_BUF_SIZE) - skge->rx_buf_size = dev->mtu + ETH_HLEN + NET_IP_ALIGN; + skge->rx_buf_size = dev->mtu + ETH_HLEN; else skge->rx_buf_size = RX_BUF_SIZE; @@ -2190,8 +2189,6 @@ static int skge_up(struct net_device *dev) if (err) goto free_rx_ring; - skge->tx_avail = skge->tx_ring.count - 1; - /* Initialize MAC */ spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) @@ -2294,6 +2291,12 @@ static int skge_down(struct net_device *dev) return 0; } +static inline int skge_avail(const struct skge_ring *ring) +{ + return ((ring->to_clean > ring->to_use) ? 0 : ring->count) + + (ring->to_clean - ring->to_use) - 1; +} + static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) { struct skge_port *skge = netdev_priv(dev); @@ -2314,7 +2317,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_LOCKED; } - if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { + if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -2390,8 +2393,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) dev->name, e - ring->start, skb->len); ring->to_use = e->next; - skge->tx_avail -= skb_shinfo(skb)->nr_frags + 1; - if (skge->tx_avail <= MAX_SKB_FRAGS + 1) { + if (skge_avail(&skge->tx_ring) <= MAX_SKB_FRAGS + 1) { pr_debug("%s: transmit queue full\n", dev->name); netif_stop_queue(dev); } @@ -2404,35 +2406,37 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e) +static void skge_tx_complete(struct skge_port *skge, struct skge_element *last) { - /* This ring element can be skb or fragment */ - if (e->skb) { - pci_unmap_single(hw->pdev, - pci_unmap_addr(e, mapaddr), - pci_unmap_len(e, maplen), - PCI_DMA_TODEVICE); - dev_kfree_skb(e->skb); + struct pci_dev *pdev = skge->hw->pdev; + struct skge_element *e; + + for (e = skge->tx_ring.to_clean; e != last; e = e->next) { + struct sk_buff *skb = e->skb; + int i; + e->skb = NULL; - } else { - pci_unmap_page(hw->pdev, - pci_unmap_addr(e, mapaddr), - pci_unmap_len(e, maplen), - PCI_DMA_TODEVICE); + pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr), + skb_headlen(skb), PCI_DMA_TODEVICE); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + e = e->next; + pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr), + skb_shinfo(skb)->frags[i].size, + PCI_DMA_TODEVICE); + } + + dev_kfree_skb(skb); } + skge->tx_ring.to_clean = e; } static void skge_tx_clean(struct skge_port *skge) { - struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; spin_lock_bh(&skge->tx_lock); - for (e = ring->to_clean; e != ring->to_use; e = e->next) { - ++skge->tx_avail; - skge_tx_free(skge->hw, e); - } - ring->to_clean = e; + skge_tx_complete(skge, skge->tx_ring.to_use); + netif_wake_queue(skge->netdev); spin_unlock_bh(&skge->tx_lock); } @@ -2592,7 +2596,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, goto error; if (len < RX_COPY_THRESHOLD) { - skb = dev_alloc_skb(len + 2); + skb = alloc_skb(len + 2, GFP_ATOMIC); if (!skb) goto resubmit; @@ -2607,10 +2611,11 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, skge_rx_reuse(e, skge->rx_buf_size); } else { struct sk_buff *nskb; - nskb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); + nskb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_ATOMIC); if (!nskb) goto resubmit; + skb_reserve(nskb, NET_IP_ALIGN); pci_unmap_single(skge->hw->pdev, pci_unmap_addr(e, mapaddr), pci_unmap_len(e, maplen), @@ -2661,30 +2666,29 @@ resubmit: static void skge_tx_done(struct skge_port *skge) { struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; + struct skge_element *e, *last; spin_lock(&skge->tx_lock); - for (e = ring->to_clean; prefetch(e->next), e != ring->to_use; e = e->next) { + last = ring->to_clean; + for (e = ring->to_clean; e != ring->to_use; e = e->next) { struct skge_tx_desc *td = e->desc; - u32 control; - rmb(); - control = td->control; - if (control & BMU_OWN) + if (td->control & BMU_OWN) break; - if (unlikely(netif_msg_tx_done(skge))) - printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n", - skge->netdev->name, e - ring->start, td->status); - - skge_tx_free(skge->hw, e); - e->skb = NULL; - ++skge->tx_avail; + if (td->control & BMU_EOF) { + last = e->next; + if (unlikely(netif_msg_tx_done(skge))) + printk(KERN_DEBUG PFX "%s: tx done slot %td\n", + skge->netdev->name, e - ring->start); + } } - ring->to_clean = e; + + skge_tx_complete(skge, last); + skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - if (skge->tx_avail > MAX_SKB_FRAGS + 1) + if (skge_avail(&skge->tx_ring) > MAX_SKB_FRAGS + 1) netif_wake_queue(skge->netdev); spin_unlock(&skge->tx_lock); @@ -2718,8 +2722,7 @@ static int skge_poll(struct net_device *dev, int *budget) netif_receive_skb(skb); ++work_done; - } else - skge_rx_reuse(e, skge->rx_buf_size); + } } ring->to_clean = e; diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 2efdacc290e5..1f1ce88c8186 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2418,7 +2418,6 @@ struct skge_port { int port; spinlock_t tx_lock; - u32 tx_avail; struct skge_ring tx_ring; struct skge_ring rx_ring; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 36db93811ac7..68f9c206a620 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1175,7 +1175,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* just drop the packet if non-linear expansion fails */ if (skb_header_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); goto out_unlock; } @@ -1324,7 +1324,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) PCI_DMA_TODEVICE); } - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); } sky2->tx_cons = put; @@ -2484,7 +2484,7 @@ static const struct sky2_stat { { "single_collisions", GM_TXF_SNG_COL }, { "multi_collisions", GM_TXF_MUL_COL }, - { "rx_short", GM_RXE_SHT }, + { "rx_short", GM_RXF_SHT }, { "rx_runt", GM_RXE_FRAG }, { "rx_64_byte_packets", GM_RXF_64B }, { "rx_65_to_127_byte_packets", GM_RXF_127B }, @@ -2607,7 +2607,7 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev) sky2->net_stats.rx_bytes = data[1]; sky2->net_stats.tx_packets = data[2] + data[4] + data[6]; sky2->net_stats.rx_packets = data[3] + data[5] + data[7]; - sky2->net_stats.multicast = data[5] + data[7]; + sky2->net_stats.multicast = data[3] + data[5]; sky2->net_stats.collisions = data[10]; sky2->net_stats.tx_aborted_errors = data[12]; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 88829eb9568e..b5473325bff4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.53" -#define DRV_MODULE_RELDATE "Mar 22, 2006" +#define DRV_MODULE_VERSION "3.54" +#define DRV_MODULE_RELDATE "Mar 23, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -225,6 +225,10 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, @@ -4557,6 +4561,7 @@ static int tg3_chip_reset(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tw32(GRC_FASTBOOT_PC, 0); @@ -6152,6 +6157,9 @@ static int tg3_reset_hw(struct tg3 *tp) gpio_mask |= GRC_LCLCTRL_GPIO_OE3 | GRC_LCLCTRL_GPIO_OUTPUT3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL; + tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; /* GPIO1 must be driven high for eeprom write protect */ @@ -6191,7 +6199,8 @@ static int tg3_reset_hw(struct tg3 *tp) } /* Enable host coalescing bug fix */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) val |= (1 << 29); tw32_f(WDMAC_MODE, val); @@ -6249,6 +6258,9 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(100); tp->rx_mode = RX_MODE_ENABLE; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); @@ -7907,7 +7919,8 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) return 0; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ethtool_op_set_tx_hw_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -8332,7 +8345,8 @@ static int tg3_test_memory(struct tg3 *tp) int i; if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) mem_tbl = mem_tbl_5755; else mem_tbl = mem_tbl_5705; @@ -8924,6 +8938,47 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) } } +static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1; + + nvcfg1 = tr32(NVRAM_CFG1); + + /* NVRAM protection for TPM */ + if (nvcfg1 & (1 << 27)) + tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + + switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { + case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ: + case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + + nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; + tw32(NVRAM_CFG1, nvcfg1); + break; + case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: + case FLASH_5755VENDOR_ATMEL_FLASH_1: + case FLASH_5755VENDOR_ATMEL_FLASH_2: + case FLASH_5755VENDOR_ATMEL_FLASH_3: + case FLASH_5755VENDOR_ATMEL_FLASH_4: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 264; + break; + case FLASH_5752VENDOR_ST_M45PE10: + case FLASH_5752VENDOR_ST_M45PE20: + case FLASH_5752VENDOR_ST_M45PE40: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 256; + break; + } +} + static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -8997,6 +9052,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tg3_get_5752_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tg3_get_5755_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tg3_get_5787_nvram_info(tp); else @@ -9310,6 +9367,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, nvram_cmd |= NVRAM_CMD_LAST; if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { @@ -10044,6 +10102,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -10053,7 +10112,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; } else @@ -10063,6 +10123,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; @@ -10219,6 +10280,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { @@ -10274,6 +10338,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; @@ -10413,7 +10478,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* All chips before 5787 can get confused if TX buffers * straddle the 4GB address boundary in some cases. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tp->dev->hard_start_xmit = tg3_start_xmit; else tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; @@ -11002,6 +11068,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; + case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; @@ -11350,7 +11417,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) dev->features |= NETIF_F_HW_CSUM; else dev->features |= NETIF_F_IP_CSUM; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index baa34c4721db..c43cc3264202 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -138,6 +138,7 @@ #define ASIC_REV_5752 0x06 #define ASIC_REV_5780 0x08 #define ASIC_REV_5714 0x09 +#define ASIC_REV_5755 0x0a #define ASIC_REV_5787 0x0b #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 @@ -456,6 +457,7 @@ #define RX_MODE_PROMISC 0x00000100 #define RX_MODE_NO_CRC_CHECK 0x00000200 #define RX_MODE_KEEP_VLAN_TAG 0x00000400 +#define RX_MODE_IPV6_CSUM_ENABLE 0x01000000 #define MAC_RX_STATUS 0x0000046c #define RX_STATUS_REMOTE_TX_XOFFED 0x00000001 #define RX_STATUS_XOFF_RCVD 0x00000002 @@ -1340,6 +1342,7 @@ #define GRC_LCLCTRL_CLEARINT 0x00000002 #define GRC_LCLCTRL_SETINT 0x00000004 #define GRC_LCLCTRL_INT_ON_ATTN 0x00000008 +#define GRC_LCLCTRL_GPIO_UART_SEL 0x00000010 /* 5755 only */ #define GRC_LCLCTRL_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */ #define GRC_LCLCTRL_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */ #define GRC_LCLCTRL_GPIO_INPUT3 0x00000020 @@ -1441,6 +1444,9 @@ #define FLASH_5755VENDOR_ATMEL_FLASH_1 0x03400001 #define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002 #define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000 +#define FLASH_5755VENDOR_ATMEL_FLASH_4 0x00000003 +#define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003 +#define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002 #define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003 #define FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ 0x03000002 #define FLASH_5787VENDOR_MICRO_EEPROM_64KHZ 0x03000000 @@ -2259,6 +2265,7 @@ struct tg3 { #define PHY_ID_BCM5752 0x60008100 #define PHY_ID_BCM5714 0x60008340 #define PHY_ID_BCM5780 0x60008350 +#define PHY_ID_BCM5755 0xbc050cc0 #define PHY_ID_BCM5787 0xbc050ce0 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff @@ -2286,7 +2293,7 @@ struct tg3 { (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ - (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 5b0a19a5058d..6a1033ec06cf 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -25,6 +25,15 @@ config NET_RADIO the tools from <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. +config NET_WIRELESS_RTNETLINK + bool "Wireless Extension API over RtNetlink" + ---help--- + Support the Wireless Extension API over the RtNetlink socket + in addition to the traditional ioctl interface (selected above). + + For now, few tools use this facility, but it might grow in the + future. The only downside is that it adds 4.5 kB to your kernel. + # Note : the cards are obsolete (can't buy them anymore), but the drivers # are not, as people are still using them... comment "Obsolete Wireless cards support (pre-802.11)" diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 864937a409e5..108d9fed8f07 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -770,6 +770,11 @@ typedef struct { } BSSListRid; typedef struct { + BSSListRid bss; + struct list_head list; +} BSSListElement; + +typedef struct { u8 rssipct; u8 rssidBm; } tdsRssiEntry; @@ -902,6 +907,7 @@ static char swversion[] = "2.1"; #define NUM_MODULES 2 #define MIC_MSGLEN_MAX 2400 #define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX +#define AIRO_DEF_MTU 2312 typedef struct { u32 size; // size @@ -1119,6 +1125,8 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi); static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm); +static void airo_networks_free(struct airo_info *ai); + struct airo_info { struct net_device_stats stats; struct net_device *dev; @@ -1150,7 +1158,7 @@ struct airo_info { #define FLAG_COMMIT 13 #define FLAG_RESET 14 #define FLAG_FLASHING 15 -#define JOB_MASK 0x1ff0000 +#define JOB_MASK 0x2ff0000 #define JOB_DIE 16 #define JOB_XMIT 17 #define JOB_XMIT11 18 @@ -1160,6 +1168,7 @@ struct airo_info { #define JOB_EVENT 22 #define JOB_AUTOWEP 23 #define JOB_WSTATS 24 +#define JOB_SCAN_RESULTS 25 int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap); unsigned short *flash; @@ -1176,7 +1185,7 @@ struct airo_info { } xmit, xmit11; struct net_device *wifidev; struct iw_statistics wstats; // wireless stats - unsigned long scan_timestamp; /* Time started to scan */ + unsigned long scan_timeout; /* Time scan should be read */ struct iw_spy_data spy_data; struct iw_public_data wireless_data; /* MIC stuff */ @@ -1198,6 +1207,10 @@ struct airo_info { APListRid *APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ]; + + struct list_head network_list; + struct list_head network_free_list; + BSSListElement *networks; }; static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, @@ -1216,6 +1229,22 @@ static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime); static int flashputbuf(struct airo_info *ai); static int flashrestart(struct airo_info *ai,struct net_device *dev); +#define airo_print(type, name, fmt, args...) \ + { printk(type "airo(%s): " fmt "\n", name, ##args); } + +#define airo_print_info(name, fmt, args...) \ + airo_print(KERN_INFO, name, fmt, ##args) + +#define airo_print_dbg(name, fmt, args...) \ + airo_print(KERN_DEBUG, name, fmt, ##args) + +#define airo_print_warn(name, fmt, args...) \ + airo_print(KERN_WARNING, name, fmt, ##args) + +#define airo_print_err(name, fmt, args...) \ + airo_print(KERN_ERR, name, fmt, ##args) + + /*********************************************************************** * MIC ROUTINES * *********************************************************************** @@ -1294,7 +1323,7 @@ static int micsetup(struct airo_info *ai) { ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP); if (ai->tfm == NULL) { - printk(KERN_ERR "airo: failed to load transform for AES\n"); + airo_print_err(ai->dev->name, "failed to load transform for AES"); return ERROR; } @@ -1726,11 +1755,11 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lo wkr.kindex = cpu_to_le16(wkr.kindex); wkr.klen = cpu_to_le16(wkr.klen); rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock); - if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc); + if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc); if (perm) { rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock); if (rc!=SUCCESS) { - printk(KERN_ERR "airo: WEP_PERM set %x\n", rc); + airo_print_err(ai->dev->name, "WEP_PERM set %x", rc); } } return rc; @@ -1909,7 +1938,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct airo_info *ai = dev->priv; if (!skb) { - printk(KERN_ERR "airo: %s: skb==NULL\n",__FUNCTION__); + airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__); return 0; } npacks = skb_queue_len (&ai->txq); @@ -1955,8 +1984,8 @@ static int mpi_send_packet (struct net_device *dev) /* get a packet to send */ if ((skb = skb_dequeue(&ai->txq)) == 0) { - printk (KERN_ERR - "airo: %s: Dequeue'd zero in send_packet()\n", + airo_print_err(dev->name, + "%s: Dequeue'd zero in send_packet()", __FUNCTION__); return 0; } @@ -2108,7 +2137,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { u32 *fids = priv->fids; if ( skb == NULL ) { - printk( KERN_ERR "airo: skb == NULL!!!\n" ); + airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__); return 0; } @@ -2179,7 +2208,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { } if ( skb == NULL ) { - printk( KERN_ERR "airo: skb == NULL!!!\n" ); + airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__); return 0; } @@ -2364,6 +2393,8 @@ void stop_airo_card( struct net_device *dev, int freeres ) dev_kfree_skb(skb); } + airo_networks_free (ai); + kfree(ai->flash); kfree(ai->rssi); kfree(ai->APList); @@ -2434,7 +2465,7 @@ static int mpi_init_descriptors (struct airo_info *ai) cmd.parm2 = MPI_MAX_FIDS; rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate RX FID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate RX FID"); return rc; } @@ -2462,7 +2493,7 @@ static int mpi_init_descriptors (struct airo_info *ai) rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate TX FID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate TX FID"); return rc; } @@ -2476,7 +2507,7 @@ static int mpi_init_descriptors (struct airo_info *ai) cmd.parm2 = 1; /* Magic number... */ rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate RID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate RID"); return rc; } @@ -2508,25 +2539,25 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, aux_len = AUXMEMSIZE; if (!request_mem_region(mem_start, mem_len, name)) { - printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", (int)mem_start, (int)mem_len, name); goto out; } if (!request_mem_region(aux_start, aux_len, name)) { - printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", (int)aux_start, (int)aux_len, name); goto free_region1; } ai->pcimem = ioremap(mem_start, mem_len); if (!ai->pcimem) { - printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", (int)mem_start, (int)mem_len, name); goto free_region2; } ai->pciaux = ioremap(aux_start, aux_len); if (!ai->pciaux) { - printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", (int)aux_start, (int)aux_len, name); goto free_memmap; } @@ -2534,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, /* Reserve PKTSIZE for each fid and 2K for the Rids */ ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma); if (!ai->shared) { - printk(KERN_ERR "airo: Couldn't alloc_consistent %d\n", + airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d", PCI_SHARED_LEN); goto free_auxmap; } @@ -2626,7 +2657,7 @@ static void wifi_setup(struct net_device *dev) dev->type = ARPHRD_IEEE80211; dev->hard_header_len = ETH_HLEN; - dev->mtu = 2312; + dev->mtu = AIRO_DEF_MTU; dev->addr_len = ETH_ALEN; dev->tx_queue_len = 100; @@ -2670,6 +2701,42 @@ static int reset_card( struct net_device *dev , int lock) { return 0; } +#define MAX_NETWORK_COUNT 64 +static int airo_networks_allocate(struct airo_info *ai) +{ + if (ai->networks) + return 0; + + ai->networks = + kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement), + GFP_KERNEL); + if (!ai->networks) { + airo_print_warn(ai->dev->name, "Out of memory allocating beacons"); + return -ENOMEM; + } + + return 0; +} + +static void airo_networks_free(struct airo_info *ai) +{ + if (!ai->networks) + return; + kfree(ai->networks); + ai->networks = NULL; +} + +static void airo_networks_initialize(struct airo_info *ai) +{ + int i; + + INIT_LIST_HEAD(&ai->network_free_list); + INIT_LIST_HEAD(&ai->network_list); + for (i = 0; i < MAX_NETWORK_COUNT; i++) + list_add_tail(&ai->networks[i].list, + &ai->network_free_list); +} + static struct net_device *_init_airo_card( unsigned short irq, int port, int is_pcmcia, struct pci_dev *pci, struct device *dmdev ) @@ -2681,22 +2748,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, /* Create the network device object. */ dev = alloc_etherdev(sizeof(*ai)); if (!dev) { - printk(KERN_ERR "airo: Couldn't alloc_etherdev\n"); + airo_print_err("", "Couldn't alloc_etherdev"); return NULL; } if (dev_alloc_name(dev, dev->name) < 0) { - printk(KERN_ERR "airo: Couldn't get name!\n"); + airo_print_err("", "Couldn't get name!"); goto err_out_free; } ai = dev->priv; ai->wifidev = NULL; ai->flags = 0; + ai->dev = dev; if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { - printk(KERN_DEBUG "airo: Found an MPI350 card\n"); + airo_print_dbg(dev->name, "Found an MPI350 card"); set_bit(FLAG_MPI, &ai->flags); } - ai->dev = dev; spin_lock_init(&ai->aux_lock); sema_init(&ai->sem, 1); ai->config.len = 0; @@ -2711,6 +2778,10 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, if (rc) goto err_out_thr; + if (airo_networks_allocate (ai)) + goto err_out_unlink; + airo_networks_initialize (ai); + /* The Airo-specific entries in the device structure. */ if (test_bit(FLAG_MPI,&ai->flags)) { skb_queue_head_init (&ai->txq); @@ -2732,33 +2803,33 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, SET_NETDEV_DEV(dev, dmdev); - reset_card (dev, 1); msleep(400); rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev ); if (rc) { - printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc ); + airo_print_err(dev->name, "register interrupt %d failed, rc %d", + irq, rc); goto err_out_unlink; } if (!is_pcmcia) { if (!request_region( dev->base_addr, 64, dev->name )) { rc = -EBUSY; - printk(KERN_ERR "airo: Couldn't request region\n"); + airo_print_err(dev->name, "Couldn't request region"); goto err_out_irq; } } if (test_bit(FLAG_MPI,&ai->flags)) { if (mpi_map_card(ai, pci, dev->name)) { - printk(KERN_ERR "airo: Could not map memory\n"); + airo_print_err(dev->name, "Could not map memory"); goto err_out_res; } } if (probe) { if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) { - printk( KERN_ERR "airo: MAC could not be enabled\n" ); + airo_print_err(dev->name, "MAC could not be enabled" ); rc = -EIO; goto err_out_map; } @@ -2769,21 +2840,20 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, rc = register_netdev(dev); if (rc) { - printk(KERN_ERR "airo: Couldn't register_netdev\n"); + airo_print_err(dev->name, "Couldn't register_netdev"); goto err_out_map; } ai->wifidev = init_wifidev(ai, dev); set_bit(FLAG_REGISTERED,&ai->flags); - printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", - dev->name, + airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x", dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] ); /* Allocate the transmit buffers */ if (probe && !test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate(ai,2312,i>=MAX_FIDS/2); + ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); setup_proc_entry( dev, dev->priv ); /* XXX check for failure */ netif_start_queue(dev); @@ -2840,16 +2910,16 @@ int reset_airo_card( struct net_device *dev ) return -1; if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) { - printk( KERN_ERR "airo: MAC could not be enabled\n" ); + airo_print_err(dev->name, "MAC could not be enabled"); return -1; } - printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", dev->name, + airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x", dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); /* Allocate the transmit buffers if needed */ if (!test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate (ai,2312,i>=MAX_FIDS/2); + ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); enable_interrupts( ai ); netif_wake_queue(dev); @@ -2875,6 +2945,65 @@ static void airo_send_event(struct net_device *dev) { wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); } +static void airo_process_scan_results (struct airo_info *ai) { + union iwreq_data wrqu; + BSSListRid BSSList; + int rc; + BSSListElement * loop_net; + BSSListElement * tmp_net; + + /* Blow away current list of scan results */ + list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) { + list_move_tail (&loop_net->list, &ai->network_free_list); + /* Don't blow away ->list, just BSS data */ + memset (loop_net, 0, sizeof (loop_net->bss)); + } + + /* Try to read the first entry of the scan result */ + rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0); + if((rc) || (BSSList.index == 0xffff)) { + /* No scan results */ + goto out; + } + + /* Read and parse all entries */ + tmp_net = NULL; + while((!rc) && (BSSList.index != 0xffff)) { + /* Grab a network off the free list */ + if (!list_empty(&ai->network_free_list)) { + tmp_net = list_entry(ai->network_free_list.next, + BSSListElement, list); + list_del(ai->network_free_list.next); + } + + if (tmp_net != NULL) { + memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss)); + list_add_tail(&tmp_net->list, &ai->network_list); + tmp_net = NULL; + } + + /* Read next entry */ + rc = PC4500_readrid(ai, RID_BSSLISTNEXT, + &BSSList, sizeof(BSSList), 0); + } + +out: + ai->scan_timeout = 0; + clear_bit(JOB_SCAN_RESULTS, &ai->flags); + up(&ai->sem); + + /* Send an empty event to user space. + * We don't send the received data on + * the event because it would require + * us to do complex transcoding, and + * we want to minimise the work done in + * the irq handler. Use a request to + * extract the data - Jean II */ + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL); +} + static int airo_thread(void *data) { struct net_device *dev = data; struct airo_info *ai = dev->priv; @@ -2904,13 +3033,26 @@ static int airo_thread(void *data) { set_current_state(TASK_INTERRUPTIBLE); if (ai->flags & JOB_MASK) break; - if (ai->expires) { - if (time_after_eq(jiffies,ai->expires)){ + if (ai->expires || ai->scan_timeout) { + if (ai->scan_timeout && + time_after_eq(jiffies,ai->scan_timeout)){ + set_bit(JOB_SCAN_RESULTS,&ai->flags); + break; + } else if (ai->expires && + time_after_eq(jiffies,ai->expires)){ set_bit(JOB_AUTOWEP,&ai->flags); break; } if (!signal_pending(current)) { - schedule_timeout(ai->expires - jiffies); + unsigned long wake_at; + if (!ai->expires || !ai->scan_timeout) { + wake_at = max(ai->expires, + ai->scan_timeout); + } else { + wake_at = min(ai->expires, + ai->scan_timeout); + } + schedule_timeout(wake_at - jiffies); continue; } } else if (!signal_pending(current)) { @@ -2953,6 +3095,10 @@ static int airo_thread(void *data) { airo_send_event(dev); else if (test_bit(JOB_AUTOWEP, &ai->flags)) timer_func(dev); + else if (test_bit(JOB_SCAN_RESULTS, &ai->flags)) + airo_process_scan_results(ai); + else /* Shouldn't get here, but we make sure to unlock */ + up(&ai->sem); } complete_and_exit (&ai->thr_exited, 0); } @@ -3047,19 +3193,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) * and reassociations as valid status * Jean II */ if(newStatus == ASSOCIATED) { - if (apriv->scan_timestamp) { - /* Send an empty event to user space. - * We don't send the received data on - * the event because it would require - * us to do complex transcoding, and - * we want to minimise the work done in - * the irq handler. Use a request to - * extract the data - Jean II */ - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); - apriv->scan_timestamp = 0; +#if 0 + /* FIXME: Grabbing scan results here + * seems to be too early??? Just wait for + * timeout instead. */ + if (apriv->scan_timeout > 0) { + set_bit(JOB_SCAN_RESULTS, &apriv->flags); + wake_up_interruptible(&apriv->thr_wait); } +#endif if (down_trylock(&apriv->sem) != 0) { set_bit(JOB_EVENT, &apriv->flags); wake_up_interruptible(&apriv->thr_wait); @@ -3117,8 +3259,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) } len = le16_to_cpu(hdr.len); - if (len > 2312) { - printk( KERN_ERR "airo: Bad size %d\n", len ); + if (len > AIRO_DEF_MTU) { + airo_print_err(apriv->dev->name, "Bad size %d", len); goto badrx; } if (len == 0) @@ -3161,10 +3303,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) bap_read (apriv, &gap, sizeof(gap), BAP0); gap = le16_to_cpu(gap); if (gap) { - if (gap <= 8) + if (gap <= 8) { bap_read (apriv, tmpbuf, gap, BAP0); - else - printk(KERN_ERR "airo: gaplen too big. Problems will follow...\n"); + } else { + airo_print_err(apriv->dev->name, "gaplen too " + "big. Problems will follow..."); + } } bap_read (apriv, buffer + hdrlen/2, len, BAP0); } else { @@ -3281,12 +3425,13 @@ exitrx: } } else { OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); - printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" ); + airo_print_err(apriv->dev->name, "Unallocated FID was " + "used to xmit" ); } } exittx: if ( status & ~STATUS_INTS & ~IGNORE_INTS ) - printk( KERN_WARNING "airo: Got weird status %x\n", + airo_print_warn(apriv->dev->name, "Got weird status %x", status & ~STATUS_INTS & ~IGNORE_INTS ); } @@ -3359,8 +3504,8 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { up(&ai->sem); if (rc) - printk(KERN_ERR "%s: Cannot enable MAC, err=%d\n", - __FUNCTION__,rc); + airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d", + __FUNCTION__, rc); return rc; } @@ -3489,8 +3634,8 @@ void mpi_receive_802_11 (struct airo_info *ai) if (ai->wifidev == NULL) hdr.len = 0; len = le16_to_cpu(hdr.len); - if (len > 2312) { - printk( KERN_ERR "airo: Bad size %d\n", len ); + if (len > AIRO_DEF_MTU) { + airo_print_err(ai->dev->name, "Bad size %d", len); goto badrx; } if (len == 0) @@ -3531,8 +3676,8 @@ void mpi_receive_802_11 (struct airo_info *ai) if (gap <= 8) ptr += gap; else - printk(KERN_ERR - "airo: gaplen too big. Problems will follow...\n"); + airo_print_err(ai->dev->name, + "gaplen too big. Problems will follow..."); } memcpy ((char *)buffer + hdrlen, ptr, len); ptr += len; @@ -3604,15 +3749,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { if (lock) up(&ai->sem); - printk(KERN_ERR "airo: Error checking for AUX port\n"); + airo_print_err(ai->dev->name, "Error checking for AUX port"); return ERROR; } if (!aux_bap || rsp.status & 0xff00) { ai->bap_read = fast_bap_read; - printk(KERN_DEBUG "airo: Doing fast bap_reads\n"); + airo_print_dbg(ai->dev->name, "Doing fast bap_reads"); } else { ai->bap_read = aux_bap_read; - printk(KERN_DEBUG "airo: Doing AUX bap_reads\n"); + airo_print_dbg(ai->dev->name, "Doing AUX bap_reads"); } } if (lock) @@ -3643,7 +3788,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if (cap_rid.softCap & 8) ai->config.rmode |= RXMODE_NORMALIZED_RSSI; else - printk(KERN_WARNING "airo: unknown received signal level scale\n"); + airo_print_warn(ai->dev->name, "unknown received signal " + "level scale"); } ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; ai->config.authType = AUTH_OPEN; @@ -3706,7 +3852,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) status = enable_MAC(ai, &rsp, lock); if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) { - printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); + airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x," + " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); return ERROR; } @@ -3749,8 +3896,8 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { } if ( max_tries == -1 ) { - printk( KERN_ERR - "airo: Max tries exceeded when issueing command\n" ); + airo_print_err(ai->dev->name, + "Max tries exceeded when issueing command"); if (IN4500(ai, COMMAND) & COMMAND_BUSY) OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); return ERROR; @@ -3762,11 +3909,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { pRsp->rsp1 = IN4500(ai, RESP1); pRsp->rsp2 = IN4500(ai, RESP2); if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) { - printk (KERN_ERR "airo: cmd= %x\n", pCmd->cmd); - printk (KERN_ERR "airo: status= %x\n", pRsp->status); - printk (KERN_ERR "airo: Rsp0= %x\n", pRsp->rsp0); - printk (KERN_ERR "airo: Rsp1= %x\n", pRsp->rsp1); - printk (KERN_ERR "airo: Rsp2= %x\n", pRsp->rsp2); + airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd); + airo_print_err(ai->dev->name, "status= %x\n", pRsp->status); + airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0); + airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1); + airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2); } // clear stuck command busy if necessary @@ -3799,15 +3946,15 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap ) } } else if ( status & BAP_ERR ) { /* invalid rid or offset */ - printk( KERN_ERR "airo: BAP error %x %d\n", + airo_print_err(ai->dev->name, "BAP error %x %d", status, whichbap ); return ERROR; } else if (status & BAP_DONE) { // success return SUCCESS; } if ( !(max_tries--) ) { - printk( KERN_ERR - "airo: BAP setup error too many retries\n" ); + airo_print_err(ai->dev->name, + "airo: BAP setup error too many retries\n"); return ERROR; } // -- PC4500 missed it, try again @@ -3962,8 +4109,8 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2; if ( len <= 2 ) { - printk( KERN_ERR - "airo: Rid %x has a length of %d which is too short\n", + airo_print_err(ai->dev->name, + "Rid %x has a length of %d which is too short", (int)rid, (int)len ); rc = ERROR; goto done; @@ -3996,8 +4143,8 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, Resp rsp; if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid)) - printk(KERN_ERR - "%s: MAC should be disabled (rid=%04x)\n", + airo_print_err(ai->dev->name, + "%s: MAC should be disabled (rid=%04x)", __FUNCTION__, rid); memset(&cmd, 0, sizeof(cmd)); memset(&rsp, 0, sizeof(rsp)); @@ -4013,7 +4160,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, &ai->config_desc.rid_desc, sizeof(Rid)); if (len < 4 || len > 2047) { - printk(KERN_ERR "%s: len=%d\n",__FUNCTION__,len); + airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len); rc = -1; } else { memcpy((char *)ai->config_desc.virtual_host_addr, @@ -4021,10 +4168,10 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, rc = issuecommand(ai, &cmd, &rsp); if ((rc & 0xff00) != 0) { - printk(KERN_ERR "%s: Write rid Error %d\n", - __FUNCTION__,rc); - printk(KERN_ERR "%s: Cmd=%04x\n", - __FUNCTION__,cmd.cmd); + airo_print_err(ai->dev->name, "%s: Write rid Error %d", + __FUNCTION__, rc); + airo_print_err(ai->dev->name, "%s: Cmd=%04x", + __FUNCTION__, cmd.cmd); } if ((rsp.status & 0x7f00)) @@ -4123,7 +4270,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) len >>= 16; if (len <= ETH_ALEN * 2) { - printk( KERN_WARNING "Short packet %d\n", len ); + airo_print_warn(ai->dev->name, "Short packet %d", len); return ERROR; } len -= ETH_ALEN * 2; @@ -4187,7 +4334,7 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket) } if (len < hdrlen) { - printk( KERN_WARNING "Short packet %d\n", len ); + airo_print_warn(ai->dev->name, "Short packet %d", len); return ERROR; } @@ -4584,15 +4731,14 @@ static int proc_stats_rid_open( struct inode *inode, i*4<stats.len; i++){ if (!statsLabels[i]) continue; if (j+strlen(statsLabels[i])+16>4096) { - printk(KERN_WARNING - "airo: Potentially disasterous buffer overflow averted!\n"); + airo_print_warn(apriv->dev->name, + "Potentially disasterous buffer overflow averted!"); break; } j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]); } if (i*4>=stats.len){ - printk(KERN_WARNING - "airo: Got a short rid\n"); + airo_print_warn(apriv->dev->name, "Got a short rid"); } data->readlen = j; return 0; @@ -4754,7 +4900,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 14; v = get_dec_u16(line, &i, 4); - v = (v<0) ? 0 : ((v>2312) ? 2312 : v); + v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); ai->config.rtsThres = (u16)v; set_bit (FLAG_COMMIT, &ai->flags); } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) { @@ -4788,7 +4934,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 15; v = get_dec_u16(line, &i, 4); - v = (v<256) ? 256 : ((v>2312) ? 2312 : v); + v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); v = v & 0xfffe; /* Make sure its even */ ai->config.fragThresh = (u16)v; set_bit (FLAG_COMMIT, &ai->flags); @@ -4798,8 +4944,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { case 'd': ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break; case 'c': ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break; case 'm': ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break; - default: - printk( KERN_WARNING "airo: Unknown modulation\n" ); + default: airo_print_warn(ai->dev->name, "Unknown modulation"); } } else if (!strncmp(line, "Preamble: ", 10)) { line += 10; @@ -4807,10 +4952,10 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break; case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break; case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break; - default: printk(KERN_WARNING "airo: Unknown preamble\n"); + default: airo_print_warn(ai->dev->name, "Unknown preamble"); } } else { - printk( KERN_WARNING "Couldn't figure out %s\n", line ); + airo_print_warn(ai->dev->name, "Couldn't figure out %s", line); } while( line[0] && line[0] != '\n' ) line++; if ( line[0] ) line++; @@ -5076,7 +5221,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { } j = 2; } else { - printk(KERN_ERR "airo: WepKey passed invalid key index\n"); + airo_print_err(ai->dev->name, "WepKey passed invalid key index"); return; } @@ -5489,17 +5634,16 @@ static int __init airo_init_module( void ) airo_entry->gid = proc_gid; for( i = 0; i < 4 && io[i] && irq[i]; i++ ) { - printk( KERN_INFO - "airo: Trying to configure ISA adapter at irq=%d io=0x%x\n", - irq[i], io[i] ); + airo_print_info("", "Trying to configure ISA adapter at irq=%d " + "io=0x%x", irq[i], io[i] ); if (init_airo_card( irq[i], io[i], 0, NULL )) have_isa_dev = 1; } #ifdef CONFIG_PCI - printk( KERN_INFO "airo: Probing for PCI adapters\n" ); + airo_print_info("", "Probing for PCI adapters"); pci_register_driver(&airo_driver); - printk( KERN_INFO "airo: Finished probing for PCI adapters\n" ); + airo_print_info("", "Finished probing for PCI adapters"); #endif /* Always exit with success, as we are a library module @@ -5511,7 +5655,7 @@ static int __init airo_init_module( void ) static void __exit airo_cleanup_module( void ) { while( airo_devices ) { - printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name ); + airo_print_info(airo_devices->dev->name, "Unregistering...\n"); stop_airo_card( airo_devices->dev, 1 ); } #ifdef CONFIG_PCI @@ -5622,7 +5766,8 @@ static int airo_set_freq(struct net_device *dev, /* We should do a better check than that, * based on the card capability !!! */ if((channel < 1) || (channel > 14)) { - printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m); + airo_print_dbg(dev->name, "New channel value of %d is invalid!", + fwrq->m); rc = -EINVAL; } else { readConfigRid(local, 1); @@ -5946,8 +6091,8 @@ static int airo_set_rts(struct net_device *dev, int rthr = vwrq->value; if(vwrq->disabled) - rthr = 2312; - if((rthr < 0) || (rthr > 2312)) { + rthr = AIRO_DEF_MTU; + if((rthr < 0) || (rthr > AIRO_DEF_MTU)) { return -EINVAL; } readConfigRid(local, 1); @@ -5970,7 +6115,7 @@ static int airo_get_rts(struct net_device *dev, readConfigRid(local, 1); vwrq->value = local->config.rtsThres; - vwrq->disabled = (vwrq->value >= 2312); + vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); vwrq->fixed = 1; return 0; @@ -5989,8 +6134,8 @@ static int airo_set_frag(struct net_device *dev, int fthr = vwrq->value; if(vwrq->disabled) - fthr = 2312; - if((fthr < 256) || (fthr > 2312)) { + fthr = AIRO_DEF_MTU; + if((fthr < 256) || (fthr > AIRO_DEF_MTU)) { return -EINVAL; } fthr &= ~0x1; /* Get an even value - is it really needed ??? */ @@ -6014,7 +6159,7 @@ static int airo_get_frag(struct net_device *dev, readConfigRid(local, 1); vwrq->value = local->config.fragThresh; - vwrq->disabled = (vwrq->value >= 2312); + vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); vwrq->fixed = 1; return 0; @@ -6709,9 +6854,9 @@ static int airo_get_range(struct net_device *dev, range->throughput = 1500 * 1000; range->min_rts = 0; - range->max_rts = 2312; + range->max_rts = AIRO_DEF_MTU; range->min_frag = 256; - range->max_frag = 2312; + range->max_frag = AIRO_DEF_MTU; if(cap_rid.softCap & 2) { // WEP: RC4 40 bits @@ -6972,6 +7117,7 @@ static int airo_set_scan(struct net_device *dev, struct airo_info *ai = dev->priv; Cmd cmd; Resp rsp; + int wake = 0; /* Note : you may have realised that, as this is a SET operation, * this is privileged and therefore a normal user can't @@ -6981,17 +7127,25 @@ static int airo_set_scan(struct net_device *dev, * Jean II */ if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; + if (down_interruptible(&ai->sem)) + return -ERESTARTSYS; + + /* If there's already a scan in progress, don't + * trigger another one. */ + if (ai->scan_timeout > 0) + goto out; + /* Initiate a scan command */ memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_LISTBSS; - if (down_interruptible(&ai->sem)) - return -ERESTARTSYS; issuecommand(ai, &cmd, &rsp); - ai->scan_timestamp = jiffies; - up(&ai->sem); - - /* At this point, just return to the user. */ + ai->scan_timeout = RUN_AT(3*HZ); + wake = 1; +out: + up(&ai->sem); + if (wake) + wake_up_interruptible(&ai->thr_wait); return 0; } @@ -7111,59 +7265,38 @@ static int airo_get_scan(struct net_device *dev, char *extra) { struct airo_info *ai = dev->priv; - BSSListRid BSSList; - int rc; + BSSListElement *net; + int err = 0; char *current_ev = extra; - /* When we are associated again, the scan has surely finished. - * Just in case, let's make sure enough time has elapsed since - * we started the scan. - Javier */ - if(ai->scan_timestamp && time_before(jiffies,ai->scan_timestamp+3*HZ)) { - /* Important note : we don't want to block the caller - * until results are ready for various reasons. - * First, managing wait queues is complex and racy - * (there may be multiple simultaneous callers). - * Second, we grab some rtnetlink lock before comming - * here (in dev_ioctl()). - * Third, the caller can wait on the Wireless Event - * - Jean II */ + /* If a scan is in-progress, return -EAGAIN */ + if (ai->scan_timeout > 0) return -EAGAIN; - } - ai->scan_timestamp = 0; - /* There's only a race with proc_BSSList_open(), but its - * consequences are begnign. So I don't bother fixing it - Javier */ - - /* Try to read the first entry of the scan result */ - rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 1); - if((rc) || (BSSList.index == 0xffff)) { - /* Client error, no scan results... - * The caller need to restart the scan. */ - return -ENODATA; - } + if (down_interruptible(&ai->sem)) + return -EAGAIN; - /* Read and parse all entries */ - while((!rc) && (BSSList.index != 0xffff)) { + list_for_each_entry (net, &ai->network_list, list) { /* Translate to WE format this entry */ current_ev = airo_translate_scan(dev, current_ev, extra + dwrq->length, - &BSSList); + &net->bss); /* Check if there is space for one more entry */ if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { /* Ask user space to try again with a bigger buffer */ - return -E2BIG; + err = -E2BIG; + goto out; } - - /* Read next entry */ - rc = PC4500_readrid(ai, RID_BSSLISTNEXT, - &BSSList, sizeof(BSSList), 1); } + /* Length of data */ dwrq->length = (current_ev - extra); dwrq->flags = 0; /* todo */ - return 0; +out: + up(&ai->sem); + return err; } /*------------------------------------------------------------------*/ @@ -7711,7 +7844,7 @@ static int cmdreset(struct airo_info *ai) { disable_MAC(ai, 1); if(!waitbusy (ai)){ - printk(KERN_INFO "Waitbusy hang before RESET\n"); + airo_print_info(ai->dev->name, "Waitbusy hang before RESET"); return -EBUSY; } @@ -7720,7 +7853,7 @@ static int cmdreset(struct airo_info *ai) { ssleep(1); /* WAS 600 12/7/00 */ if(!waitbusy (ai)){ - printk(KERN_INFO "Waitbusy hang AFTER RESET\n"); + airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET"); return -EBUSY; } return 0; @@ -7748,7 +7881,7 @@ static int setflashmode (struct airo_info *ai) { if(!waitbusy(ai)) { clear_bit (FLAG_FLASHING, &ai->flags); - printk(KERN_INFO "Waitbusy hang after setflash mode\n"); + airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode"); return -EIO; } return 0; @@ -7777,7 +7910,7 @@ static int flashpchar(struct airo_info *ai,int byte,int dwelltime) { /* timeout for busy clear wait */ if(waittime <= 0 ){ - printk(KERN_INFO "flash putchar busywait timeout! \n"); + airo_print_info(ai->dev->name, "flash putchar busywait timeout!"); return -EBUSY; } @@ -7866,7 +7999,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev){ if (!test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) { ai->fids[i] = transmit_allocate - ( ai, 2312, i >= MAX_FIDS / 2 ); + ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 ); } ssleep(1); /* Added 12/7/00 */ diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 753a1de6664b..06c3fa32b310 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -3141,7 +3141,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr) if (ret == 1) { sta = ap_add_sta(ap, sta_addr); if (!sta) - ret = -1; + return -1; sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; sta->ap = 1; memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index f8f4503475f9..d335b250923a 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -585,8 +585,6 @@ static int prism2_config(dev_link_t *link) parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL); if (parse == NULL || hw_priv == NULL) { - kfree(parse); - kfree(hw_priv); ret = -ENOMEM; goto failed; } diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index b1f142d9e232..328e9a1d13b5 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -928,15 +928,15 @@ static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len) res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL); up(&local->rid_bap_sem); + if (res) { printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE " "failed (res=%d, rid=%04x, len=%d)\n", dev->name, res, rid, len); - return res; - } - if (res == -ETIMEDOUT) - prism2_hw_reset(dev); + if (res == -ETIMEDOUT) + prism2_hw_reset(dev); + } return res; } diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index f3e0ce1ee037..8b37e824dfcb 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -3358,10 +3358,6 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { if (!sta_ptr) local->tx_keyidx = i; - else if (i) { - ret = -EINVAL; - goto done; - } } diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 2e85bdced2dd..194f07097581 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -307,7 +307,7 @@ static int prism2_pci_probe(struct pci_dev *pdev, memset(hw_priv, 0, sizeof(*hw_priv)); if (pci_enable_device(pdev)) - return -EIO; + goto err_out_free; phymem = pci_resource_start(pdev, 0); @@ -368,6 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev, err_out_disable: pci_disable_device(pdev); prism2_free_local_data(dev); + + err_out_free: kfree(hw_priv); return -ENODEV; diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 94fe2449f099..edaaa943eb8f 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -368,7 +368,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, switch (cis[pos]) { case CISTPL_CONFIG: - if (cis[pos + 1] < 1) + if (cis[pos + 1] < 2) goto cis_error; rmsz = (cis[pos + 2] & 0x3c) >> 2; rasz = cis[pos + 2] & 0x03; @@ -390,7 +390,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, break; case CISTPL_MANFID: - if (cis[pos + 1] < 4) + if (cis[pos + 1] < 5) goto cis_error; manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); @@ -452,7 +452,7 @@ static int prism2_plx_probe(struct pci_dev *pdev, memset(hw_priv, 0, sizeof(*hw_priv)); if (pci_enable_device(pdev)) - return -EIO; + goto err_out_free; /* National Datacomm NCP130 based on TMD7160, not PLX9052. */ tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131); @@ -567,9 +567,6 @@ static int prism2_plx_probe(struct pci_dev *pdev, return hostap_hw_ready(dev); fail: - prism2_free_local_data(dev); - kfree(hw_priv); - if (irq_registered && dev) free_irq(dev->irq, dev); @@ -577,6 +574,10 @@ static int prism2_plx_probe(struct pci_dev *pdev, iounmap(attr_mem); pci_disable_device(pdev); + prism2_free_local_data(dev); + + err_out_free: + kfree(hw_priv); return -ENODEV; } diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index f187fd8aeed6..4d762fc4878c 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -11,24 +11,11 @@ config PCI_MSI generate an interrupt using an inbound Memory Write on its PCI bus instead of asserting a device IRQ pin. - If you don't know what to do here, say N. - -config PCI_LEGACY_PROC - bool "Legacy /proc/pci interface" - depends on PCI - ---help--- - This feature enables a procfs file -- /proc/pci -- that provides a - summary of PCI devices in the system. - - This feature has been deprecated as of v2.5.53, in favor of using the - tool lspci(8). This feature may be removed at a future date. + Use of PCI MSI interrupts can be disabled at kernel boot time + by using the 'pci=nomsi' option. This disables MSI for the + entire system. - lspci can provide the same data, as well as much more. lspci is a part of - the pci-utils package, which should be installed by your distribution. - See <file:Documentation/Changes> for information on where to get the latest - version. - - When in doubt, say N. + If you don't know what to do here, say N. config PCI_DEBUG bool "PCI Debugging" diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 3c71e3077ff1..421cfffb1756 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI pci_hotplug-objs += cpci_hotplug_core.o \ cpci_hotplug_pci.o endif +ifdef CONFIG_ACPI +pci_hotplug-objs += acpi_pcihp.o +endif cpqphp-objs := cpqphp_core.o \ cpqphp_ctrl.o \ @@ -37,7 +40,8 @@ ibmphp-objs := ibmphp_core.o \ ibmphp_hpc.o acpiphp-objs := acpiphp_core.o \ - acpiphp_glue.o + acpiphp_glue.o \ + acpiphp_dock.o rpaphp-objs := rpaphp_core.o \ rpaphp_pci.o \ @@ -50,23 +54,9 @@ pciehp-objs := pciehp_core.o \ pciehp_ctrl.o \ pciehp_pci.o \ pciehp_hpc.o -ifdef CONFIG_ACPI - pciehp-objs += pciehprm_acpi.o -else - pciehp-objs += pciehprm_nonacpi.o -endif shpchp-objs := shpchp_core.o \ shpchp_ctrl.o \ shpchp_pci.o \ shpchp_sysfs.o \ shpchp_hpc.o -ifdef CONFIG_ACPI - shpchp-objs += shpchprm_acpi.o -else - ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY - shpchp-objs += shpchprm_legacy.o - else - shpchp-objs += shpchprm_nonacpi.o - endif -endif diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/acpi_pcihp.c index 17145e52223a..39af9c325f35 100644 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -1,7 +1,7 @@ /* - * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform + * Common ACPI functions for hot plug platforms * - * Copyright (C) 2003-2004 Intel Corporation + * Copyright (C) 2006 Intel Corporation * * All rights reserved. * @@ -31,26 +31,12 @@ #include <acpi/acpi.h> #include <acpi/acpi_bus.h> #include <acpi/actypes.h> -#include "shpchp.h" +#include "pci_hotplug.h" #define METHOD_NAME__SUN "_SUN" #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" -static u8 * acpi_path_name( acpi_handle handle) -{ - acpi_status status; - static u8 path_name[ACPI_PATHNAME_MAX]; - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; - - memset(path_name, 0, sizeof (path_name)); - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); - - if (ACPI_FAILURE(status)) - return NULL; - else - return path_name; -} static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) @@ -58,18 +44,21 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) acpi_status status; u8 nui[4]; struct acpi_buffer ret_buf = { 0, NULL}; + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *ext_obj, *package; - u8 *path_name = acpi_path_name(handle); int i, len = 0; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + /* get _hpp */ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); switch (status) { case AE_BUFFER_OVERFLOW: ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); if (!ret_buf.pointer) { - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, - path_name); + printk(KERN_ERR "%s:%s alloc for _HPP fail\n", + __FUNCTION__, (char *)string.pointer); + acpi_os_free(string.pointer); return AE_NO_MEMORY; } status = acpi_evaluate_object(handle, METHOD_NAME__HPP, @@ -78,16 +67,17 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) break; default: if (ACPI_FAILURE(status)) { - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, - path_name, status); + pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__, + (char *)string.pointer, status); + acpi_os_free(string.pointer); return status; } } ext_obj = (union acpi_object *) ret_buf.pointer; if (ext_obj->type != ACPI_TYPE_PACKAGE) { - err ("%s:%s _HPP obj not a package\n", __FUNCTION__, - path_name); + printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__, + (char *)string.pointer); status = AE_ERROR; goto free_and_return; } @@ -101,8 +91,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) nui[i] = (u8)ext_obj->integer.value; break; default: - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, - path_name); + printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", + __FUNCTION__, (char *)string.pointer); status = AE_ERROR; goto free_and_return; } @@ -113,54 +103,52 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) hpp->enable_serr = nui[2]; hpp->enable_perr = nui[3]; - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); + pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); + pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer); + pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); + pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); free_and_return: - kfree(ret_buf.pointer); + acpi_os_free(string.pointer); + acpi_os_free(ret_buf.pointer); return status; } -static void acpi_run_oshp(acpi_handle handle) + + +/* acpi_run_oshp - get control of hotplug from the firmware + * + * @handle - the handle of the hotplug controller. + */ +acpi_status acpi_run_oshp(acpi_handle handle) { acpi_status status; - u8 *path_name = acpi_path_name(handle); + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); /* run OSHP */ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); - if (ACPI_FAILURE(status)) { - err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, - status); - } else { - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); - } -} - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; + if (ACPI_FAILURE(status)) + printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__, + (char *)string.pointer, status); + else + pr_debug("%s:%s OSHP passes\n", __FUNCTION__, + (char *)string.pointer); - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); - return 0; + acpi_os_free(string.pointer); + return status; } +EXPORT_SYMBOL_GPL(acpi_run_oshp); + -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - /* - * OSHP is an optional ACPI firmware control method. If present, - * we need to run it to inform BIOS that we will control SHPC - * hardware from now on. - */ - acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev)); - if (!handle) - return; - acpi_run_oshp(handle); -} -void get_hp_params_from_firmware(struct pci_dev *dev, +/* acpi_get_hp_params_from_firmware + * + * @dev - the pci_dev of the newly added device + * @hpp - allocated by the caller + */ +acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { acpi_status status = AE_NOT_FOUND; @@ -182,5 +170,42 @@ void get_hp_params_from_firmware(struct pci_dev *dev, /* Check if a parent object supports _HPP */ pdev = pdev->bus->parent->self; } + return status; } +EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); + +/* acpi_root_bridge - check to see if this acpi object is a root bridge + * + * @handle - the acpi object in question. + */ +int acpi_root_bridge(acpi_handle handle) +{ + acpi_status status; + struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + int i; + + status = acpi_get_object_info(handle, &buffer); + if (ACPI_SUCCESS(status)) { + info = buffer.pointer; + if ((info->valid & ACPI_VALID_HID) && + !strcmp(PCI_ROOT_HID_STRING, + info->hardware_id.value)) { + acpi_os_free(buffer.pointer); + return 1; + } + if (info->valid & ACPI_VALID_CID) { + for (i=0; i < info->compatibility_id.count; i++) { + if (!strcmp(PCI_ROOT_HID_STRING, + info->compatibility_id.id[i].value)) { + acpi_os_free(buffer.pointer); + return 1; + } + } + } + acpi_os_free(buffer.pointer); + } + return 0; +} +EXPORT_SYMBOL_GPL(acpi_root_bridge); diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 293603e1b7c3..467ac70a46ff 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -37,6 +37,7 @@ #include <linux/acpi.h> #include <linux/kobject.h> /* for KOBJ_NAME_LEN */ +#include <linux/mutex.h> #include "pci_hotplug.h" #define dbg(format, arg...) \ @@ -59,26 +60,10 @@ struct acpiphp_slot; * struct slot - slot information for each *physical* slot */ struct slot { - u8 number; struct hotplug_slot *hotplug_slot; - struct list_head slot_list; - struct acpiphp_slot *acpi_slot; }; -/** - * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters - * @cache_line_size in DWORD - * @latency_timer in PCI clock - * @enable_SERR 0 or 1 - * @enable_PERR 0 or 1 - */ -struct hpp_param { - u8 cache_line_size; - u8 latency_timer; - u8 enable_SERR; - u8 enable_PERR; -}; /** @@ -102,7 +87,7 @@ struct acpiphp_bridge { struct pci_dev *pci_dev; /* ACPI 2.0 _HPP parameters */ - struct hpp_param hpp; + struct hotplug_params hpp; spinlock_t res_lock; }; @@ -118,9 +103,9 @@ struct acpiphp_slot { struct acpiphp_bridge *bridge; /* parent */ struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ - struct semaphore crit_sect; + struct slot *slot; + struct mutex crit_sect; - u32 id; /* slot id (serial #) for hotplug core */ u8 device; /* pci device# */ u32 sun; /* ACPI _SUN (slot unique number) */ @@ -160,6 +145,25 @@ struct acpiphp_attention_info struct module *owner; }; + +struct dependent_device { + struct list_head device_list; + struct list_head pci_list; + acpi_handle handle; + struct acpiphp_func *func; +}; + + +struct acpiphp_dock_station { + acpi_handle handle; + u32 last_dock_time; + u32 flags; + struct acpiphp_func *dock_bridge; + struct list_head dependent_devices; + struct list_head pci_dependent_devices; +}; + + /* PCI bus bridge HID */ #define ACPI_PCI_HOST_HID "PNP0A03" @@ -197,19 +201,27 @@ struct acpiphp_attention_info #define FUNC_HAS_PS1 (0x00000020) #define FUNC_HAS_PS2 (0x00000040) #define FUNC_HAS_PS3 (0x00000080) +#define FUNC_HAS_DCK (0x00000100) +#define FUNC_IS_DD (0x00000200) + +/* dock station flags */ +#define DOCK_DOCKING (0x00000001) +#define DOCK_HAS_BRIDGE (0x00000002) /* function prototypes */ /* acpiphp_core.c */ extern int acpiphp_register_attention(struct acpiphp_attention_info*info); extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); +extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); +extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); /* acpiphp_glue.c */ extern int acpiphp_glue_init (void); extern void acpiphp_glue_exit (void); extern int acpiphp_get_num_slots (void); -extern struct acpiphp_slot *get_slot_from_id (int id); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); +void handle_hotplug_event_func(acpi_handle, u32, void*); extern int acpiphp_enable_slot (struct acpiphp_slot *slot); extern int acpiphp_disable_slot (struct acpiphp_slot *slot); @@ -219,6 +231,16 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); extern u32 acpiphp_get_address (struct acpiphp_slot *slot); +/* acpiphp_dock.c */ +extern int find_dock_station(void); +extern void remove_dock_station(void); +extern void add_dependent_device(struct dependent_device *new_dd); +extern void add_pci_dependent_device(struct dependent_device *new_dd); +extern struct dependent_device *get_dependent_device(acpi_handle handle); +extern int is_dependent_device(acpi_handle handle); +extern int detect_dependent_devices(acpi_handle *bridge_handle); +extern struct dependent_device *alloc_dependent_device(acpi_handle handle); + /* variables */ extern int acpiphp_debug; diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 60c4c38047a3..4f1b0da8e47e 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -44,8 +44,6 @@ #include "pci_hotplug.h" #include "acpiphp.h" -static LIST_HEAD(slot_list); - #define MY_NAME "acpiphp" static int debug; @@ -341,62 +339,53 @@ static void release_slot(struct hotplug_slot *hotplug_slot) kfree(slot); } -/** - * init_slots - initialize 'struct slot' structures for each slot - * - */ -static int __init init_slots(void) +/* callback routine to initialize 'struct slot' for each slot */ +int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) { struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *hotplug_slot_info; int retval = -ENOMEM; - int i; - - for (i = 0; i < num_slots; ++i) { - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); - if (!slot) - goto error; - memset(slot, 0, sizeof(struct slot)); - - slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); - if (!slot->hotplug_slot) - goto error_slot; - memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); - - slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); - if (!slot->hotplug_slot->info) - goto error_hpslot; - memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info)); - - slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!slot->hotplug_slot->name) - goto error_info; - - slot->number = i; - - slot->hotplug_slot->private = slot; - slot->hotplug_slot->release = &release_slot; - slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; - - slot->acpi_slot = get_slot_from_id(i); - slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); - slot->hotplug_slot->info->attention_status = 0; - slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); - slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); - slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; - slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; - - make_slot_name(slot); - - retval = pci_hp_register(slot->hotplug_slot); - if (retval) { - err("pci_hp_register failed with error %d\n", retval); - goto error_name; - } - - /* add slot to our internal list */ - list_add(&slot->slot_list, &slot_list); - info("Slot [%s] registered\n", slot->hotplug_slot->name); - } + + slot = kzalloc(sizeof(*slot), GFP_KERNEL); + if (!slot) + goto error; + + slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); + if (!slot->hotplug_slot) + goto error_slot; + + slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info), + GFP_KERNEL); + if (!slot->hotplug_slot->info) + goto error_hpslot; + + slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!slot->hotplug_slot->name) + goto error_info; + + slot->hotplug_slot->private = slot; + slot->hotplug_slot->release = &release_slot; + slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; + + slot->acpi_slot = acpiphp_slot; + slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); + slot->hotplug_slot->info->attention_status = 0; + slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); + slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); + slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; + slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; + + acpiphp_slot->slot = slot; + make_slot_name(slot); + + retval = pci_hp_register(slot->hotplug_slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); + goto error_name; + } + + info("Slot [%s] registered\n", slot->hotplug_slot->name); return 0; error_name: @@ -412,42 +401,51 @@ error: } -static void __exit cleanup_slots (void) +void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) { - struct list_head *tmp, *n; - struct slot *slot; + struct slot *slot = acpiphp_slot->slot; + int retval = 0; - list_for_each_safe (tmp, n, &slot_list) { - /* memory will be freed in release_slot callback */ - slot = list_entry(tmp, struct slot, slot_list); - list_del(&slot->slot_list); - pci_hp_deregister(slot->hotplug_slot); - } + info ("Slot [%s] unregistered\n", slot->hotplug_slot->name); + + retval = pci_hp_deregister(slot->hotplug_slot); + if (retval) + err("pci_hp_deregister failed with error %d\n", retval); } static int __init acpiphp_init(void) { int retval; + int docking_station; info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); acpiphp_debug = debug; + docking_station = find_dock_station(); + /* read all the ACPI info from the system */ retval = init_acpi(); - if (retval) - return retval; - return init_slots(); + /* if we have found a docking station, we should + * go ahead and load even if init_acpi has found + * no slots. This handles the case when the _DCK + * method not defined under the actual dock bridge + */ + if (docking_station) + return 0; + else + return retval; } static void __exit acpiphp_exit(void) { - cleanup_slots(); /* deallocate internal data structures etc. */ acpiphp_glue_exit(); + + remove_dock_station(); } module_init(acpiphp_init); diff --git a/drivers/pci/hotplug/acpiphp_dock.c b/drivers/pci/hotplug/acpiphp_dock.c new file mode 100644 index 000000000000..4f1aaf128312 --- /dev/null +++ b/drivers/pci/hotplug/acpiphp_dock.c @@ -0,0 +1,438 @@ +/* + * ACPI PCI HotPlug dock functions to ACPI CA subsystem + * + * Copyright (C) 2006 Kristen Carlson Accardi (kristen.c.accardi@intel.com) + * Copyright (C) 2006 Intel Corporation + * + * All rights reserved. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to <kristen.c.accardi@intel.com> + * + */ +#include <linux/init.h> +#include <linux/module.h> + +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/smp_lock.h> +#include <linux/mutex.h> + +#include "../pci.h" +#include "pci_hotplug.h" +#include "acpiphp.h" + +static struct acpiphp_dock_station *ds; +#define MY_NAME "acpiphp_dock" + + +int is_dependent_device(acpi_handle handle) +{ + return (get_dependent_device(handle) ? 1 : 0); +} + + +static acpi_status +find_dependent_device(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + + if (is_dependent_device(handle)) { + (*count)++; + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } +} + + + + +void add_dependent_device(struct dependent_device *new_dd) +{ + list_add_tail(&new_dd->device_list, &ds->dependent_devices); +} + + +void add_pci_dependent_device(struct dependent_device *new_dd) +{ + list_add_tail(&new_dd->pci_list, &ds->pci_dependent_devices); +} + + + +struct dependent_device * get_dependent_device(acpi_handle handle) +{ + struct dependent_device *dd; + + if (!ds) + return NULL; + + list_for_each_entry(dd, &ds->dependent_devices, device_list) { + if (handle == dd->handle) + return dd; + } + return NULL; +} + + + +struct dependent_device *alloc_dependent_device(acpi_handle handle) +{ + struct dependent_device *dd; + + dd = kzalloc(sizeof(*dd), GFP_KERNEL); + if (dd) { + INIT_LIST_HEAD(&dd->pci_list); + INIT_LIST_HEAD(&dd->device_list); + dd->handle = handle; + } + return dd; +} + + + +static int is_dock(acpi_handle handle) +{ + acpi_status status; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_DCK", &tmp); + if (ACPI_FAILURE(status)) { + return 0; + } + return 1; +} + + + +static int dock_present(void) +{ + unsigned long sta; + acpi_status status; + + if (ds) { + status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta); + if (ACPI_SUCCESS(status) && sta) + return 1; + } + return 0; +} + + + +static void eject_dock(void) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", + &arg_list, NULL)) || dock_present()) + warn("%s: failed to eject dock!\n", __FUNCTION__); + + return; +} + + + + +static acpi_status handle_dock(int dock) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + + dbg("%s: %s\n", __FUNCTION__, dock ? "docking" : "undocking"); + + /* _DCK method has one argument */ + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = dock; + status = acpi_evaluate_object(ds->handle, "_DCK", + &arg_list, &buffer); + if (ACPI_FAILURE(status)) + err("%s: failed to execute _DCK\n", __FUNCTION__); + acpi_os_free(buffer.pointer); + + return status; +} + + + +static inline void dock(void) +{ + handle_dock(1); +} + + + +static inline void undock(void) +{ + handle_dock(0); +} + + + +/* + * the _DCK method can do funny things... and sometimes not + * hah-hah funny. + * + * TBD - figure out a way to only call fixups for + * systems that require them. + */ +static void post_dock_fixups(void) +{ + struct pci_bus *bus; + u32 buses; + struct dependent_device *dd; + + list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) { + bus = dd->func->slot->bridge->pci_bus; + + /* fixup bad _DCK function that rewrites + * secondary bridge on slot + */ + pci_read_config_dword(bus->self, + PCI_PRIMARY_BUS, + &buses); + + if (((buses >> 8) & 0xff) != bus->secondary) { + buses = (buses & 0xff000000) + | ((unsigned int)(bus->primary) << 0) + | ((unsigned int)(bus->secondary) << 8) + | ((unsigned int)(bus->subordinate) << 16); + pci_write_config_dword(bus->self, + PCI_PRIMARY_BUS, + buses); + } + } +} + + + +static void hotplug_pci(u32 type) +{ + struct dependent_device *dd; + + list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) + handle_hotplug_event_func(dd->handle, type, dd->func); +} + + + +static inline void begin_dock(void) +{ + ds->flags |= DOCK_DOCKING; +} + + +static inline void complete_dock(void) +{ + ds->flags &= ~(DOCK_DOCKING); + ds->last_dock_time = jiffies; +} + + +static int dock_in_progress(void) +{ + if (ds->flags & DOCK_DOCKING || + ds->last_dock_time == jiffies) { + dbg("dock in progress\n"); + return 1; + } + return 0; +} + + + +static void +handle_hotplug_event_dock(acpi_handle handle, u32 type, void *context) +{ + dbg("%s: enter\n", __FUNCTION__); + + switch (type) { + case ACPI_NOTIFY_BUS_CHECK: + dbg("BUS Check\n"); + if (!dock_in_progress() && dock_present()) { + begin_dock(); + dock(); + if (!dock_present()) { + err("Unable to dock!\n"); + break; + } + post_dock_fixups(); + hotplug_pci(type); + complete_dock(); + } + break; + case ACPI_NOTIFY_EJECT_REQUEST: + dbg("EJECT request\n"); + if (!dock_in_progress() && dock_present()) { + hotplug_pci(type); + undock(); + eject_dock(); + if (dock_present()) + err("Unable to undock!\n"); + } + break; + } +} + + + + +static acpi_status +find_dock_ejd(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + acpi_handle tmp; + acpi_handle dck_handle = (acpi_handle) context; + char objname[64]; + struct acpi_buffer buffer = { .length = sizeof(objname), + .pointer = objname }; + struct acpi_buffer ejd_buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *ejd_obj; + + status = acpi_get_handle(handle, "_EJD", &tmp); + if (ACPI_FAILURE(status)) + return AE_OK; + + /* make sure we are dependent on the dock device, + * by executing the _EJD method, then getting a handle + * to the device referenced by that name. If that + * device handle is the same handle as the dock station + * handle, then we are a device dependent on the dock station + */ + acpi_get_name(dck_handle, ACPI_FULL_PATHNAME, &buffer); + status = acpi_evaluate_object(handle, "_EJD", NULL, &ejd_buffer); + if (ACPI_FAILURE(status)) { + err("Unable to execute _EJD!\n"); + goto find_ejd_out; + } + ejd_obj = ejd_buffer.pointer; + status = acpi_get_handle(NULL, ejd_obj->string.pointer, &tmp); + if (ACPI_FAILURE(status)) + goto find_ejd_out; + + if (tmp == dck_handle) { + struct dependent_device *dd; + dbg("%s: found device dependent on dock\n", __FUNCTION__); + dd = alloc_dependent_device(handle); + if (!dd) { + err("Can't allocate memory for dependent device!\n"); + goto find_ejd_out; + } + add_dependent_device(dd); + } + +find_ejd_out: + acpi_os_free(ejd_buffer.pointer); + return AE_OK; +} + + + +int detect_dependent_devices(acpi_handle *bridge_handle) +{ + acpi_status status; + int count; + + count = 0; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, + (u32)1, find_dependent_device, + (void *)&count, NULL); + + return count; +} + + + + + +static acpi_status +find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + + if (is_dock(handle)) { + dbg("%s: found dock\n", __FUNCTION__); + ds = kzalloc(sizeof(*ds), GFP_KERNEL); + ds->handle = handle; + INIT_LIST_HEAD(&ds->dependent_devices); + INIT_LIST_HEAD(&ds->pci_dependent_devices); + + /* look for devices dependent on dock station */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_dock_ejd, handle, NULL); + + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_dock, ds); + (*count)++; + } + + return AE_OK; +} + + + + +int find_dock_station(void) +{ + int num = 0; + + ds = NULL; + + /* start from the root object, because some laptops define + * _DCK methods outside the scope of PCI (IBM x-series laptop) + */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_dock, &num, NULL); + + return num; +} + + + +void remove_dock_station(void) +{ + struct dependent_device *dd, *tmp; + if (ds) { + if (ACPI_FAILURE(acpi_remove_notify_handler(ds->handle, + ACPI_SYSTEM_NOTIFY, handle_hotplug_event_dock))) + err("failed to remove dock notify handler\n"); + + /* free all dependent devices */ + list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, + device_list) + kfree(dd); + + /* no need to touch the pci_dependent_device list, + * cause all memory was freed above + */ + kfree(ds); + } +} + + diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 509a5b3ae998..053ee843863c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -46,7 +46,7 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/smp_lock.h> -#include <asm/semaphore.h> +#include <linux/mutex.h> #include "../pci.h" #include "pci_hotplug.h" @@ -57,7 +57,6 @@ static LIST_HEAD(bridge_list); #define MY_NAME "acpiphp_glue" static void handle_hotplug_event_bridge (acpi_handle, u32, void *); -static void handle_hotplug_event_func (acpi_handle, u32, void *); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); @@ -125,11 +124,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; struct acpiphp_slot *slot; struct acpiphp_func *newfunc; + struct dependent_device *dd; acpi_handle tmp; acpi_status status = AE_OK; unsigned long adr, sun; - int device, function; - static int num_slots = 0; /* XXX if we support I/O node hotplug... */ + int device, function, retval; status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); @@ -138,21 +137,21 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status) && !(is_dependent_device(handle))) return AE_OK; device = (adr >> 16) & 0xffff; function = adr & 0xffff; - newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL); + newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); if (!newfunc) return AE_NO_MEMORY; - memset(newfunc, 0, sizeof(struct acpiphp_func)); INIT_LIST_HEAD(&newfunc->sibling); newfunc->handle = handle; newfunc->function = function; - newfunc->flags = FUNC_HAS_EJ0; + if (ACPI_SUCCESS(status)) + newfunc->flags = FUNC_HAS_EJ0; if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) newfunc->flags |= FUNC_HAS_STA; @@ -163,6 +162,19 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) newfunc->flags |= FUNC_HAS_PS3; + if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) { + newfunc->flags |= FUNC_HAS_DCK; + /* add to devices dependent on dock station, + * because this may actually be the dock bridge + */ + dd = alloc_dependent_device(handle); + if (!dd) + err("Can't allocate memory for " + "new dependent device!\n"); + else + add_dependent_device(dd); + } + status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); if (ACPI_FAILURE(status)) sun = -1; @@ -176,19 +188,17 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } if (!slot) { - slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); if (!slot) { kfree(newfunc); return AE_NO_MEMORY; } - memset(slot, 0, sizeof(struct acpiphp_slot)); slot->bridge = bridge; - slot->id = num_slots++; slot->device = device; slot->sun = sun; INIT_LIST_HEAD(&slot->funcs); - init_MUTEX(&slot->crit_sect); + mutex_init(&slot->crit_sect); slot->next = bridge->slots; bridge->slots = slot; @@ -198,6 +208,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", slot->sun, pci_domain_nr(bridge->pci_bus), bridge->pci_bus->number, slot->device); + retval = acpiphp_register_hotplug_slot(slot); + if (retval) { + warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval); + goto err_exit; + } } newfunc->slot = slot; @@ -210,16 +225,41 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); } + /* if this is a device dependent on a dock station, + * associate the acpiphp_func to the dependent_device + * struct. + */ + if ((dd = get_dependent_device(handle))) { + newfunc->flags |= FUNC_IS_DD; + /* + * we don't want any devices which is dependent + * on the dock to have it's _EJ0 method executed. + * because we need to run _DCK first. + */ + newfunc->flags &= ~FUNC_HAS_EJ0; + dd->func = newfunc; + add_pci_dependent_device(dd); + } + /* install notify handler */ - status = acpi_install_notify_handler(handle, + if (!(newfunc->flags & FUNC_HAS_DCK)) { + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func, newfunc); - if (ACPI_FAILURE(status)) { - err("failed to register interrupt notify handler\n"); - return status; - } + if (ACPI_FAILURE(status)) + err("failed to register interrupt notify handler\n"); + } else + status = AE_OK; + + return status; + + err_exit: + bridge->nr_slots--; + bridge->slots = slot->next; + kfree(slot); + kfree(newfunc); return AE_OK; } @@ -245,57 +285,19 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle) static void decode_hpp(struct acpiphp_bridge *bridge) { acpi_status status; - struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER, - .pointer = NULL}; - union acpi_object *package; - int i; - - /* default numbers */ - bridge->hpp.cache_line_size = 0x10; - bridge->hpp.latency_timer = 0x40; - bridge->hpp.enable_SERR = 0; - bridge->hpp.enable_PERR = 0; - - status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer); + status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); if (ACPI_FAILURE(status)) { - dbg("_HPP evaluation failed\n"); - return; + /* use default numbers */ + bridge->hpp.cache_line_size = 0x10; + bridge->hpp.latency_timer = 0x40; + bridge->hpp.enable_serr = 0; + bridge->hpp.enable_perr = 0; } - - package = (union acpi_object *) buffer.pointer; - - if (!package || package->type != ACPI_TYPE_PACKAGE || - package->package.count != 4 || !package->package.elements) { - err("invalid _HPP object; ignoring\n"); - goto err_exit; - } - - for (i = 0; i < 4; i++) { - if (package->package.elements[i].type != ACPI_TYPE_INTEGER) { - err("invalid _HPP parameter type; ignoring\n"); - goto err_exit; - } - } - - bridge->hpp.cache_line_size = package->package.elements[0].integer.value; - bridge->hpp.latency_timer = package->package.elements[1].integer.value; - bridge->hpp.enable_SERR = package->package.elements[2].integer.value; - bridge->hpp.enable_PERR = package->package.elements[3].integer.value; - - dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n", - bridge->hpp.cache_line_size, - bridge->hpp.latency_timer, - bridge->hpp.enable_SERR, - bridge->hpp.enable_PERR); - - bridge->flags |= BRIDGE_HAS_HPP; - - err_exit: - kfree(buffer.pointer); } + /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ static void init_bridge_misc(struct acpiphp_bridge *bridge) { @@ -304,9 +306,16 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) /* decode ACPI 2.0 _HPP (hot plug parameters) */ decode_hpp(bridge); + /* must be added to the list prior to calling register_slot */ + list_add(&bridge->list, &bridge_list); + /* register all slot objects under this bridge */ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, register_slot, bridge, NULL); + if (ACPI_FAILURE(status)) { + list_del(&bridge->list); + return; + } /* install notify handler */ if (bridge->type != BRIDGE_TYPE_HOST) { @@ -319,8 +328,6 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) err("failed to register interrupt notify handler\n"); } } - - list_add(&bridge->list, &bridge_list); } @@ -329,12 +336,10 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) { struct acpiphp_bridge *bridge; - bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (bridge == NULL) return; - memset(bridge, 0, sizeof(struct acpiphp_bridge)); - bridge->type = BRIDGE_TYPE_HOST; bridge->handle = handle; @@ -351,14 +356,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) { struct acpiphp_bridge *bridge; - bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (bridge == NULL) { err("out of memory\n"); return; } - memset(bridge, 0, sizeof(struct acpiphp_bridge)); - bridge->type = BRIDGE_TYPE_P2P; bridge->handle = handle; @@ -410,11 +413,18 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) goto out; /* check if this bridge has ejectable slots */ - if (detect_ejectable_slots(handle) > 0) { + if ((detect_ejectable_slots(handle) > 0) || + (detect_dependent_devices(handle) > 0)) { dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); add_p2p_bridge(handle, dev); } + /* search P2P bridges under this p2p bridge */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + find_p2p_bridge, dev->subordinate, NULL); + if (ACPI_FAILURE(status)) + warn("find_p2p_bridge faied (error code = 0x%x)\n", status); + out: pci_dev_put(dev); return AE_OK; @@ -512,15 +522,19 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) list_for_each_safe (list, tmp, &slot->funcs) { struct acpiphp_func *func; func = list_entry(list, struct acpiphp_func, sibling); - status = acpi_remove_notify_handler(func->handle, + if (!(func->flags & FUNC_HAS_DCK)) { + status = acpi_remove_notify_handler(func->handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func); - if (ACPI_FAILURE(status)) - err("failed to remove notify handler\n"); + if (ACPI_FAILURE(status)) + err("failed to remove notify handler\n"); + } pci_dev_put(func->pci_dev); list_del(list); kfree(func); } + acpiphp_unregister_hotplug_slot(slot); + list_del(&slot->funcs); kfree(slot); slot = next; } @@ -551,7 +565,8 @@ static void remove_bridge(acpi_handle handle) } else { /* clean-up p2p bridges under this host bridge */ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - (u32)1, cleanup_p2p_bridge, NULL, NULL); + ACPI_UINT32_MAX, cleanup_p2p_bridge, + NULL, NULL); } } @@ -751,6 +766,113 @@ static int power_off_slot(struct acpiphp_slot *slot) } + +/** + * acpiphp_max_busnr - return the highest reserved bus number under + * the given bus. + * @bus: bus to start search with + * + */ +static unsigned char acpiphp_max_busnr(struct pci_bus *bus) +{ + struct list_head *tmp; + unsigned char max, n; + + /* + * pci_bus_max_busnr will return the highest + * reserved busnr for all these children. + * that is equivalent to the bus->subordinate + * value. We don't want to use the parent's + * bus->subordinate value because it could have + * padding in it. + */ + max = bus->secondary; + + list_for_each(tmp, &bus->children) { + n = pci_bus_max_busnr(pci_bus_b(tmp)); + if (n > max) + max = n; + } + return max; +} + + + +/** + * get_func - get a pointer to acpiphp_func given a slot, device + * @slot: slot to search + * @dev: pci_dev struct to match. + * + * This function will increase the reference count of pci_dev, + * so callers should call pci_dev_put when complete. + * + */ +static struct acpiphp_func * +get_func(struct acpiphp_slot *slot, struct pci_dev *dev) +{ + struct acpiphp_func *func = NULL; + struct pci_bus *bus = slot->bridge->pci_bus; + struct pci_dev *pdev; + + list_for_each_entry(func, &slot->funcs, sibling) { + pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, + func->function)); + if (pdev) { + if (pdev == dev) + break; + pci_dev_put(pdev); + } + } + return func; +} + + +/** + * acpiphp_bus_add - add a new bus to acpi subsystem + * @func: acpiphp_func of the bridge + * + */ +static int acpiphp_bus_add(struct acpiphp_func *func) +{ + acpi_handle phandle; + struct acpi_device *device, *pdevice; + int ret_val; + + acpi_get_parent(func->handle, &phandle); + if (acpi_bus_get_device(phandle, &pdevice)) { + dbg("no parent device, assuming NULL\n"); + pdevice = NULL; + } + if (!acpi_bus_get_device(func->handle, &device)) { + dbg("bus exists... trim\n"); + /* this shouldn't be in here, so remove + * the bus then re-add it... + */ + ret_val = acpi_bus_trim(device, 1); + dbg("acpi_bus_trim return %x\n", ret_val); + } + + ret_val = acpi_bus_add(&device, pdevice, func->handle, + ACPI_BUS_TYPE_DEVICE); + if (ret_val) { + dbg("error adding bus, %x\n", + -ret_val); + goto acpiphp_bus_add_out; + } + /* + * try to start anyway. We could have failed to add + * simply because this bus had previously been added + * on another add. Don't bother with the return value + * we just keep going. + */ + ret_val = acpi_bus_start(device); + +acpiphp_bus_add_out: + return ret_val; +} + + + /** * enable_device - enable, configure a slot * @slot: slot to be enabled @@ -788,7 +910,7 @@ static int enable_device(struct acpiphp_slot *slot) goto err_exit; } - max = bus->secondary; + max = acpiphp_max_busnr(bus); for (pass = 0; pass < 2; pass++) { list_for_each_entry(dev, &bus->devices, bus_list) { if (PCI_SLOT(dev->devfn) != slot->device) @@ -796,8 +918,15 @@ static int enable_device(struct acpiphp_slot *slot) if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { max = pci_scan_bridge(bus, dev, max, pass); - if (pass && dev->subordinate) + if (pass && dev->subordinate) { pci_bus_size_bridges(dev->subordinate); + func = get_func(slot, dev); + if (func) { + acpiphp_bus_add(func); + /* side effect of get_func */ + pci_dev_put(dev); + } + } } } } @@ -806,8 +935,8 @@ static int enable_device(struct acpiphp_slot *slot) acpiphp_sanitize_bus(bus); pci_enable_bridges(bus); pci_bus_add_devices(bus); - acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus); - acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev)); + acpiphp_set_hpp_values(slot->bridge->handle, bus); + acpiphp_configure_ioapics(slot->bridge->handle); /* associate pci_dev to our representation */ list_for_each (l, &slot->funcs) { @@ -987,11 +1116,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) pci_write_config_byte(dev, PCI_LATENCY_TIMER, bridge->hpp.latency_timer); pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - if (bridge->hpp.enable_SERR) + if (bridge->hpp.enable_serr) pci_cmd |= PCI_COMMAND_SERR; else pci_cmd &= ~PCI_COMMAND_SERR; - if (bridge->hpp.enable_PERR) + if (bridge->hpp.enable_perr) pci_cmd |= PCI_COMMAND_PARITY; else pci_cmd &= ~PCI_COMMAND_PARITY; @@ -1002,11 +1131,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, bridge->hpp.latency_timer); pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); - if (bridge->hpp.enable_SERR) + if (bridge->hpp.enable_serr) pci_bctl |= PCI_BRIDGE_CTL_SERR; else pci_bctl &= ~PCI_BRIDGE_CTL_SERR; - if (bridge->hpp.enable_PERR) + if (bridge->hpp.enable_perr) pci_bctl |= PCI_BRIDGE_CTL_PARITY; else pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; @@ -1026,6 +1155,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus) memset(&bridge, 0, sizeof(bridge)); bridge.handle = handle; + bridge.pci_dev = bus->self; decode_hpp(&bridge); list_for_each_entry(dev, &bus->devices, bus_list) program_hpp(dev, &bridge); @@ -1200,7 +1330,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont * handles ACPI event notification on slots * */ -static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) +void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) { struct acpiphp_func *func; char objname[64]; @@ -1242,41 +1372,13 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex } } -static int is_root_bridge(acpi_handle handle) -{ - acpi_status status; - struct acpi_device_info *info; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - int i; - - status = acpi_get_object_info(handle, &buffer); - if (ACPI_SUCCESS(status)) { - info = buffer.pointer; - if ((info->valid & ACPI_VALID_HID) && - !strcmp(PCI_ROOT_HID_STRING, - info->hardware_id.value)) { - acpi_os_free(buffer.pointer); - return 1; - } - if (info->valid & ACPI_VALID_CID) { - for (i=0; i < info->compatibility_id.count; i++) { - if (!strcmp(PCI_ROOT_HID_STRING, - info->compatibility_id.id[i].value)) { - acpi_os_free(buffer.pointer); - return 1; - } - } - } - } - return 0; -} static acpi_status find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) { int *count = (int *)context; - if (is_root_bridge(handle)) { + if (acpi_root_bridge(handle)) { acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_bridge, NULL); (*count)++; @@ -1373,26 +1475,6 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) } #endif -/* search matching slot from id */ -struct acpiphp_slot *get_slot_from_id(int id) -{ - struct list_head *node; - struct acpiphp_bridge *bridge; - struct acpiphp_slot *slot; - - list_for_each (node, &bridge_list) { - bridge = (struct acpiphp_bridge *)node; - for (slot = bridge->slots; slot; slot = slot->next) - if (slot->id == id) - return slot; - } - - /* should never happen! */ - err("%s: no object for id %d\n", __FUNCTION__, id); - WARN_ON(1); - return NULL; -} - /** * acpiphp_enable_slot - power on slot @@ -1401,7 +1483,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) { int retval; - down(&slot->crit_sect); + mutex_lock(&slot->crit_sect); /* wake up all functions */ retval = power_on_slot(slot); @@ -1413,7 +1495,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) retval = enable_device(slot); err_exit: - up(&slot->crit_sect); + mutex_unlock(&slot->crit_sect); return retval; } @@ -1424,7 +1506,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) { int retval = 0; - down(&slot->crit_sect); + mutex_lock(&slot->crit_sect); /* unconfigure all functions */ retval = disable_device(slot); @@ -1437,7 +1519,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) goto err_exit; err_exit: - up(&slot->crit_sect); + mutex_unlock(&slot->crit_sect); return retval; } diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 30af105271a2..037ce4c91687 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -248,22 +248,19 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) * with the pci_hotplug subsystem. */ for (i = first; i <= last; ++i) { - slot = kmalloc(sizeof (struct slot), GFP_KERNEL); + slot = kzalloc(sizeof (struct slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof (struct slot)); hotplug_slot = - kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); + kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL); if (!hotplug_slot) goto error_slot; - memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); + info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); if (!info) goto error_hpslot; - memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index cb88404c89fe..c74e9e37e76b 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -32,6 +32,7 @@ #include <linux/interrupt.h> #include <asm/io.h> /* for read? and write? functions */ #include <linux/delay.h> /* for delays */ +#include <linux/mutex.h> #define MY_NAME "cpqphp" @@ -286,7 +287,7 @@ struct event_info { struct controller { struct controller *next; u32 ctrl_int_comp; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ void __iomem *hpc_reg; /* cookie for our pci controller location */ struct pci_resource *mem_head; struct pci_resource *p_mem_head; diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index b3659ffccac9..9bc1deb8df52 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -347,26 +347,22 @@ static int ctrl_slot_setup(struct controller *ctrl, slot_number = ctrl->first_slot; while (number_of_slots) { - slot = kmalloc(sizeof(*slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); - slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)), + slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; hotplug_slot = slot->hotplug_slot; - memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); hotplug_slot->info = - kmalloc(sizeof(*(hotplug_slot->info)), + kzalloc(sizeof(*(hotplug_slot->info)), GFP_KERNEL); if (!hotplug_slot->info) goto error_hpslot; hotplug_slot_info = hotplug_slot->info; - memset(hotplug_slot_info, 0, - sizeof(struct hotplug_slot_info)); hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); if (!hotplug_slot->name) @@ -599,7 +595,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, hp_slot = func->device - ctrl->slot_device_offset; // Wait for exclusive access to hardware - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (status == 1) { amber_LED_on (ctrl, hp_slot); @@ -607,7 +603,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, amber_LED_off (ctrl, hp_slot); } else { // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(1); } @@ -617,7 +613,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, wait_for_ctrl_irq (ctrl); // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(0); } @@ -854,13 +850,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_disable_device; } - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); rc = -ENOMEM; goto err_disable_device; } - memset(ctrl, 0, sizeof(struct controller)); rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); if (rc) { @@ -1084,7 +1079,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); init_waitqueue_head(&ctrl->queue); /* initialize our threads if they haven't already been started up */ @@ -1223,7 +1218,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // turn off empty slots here unless command line option "ON" set // Wait for exclusive access to hardware - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; @@ -1270,12 +1265,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = init_SERR(ctrl); if (rc) { err("init_SERR failed\n"); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); goto err_free_irq; } // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); cpqhp_create_debugfs_files(ctrl); diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 771ed34b1819..55d2dc7e39ca 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1282,9 +1282,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) u8 hp_slot; u8 temp_byte; u8 adapter_speed; - u32 index; u32 rc = 0; - u32 src = 8; hp_slot = func->device - ctrl->slot_device_offset; @@ -1299,7 +1297,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) **********************************/ rc = CARD_FUNCTIONING; } else { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board without attaching to the bus */ enable_slot_power (ctrl, hp_slot); @@ -1333,12 +1331,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (rc) return rc; - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); slot_enable (ctrl, hp_slot); green_LED_blink (ctrl, hp_slot); @@ -1350,7 +1348,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second because of hot plug spec */ long_delay(1*HZ); @@ -1368,76 +1366,30 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) rc = cpqhp_configure_board(ctrl, func); - if (rc || src) { - /* If configuration fails, turn it off - * Get slot won't work for devices behind - * bridges, but in this case it will always be - * called for the "base" bus/dev/func of an - * adapter. */ + /* If configuration fails, turn it off + * Get slot won't work for devices behind + * bridges, but in this case it will always be + * called for the "base" bus/dev/func of an + * adapter. */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - /* Wait for SOBS to be unset */ - wait_for_ctrl_irq (ctrl); - - up(&ctrl->crit_sect); - - if (rc) - return rc; - else - return 1; - } - - func->status = 0; - func->switch_save = 0x10; - - index = 1; - while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) { - rc |= cpqhp_configure_board(ctrl, func); - index++; - } - - if (rc) { - /* If configuration fails, turn it off - * Get slot won't work for devices behind - * bridges, but in this case it will always be - * called for the "base" bus/dev/func of an - * adapter. */ - - down(&ctrl->crit_sect); - - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - /* Wait for SOBS to be unset */ - wait_for_ctrl_irq (ctrl); - - up(&ctrl->crit_sect); - - return rc; - } - /* Done configuring so turn LED on full time */ - - down(&ctrl->crit_sect); - - green_LED_on (ctrl, hp_slot); + amber_LED_on (ctrl, hp_slot); + green_LED_off (ctrl, hp_slot); + slot_disable (ctrl, hp_slot); set_SOGO(ctrl); /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); - rc = 0; + mutex_unlock(&ctrl->crit_sect); + + if (rc) + return rc; + else + return 1; + } else { /* Something is wrong @@ -1445,7 +1397,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) * in this case it will always be called for the "base" * bus/dev/func of an adapter. */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1456,7 +1408,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } } @@ -1488,7 +1440,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board without attaching to the bus */ enable_slot_power(ctrl, hp_slot); @@ -1522,7 +1474,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq(ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (rc) return rc; @@ -1532,7 +1484,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* turn on board and blink green LED */ dbg("%s: before down\n", __FUNCTION__); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); dbg("%s: after down\n", __FUNCTION__); dbg("%s: before slot_enable\n", __FUNCTION__); @@ -1553,7 +1505,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__); dbg("%s: before up\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); dbg("%s: after up\n", __FUNCTION__); /* Wait for ~1 second because of hot plug spec */ @@ -1607,7 +1559,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); if (rc) { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1618,7 +1570,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } else { cpqhp_save_slot_config(ctrl, func); @@ -1640,7 +1592,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) } } while (new_slot); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); green_LED_on (ctrl, hp_slot); @@ -1649,9 +1601,9 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } else { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1662,7 +1614,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -1721,7 +1673,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control func->status = 0x01; func->configured = 0; - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); green_LED_off (ctrl, hp_slot); slot_disable (ctrl, hp_slot); @@ -1736,7 +1688,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (!replace_flag && ctrl->add_support) { while (func) { @@ -1899,7 +1851,7 @@ static void interrupt_event_handler(struct controller *ctrl) dbg("button cancel\n"); del_timer(&p_slot->task_event); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (p_slot->state == BLINKINGOFF_STATE) { /* slot is on */ @@ -1922,7 +1874,7 @@ static void interrupt_event_handler(struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } /*** button Released (No action on press...) */ else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) { @@ -1937,7 +1889,7 @@ static void interrupt_event_handler(struct controller *ctrl) p_slot->state = BLINKINGON_STATE; info(msg_button_on, p_slot->number); } - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); dbg("blink green LED and turn off amber\n"); @@ -1949,7 +1901,7 @@ static void interrupt_event_handler(struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->hp_slot = hp_slot; p_slot->ctrl = ctrl; diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 060d74775d7b..71b80c23e8ce 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -95,15 +95,13 @@ static int add_slot(struct pci_dev *dev) struct hotplug_slot *slot; int retval = -ENOMEM; - slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(*slot)); - slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!slot->info) goto error_slot; - memset(slot->info, 0, sizeof(struct hotplug_slot_info)); slot->info->power_status = 1; slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; @@ -227,11 +225,10 @@ static void pci_rescan_bus(const struct pci_bus *bus) { unsigned int devfn; struct pci_dev *dev; - dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return; - memset(dev, 0, sizeof(dev)); dev->bus = (struct pci_bus*)bus; dev->sysdata = bus->sysdata; for (devfn = 0; devfn < 0x100; devfn += 8) { diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index c22e0284d7b1..dba6d8ca9bda 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -406,8 +406,6 @@ extern void ibmphp_hpc_stop_poll_thread (void); //---------------------------------------------------------------------------- // HPC return codes //---------------------------------------------------------------------------- -#define FALSE 0x00 -#define TRUE 0x01 #define HPC_ERROR 0xFF //----------------------------------------------------------------------------- diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index dc59da675c08..e13d5b87241a 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -1141,7 +1141,7 @@ static int enable_slot(struct hotplug_slot *hs) goto error_power; } - slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL); + slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); if (!slot_cur->func) { /* We cannot do update_slot_info here, since no memory for * kmalloc n.e.ways, and update_slot_info allocates some */ @@ -1149,7 +1149,6 @@ static int enable_slot(struct hotplug_slot *hs) rc = -ENOMEM; goto error_power; } - memset(slot_cur->func, 0, sizeof(struct pci_func)); slot_cur->func->busno = slot_cur->bus; slot_cur->func->device = slot_cur->device; for (i = 0; i < 4; i++) @@ -1240,9 +1239,9 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) } flag = slot_cur->flag; - slot_cur->flag = TRUE; + slot_cur->flag = 1; - if (flag == TRUE) { + if (flag == 1) { rc = validate(slot_cur, DISABLE); /* checking if powered off already & valid slot # */ if (rc) @@ -1252,13 +1251,12 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) if (slot_cur->func == NULL) { /* We need this for fncs's that were there on bootup */ - slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL); + slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); if (!slot_cur->func) { err("out of system memory\n"); rc = -ENOMEM; goto error; } - memset(slot_cur->func, 0, sizeof(struct pci_func)); slot_cur->func->busno = slot_cur->bus; slot_cur->func->device = slot_cur->device; } diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index aea1187c73ad..05e4f5a1927a 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c @@ -72,13 +72,7 @@ static int ebda_rio_table (void); static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void) { - struct ebda_hpc_list *list; - - list = kmalloc (sizeof (struct ebda_hpc_list), GFP_KERNEL); - if (!list) - return NULL; - memset (list, 0, sizeof (*list)); - return list; + return kzalloc(sizeof(struct ebda_hpc_list), GFP_KERNEL); } static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) @@ -87,21 +81,18 @@ static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) struct ebda_hpc_slot *slots; struct ebda_hpc_bus *buses; - controller = kmalloc (sizeof (struct controller), GFP_KERNEL); + controller = kzalloc(sizeof(struct controller), GFP_KERNEL); if (!controller) goto error; - memset (controller, 0, sizeof (*controller)); - slots = kmalloc (sizeof (struct ebda_hpc_slot) * slot_count, GFP_KERNEL); + slots = kcalloc(slot_count, sizeof(struct ebda_hpc_slot), GFP_KERNEL); if (!slots) goto error_contr; - memset (slots, 0, sizeof (*slots) * slot_count); controller->slots = slots; - buses = kmalloc (sizeof (struct ebda_hpc_bus) * bus_count, GFP_KERNEL); + buses = kcalloc(bus_count, sizeof(struct ebda_hpc_bus), GFP_KERNEL); if (!buses) goto error_slots; - memset (buses, 0, sizeof (*buses) * bus_count); controller->buses = buses; return controller; @@ -122,24 +113,12 @@ static void free_ebda_hpc (struct controller *controller) static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void) { - struct ebda_rsrc_list *list; - - list = kmalloc (sizeof (struct ebda_rsrc_list), GFP_KERNEL); - if (!list) - return NULL; - memset (list, 0, sizeof (*list)); - return list; + return kzalloc(sizeof(struct ebda_rsrc_list), GFP_KERNEL); } static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void) { - struct ebda_pci_rsrc *resource; - - resource = kmalloc (sizeof (struct ebda_pci_rsrc), GFP_KERNEL); - if (!resource) - return NULL; - memset (resource, 0, sizeof (*resource)); - return resource; + return kzalloc(sizeof(struct ebda_pci_rsrc), GFP_KERNEL); } static void __init print_bus_info (void) @@ -390,10 +369,9 @@ int __init ibmphp_access_ebda (void) debug ("now enter io table ---\n"); debug ("rio blk id: %x\n", blk_id); - rio_table_ptr = kmalloc (sizeof (struct rio_table_hdr), GFP_KERNEL); + rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL); if (!rio_table_ptr) return -ENOMEM; - memset (rio_table_ptr, 0, sizeof (struct rio_table_hdr) ); rio_table_ptr->ver_num = readb (io_mem + offset); rio_table_ptr->scal_count = readb (io_mem + offset + 1); rio_table_ptr->riodev_count = readb (io_mem + offset + 2); @@ -445,10 +423,9 @@ static int __init ebda_rio_table (void) // we do concern about rio details for (i = 0; i < rio_table_ptr->riodev_count; i++) { - rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL); + rio_detail_ptr = kzalloc(sizeof(struct rio_detail), GFP_KERNEL); if (!rio_detail_ptr) return -ENOMEM; - memset (rio_detail_ptr, 0, sizeof (struct rio_detail)); rio_detail_ptr->rio_node_id = readb (io_mem + offset); rio_detail_ptr->bbar = readl (io_mem + offset + 1); rio_detail_ptr->rio_type = readb (io_mem + offset + 5); @@ -503,10 +480,9 @@ static int __init combine_wpg_for_chassis (void) rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num); if (!opt_rio_ptr) { - opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL); + opt_rio_ptr = kzalloc(sizeof(struct opt_rio), GFP_KERNEL); if (!opt_rio_ptr) return -ENOMEM; - memset (opt_rio_ptr, 0, sizeof (struct opt_rio)); opt_rio_ptr->rio_type = rio_detail_ptr->rio_type; opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num; opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num; @@ -546,10 +522,9 @@ static int combine_wpg_for_expansion (void) rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num); if (!opt_rio_lo_ptr) { - opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL); + opt_rio_lo_ptr = kzalloc(sizeof(struct opt_rio_lo), GFP_KERNEL); if (!opt_rio_lo_ptr) return -ENOMEM; - memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo)); opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type; opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num; opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num; @@ -842,12 +817,11 @@ static int __init ebda_rsrc_controller (void) bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num); if (!bus_info_ptr2) { - bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL); + bus_info_ptr1 = kzalloc(sizeof(struct bus_info), GFP_KERNEL); if (!bus_info_ptr1) { rc = -ENOMEM; goto error_no_hp_slot; } - memset (bus_info_ptr1, 0, sizeof (struct bus_info)); bus_info_ptr1->slot_min = slot_ptr->slot_num; bus_info_ptr1->slot_max = slot_ptr->slot_num; bus_info_ptr1->slot_count += 1; @@ -946,19 +920,17 @@ static int __init ebda_rsrc_controller (void) // register slots with hpc core as well as create linked list of ibm slot for (index = 0; index < hpc_ptr->slot_count; index++) { - hp_slot_ptr = kmalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); + hp_slot_ptr = kzalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); if (!hp_slot_ptr) { rc = -ENOMEM; goto error_no_hp_slot; } - memset(hp_slot_ptr, 0, sizeof(*hp_slot_ptr)); - hp_slot_ptr->info = kmalloc (sizeof(struct hotplug_slot_info), GFP_KERNEL); + hp_slot_ptr->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!hp_slot_ptr->info) { rc = -ENOMEM; goto error_no_hp_info; } - memset(hp_slot_ptr->info, 0, sizeof(struct hotplug_slot_info)); hp_slot_ptr->name = kmalloc(30, GFP_KERNEL); if (!hp_slot_ptr->name) { @@ -966,14 +938,13 @@ static int __init ebda_rsrc_controller (void) goto error_no_hp_name; } - tmp_slot = kmalloc(sizeof(*tmp_slot), GFP_KERNEL); + tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL); if (!tmp_slot) { rc = -ENOMEM; goto error_no_slot; } - memset(tmp_slot, 0, sizeof(*tmp_slot)); - tmp_slot->flag = TRUE; + tmp_slot->flag = 1; tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap; if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index 1a3eb8d3d4cb..c3ac98a0a6a6 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -34,9 +34,11 @@ #include <linux/pci.h> #include <linux/smp_lock.h> #include <linux/init.h> +#include <linux/mutex.h> + #include "ibmphp.h" -static int to_debug = FALSE; +static int to_debug = 0; #define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0) //---------------------------------------------------------------------------- @@ -93,15 +95,15 @@ static int to_debug = FALSE; //---------------------------------------------------------------------------- // macro utilities //---------------------------------------------------------------------------- -// if bits 20,22,25,26,27,29,30 are OFF return TRUE -#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? FALSE : TRUE)) +// if bits 20,22,25,26,27,29,30 are OFF return 1 +#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? 0 : 1)) //---------------------------------------------------------------------------- // global variables //---------------------------------------------------------------------------- static int ibmphp_shutdown; static int tid_poll; -static struct semaphore sem_hpcaccess; // lock access to HPC +static struct mutex sem_hpcaccess; // lock access to HPC static struct semaphore semOperations; // lock all operations and // access to data structures static struct semaphore sem_exit; // make sure polling thread goes away @@ -131,11 +133,11 @@ void __init ibmphp_hpc_initvars (void) { debug ("%s - Entry\n", __FUNCTION__); - init_MUTEX (&sem_hpcaccess); + mutex_init(&sem_hpcaccess); init_MUTEX (&semOperations); init_MUTEX_LOCKED (&sem_exit); - to_debug = FALSE; - ibmphp_shutdown = FALSE; + to_debug = 0; + ibmphp_shutdown = 0; tid_poll = 0; debug ("%s - Exit\n", __FUNCTION__); @@ -737,21 +739,21 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) // check controller is still not working on the command //-------------------------------------------------------------------- timeout = CMD_COMPLETE_TOUT_SEC; - done = FALSE; + done = 0; while (!done) { rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status); if (!rc) { if (NEEDTOCHECK_CMDSTATUS (cmd)) { if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES) - done = TRUE; + done = 1; } else - done = TRUE; + done = 1; } if (!done) { msleep(1000); if (timeout < 1) { - done = TRUE; + done = 1; err ("%s - Error command complete timeout\n", __FUNCTION__); rc = -EFAULT; } else @@ -778,7 +780,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) *---------------------------------------------------------------------*/ static void get_hpc_access (void) { - down (&sem_hpcaccess); + mutex_lock(&sem_hpcaccess); } /*---------------------------------------------------------------------- @@ -786,7 +788,7 @@ static void get_hpc_access (void) *---------------------------------------------------------------------*/ void free_hpc_access (void) { - up (&sem_hpcaccess); + mutex_unlock(&sem_hpcaccess); } /*---------------------------------------------------------------------- @@ -797,7 +799,7 @@ void free_hpc_access (void) void ibmphp_lock_operations (void) { down (&semOperations); - to_debug = TRUE; + to_debug = 1; } /*---------------------------------------------------------------------- @@ -807,7 +809,7 @@ void ibmphp_unlock_operations (void) { debug ("%s - Entry\n", __FUNCTION__); up (&semOperations); - to_debug = FALSE; + to_debug = 0; debug ("%s - Exit\n", __FUNCTION__); } @@ -935,40 +937,40 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) { u8 status; int rc = 0; - u8 disable = FALSE; - u8 update = FALSE; + u8 disable = 0; + u8 update = 0; debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot); // bit 0 - HPC_SLOT_POWER if ((pslot->status & 0x01) != (poldslot->status & 0x01)) - update = TRUE; + update = 1; // bit 1 - HPC_SLOT_CONNECT // ignore // bit 2 - HPC_SLOT_ATTN if ((pslot->status & 0x04) != (poldslot->status & 0x04)) - update = TRUE; + update = 1; // bit 3 - HPC_SLOT_PRSNT2 // bit 4 - HPC_SLOT_PRSNT1 if (((pslot->status & 0x08) != (poldslot->status & 0x08)) || ((pslot->status & 0x10) != (poldslot->status & 0x10))) - update = TRUE; + update = 1; // bit 5 - HPC_SLOT_PWRGD if ((pslot->status & 0x20) != (poldslot->status & 0x20)) // OFF -> ON: ignore, ON -> OFF: disable slot if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) - disable = TRUE; + disable = 1; // bit 6 - HPC_SLOT_BUS_SPEED // ignore // bit 7 - HPC_SLOT_LATCH if ((pslot->status & 0x80) != (poldslot->status & 0x80)) { - update = TRUE; + update = 1; // OPEN -> CLOSE if (pslot->status & 0x80) { if (SLOT_PWRGD (pslot->status)) { @@ -977,7 +979,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) msleep(1000); rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); if (SLOT_PWRGD (status)) - update = TRUE; + update = 1; else // overwrite power in pslot to OFF pslot->status &= ~HPC_SLOT_POWER; } @@ -985,17 +987,17 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) // CLOSE -> OPEN else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) { - disable = TRUE; + disable = 1; } // else - ignore } // bit 4 - HPC_SLOT_BLINK_ATTN if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08)) - update = TRUE; + update = 1; if (disable) { debug ("process_changeinstatus - disable slot\n"); - pslot->flag = FALSE; + pslot->flag = 0; rc = ibmphp_do_disable_slot (pslot); } @@ -1100,7 +1102,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void) { debug ("%s - Entry\n", __FUNCTION__); - ibmphp_shutdown = TRUE; + ibmphp_shutdown = 1; debug ("before locking operations \n"); ibmphp_lock_operations (); debug ("after locking operations \n"); @@ -1134,7 +1136,7 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v u8 * pstatus) { int rc = 0; - u8 done = FALSE; + u8 done = 0; debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout); @@ -1142,14 +1144,14 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v *pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX); if (*pstatus == HPC_ERROR) { rc = HPC_ERROR; - done = TRUE; + done = 1; } if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO) - done = TRUE; + done = 1; if (!done) { msleep(1000); if (timeout < 1) { - done = TRUE; + done = 1; err ("HPCreadslot - Error ctlr timeout\n"); rc = HPC_ERROR; } else diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 155133fe5c12..d87a9e3eaeeb 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -164,12 +164,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 6; goto error; } - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = cur_func->busno; newfunc->device = device; cur_func->next = newfunc; @@ -200,15 +199,14 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) } pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); - flag = FALSE; + flag = 0; for (i = 0; i < 32; i++) { if (func->devices[i]) { - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = sec_number; newfunc->device = (u8) i; for (j = 0; j < 4; j++) @@ -228,16 +226,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 2; goto error; } - flag = TRUE; + flag = 1; } } - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = cur_func->busno; newfunc->device = device; for (j = 0; j < 4; j++) @@ -275,16 +272,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cur_func->busno, device, function); pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); debug ("after configuring bridge..., sec_number = %x\n", sec_number); - flag = FALSE; + flag = 0; for (i = 0; i < 32; i++) { if (func->devices[i]) { debug ("inside for loop, device is %x\n", i); - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err (" out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = sec_number; newfunc->device = (u8) i; for (j = 0; j < 4; j++) @@ -305,7 +301,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 2; goto error; } - flag = TRUE; + flag = 1; } } @@ -405,13 +401,12 @@ static int configure_device (struct pci_func *func) debug ("len[count] in IO %x, count %d\n", len[count], count); - io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!io[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (io[count], 0, sizeof (struct resource_node)); io[count]->type = IO; io[count]->busno = func->busno; io[count]->devfunc = PCI_DEVFN(func->device, func->function); @@ -444,29 +439,27 @@ static int configure_device (struct pci_func *func) debug ("len[count] in PFMEM %x, count %d\n", len[count], count); - pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!pfmem[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem[count], 0, sizeof (struct resource_node)); pfmem[count]->type = PFMEM; pfmem[count]->busno = func->busno; pfmem[count]->devfunc = PCI_DEVFN(func->device, func->function); pfmem[count]->len = len[count]; - pfmem[count]->fromMem = FALSE; + pfmem[count]->fromMem = 0; if (ibmphp_check_resource (pfmem[count], 0) == 0) { ibmphp_add_resource (pfmem[count]); func->pfmem[count] = pfmem[count]; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); kfree (pfmem[count]); return -ENOMEM; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = pfmem[count]->busno; mem_tmp->devfunc = pfmem[count]->devfunc; @@ -474,7 +467,7 @@ static int configure_device (struct pci_func *func) debug ("there's no pfmem... going into mem.\n"); if (ibmphp_check_resource (mem_tmp, 0) == 0) { ibmphp_add_resource (mem_tmp); - pfmem[count]->fromMem = TRUE; + pfmem[count]->fromMem = 1; pfmem[count]->rangeno = mem_tmp->rangeno; pfmem[count]->start = mem_tmp->start; pfmem[count]->end = mem_tmp->end; @@ -512,12 +505,11 @@ static int configure_device (struct pci_func *func) debug ("len[count] in Mem %x, count %d\n", len[count], count); - mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem[count], 0, sizeof (struct resource_node)); mem[count]->type = MEM; mem[count]->busno = func->busno; mem[count]->devfunc = PCI_DEVFN(func->device, @@ -579,11 +571,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) u16 pfmem_base; u32 bar[2]; u32 len[2]; - u8 flag_io = FALSE; - u8 flag_mem = FALSE; - u8 flag_pfmem = FALSE; - u8 need_io_upper = FALSE; - u8 need_pfmem_upper = FALSE; + u8 flag_io = 0; + u8 flag_mem = 0; + u8 flag_pfmem = 0; + u8 need_io_upper = 0; + u8 need_pfmem_upper = 0; struct res_needed *amount_needed = NULL; struct resource_node *io = NULL; struct resource_node *bus_io[2] = {NULL, NULL}; @@ -677,14 +669,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in IO = %x\n", len[count]); - bus_io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_io[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_io[count], 0, sizeof (struct resource_node)); bus_io[count]->type = IO; bus_io[count]->busno = func->busno; bus_io[count]->devfunc = PCI_DEVFN(func->device, @@ -711,37 +702,35 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in PFMEM = %x\n", len[count]); - bus_pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_pfmem[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_pfmem[count], 0, sizeof (struct resource_node)); bus_pfmem[count]->type = PFMEM; bus_pfmem[count]->busno = func->busno; bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, func->function); bus_pfmem[count]->len = len[count]; - bus_pfmem[count]->fromMem = FALSE; + bus_pfmem[count]->fromMem = 0; if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) { ibmphp_add_resource (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = bus_pfmem[count]->busno; mem_tmp->devfunc = bus_pfmem[count]->devfunc; mem_tmp->len = bus_pfmem[count]->len; if (ibmphp_check_resource (mem_tmp, 0) == 0) { ibmphp_add_resource (mem_tmp); - bus_pfmem[count]->fromMem = TRUE; + bus_pfmem[count]->fromMem = 1; bus_pfmem[count]->rangeno = mem_tmp->rangeno; ibmphp_add_pfmem_from_mem (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; @@ -770,13 +759,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in Memory is %x\n", len[count]); - bus_mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_mem[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_mem[count], 0, sizeof (struct resource_node)); bus_mem[count]->type = MEM; bus_mem[count]->busno = func->busno; bus_mem[count]->devfunc = PCI_DEVFN(func->device, @@ -838,17 +826,16 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if (!amount_needed->io) { debug ("it doesn't want IO?\n"); - flag_io = TRUE; + flag_io = 1; } else { debug ("it wants %x IO behind the bridge\n", amount_needed->io); - io = kmalloc(sizeof(*io), GFP_KERNEL); + io = kzalloc(sizeof(*io), GFP_KERNEL); if (!io) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (io, 0, sizeof (struct resource_node)); io->type = IO; io->busno = func->busno; io->devfunc = PCI_DEVFN(func->device, func->function); @@ -856,71 +843,68 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if (ibmphp_check_resource (io, 1) == 0) { debug ("were we able to add io\n"); ibmphp_add_resource (io); - flag_io = TRUE; + flag_io = 1; } } if (!amount_needed->mem) { debug ("it doesn't want n.e.memory?\n"); - flag_mem = TRUE; + flag_mem = 1; } else { debug ("it wants %x memory behind the bridge\n", amount_needed->mem); - mem = kmalloc(sizeof(*mem), GFP_KERNEL); + mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = func->busno; mem->devfunc = PCI_DEVFN(func->device, func->function); mem->len = amount_needed->mem; if (ibmphp_check_resource (mem, 1) == 0) { ibmphp_add_resource (mem); - flag_mem = TRUE; + flag_mem = 1; debug ("were we able to add mem\n"); } } if (!amount_needed->pfmem) { debug ("it doesn't want n.e.pfmem mem?\n"); - flag_pfmem = TRUE; + flag_pfmem = 1; } else { debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem); - pfmem = kmalloc(sizeof(*pfmem), GFP_KERNEL); + pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL); if (!pfmem) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (pfmem, 0, sizeof (struct resource_node)); pfmem->type = PFMEM; pfmem->busno = func->busno; pfmem->devfunc = PCI_DEVFN(func->device, func->function); pfmem->len = amount_needed->pfmem; - pfmem->fromMem = FALSE; + pfmem->fromMem = 0; if (ibmphp_check_resource (pfmem, 1) == 0) { ibmphp_add_resource (pfmem); - flag_pfmem = TRUE; + flag_pfmem = 1; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = pfmem->busno; mem_tmp->devfunc = pfmem->devfunc; mem_tmp->len = pfmem->len; if (ibmphp_check_resource (mem_tmp, 1) == 0) { ibmphp_add_resource (mem_tmp); - pfmem->fromMem = TRUE; + pfmem->fromMem = 1; pfmem->rangeno = mem_tmp->rangeno; ibmphp_add_pfmem_from_mem (pfmem); - flag_pfmem = TRUE; + flag_pfmem = 1; } } } @@ -936,13 +920,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) */ bus = ibmphp_find_res_bus (sec_number); if (!bus) { - bus = kmalloc(sizeof(*bus), GFP_KERNEL); + bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (!bus) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus, 0, sizeof (struct bus_node)); bus->busno = sec_number; debug ("b4 adding new bus\n"); rc = add_new_bus (bus, io, mem, pfmem, func->busno); @@ -967,11 +950,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { debug ("io 32\n"); - need_io_upper = TRUE; + need_io_upper = 1; } if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { debug ("pfmem 64\n"); - need_pfmem_upper = TRUE; + need_pfmem_upper = 1; } if (bus->noIORanges) { @@ -1111,10 +1094,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) }; struct res_needed *amount; - amount = kmalloc(sizeof(*amount), GFP_KERNEL); + amount = kzalloc(sizeof(*amount), GFP_KERNEL); if (amount == NULL) return NULL; - memset (amount, 0, sizeof (struct res_needed)); ibmphp_pci_bus->number = busno; @@ -1137,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) debug ("hdr_type behind the bridge is %x\n", hdr_type); if (hdr_type & PCI_HEADER_TYPE_BRIDGE) { err ("embedded bridges not supported for hot-plugging.\n"); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } @@ -1145,12 +1127,12 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) if (class == PCI_CLASS_NOT_DEFINED_VGA) { err ("The device %x is VGA compatible and as is not supported for hot plugging. " "Please choose another device.\n", device); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } else if (class == PCI_CLASS_DISPLAY_VGA) { err ("The device %x is not supported for hot plugging. " "Please choose another device.\n", device); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } @@ -1210,9 +1192,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) } /* end for */ if (!howmany) - amount->not_correct = TRUE; + amount->not_correct = 1; else - amount->not_correct = FALSE; + amount->not_correct = 0; if ((amount->io) && (amount->io < IOBRIDGE)) amount->io = IOBRIDGE; if ((amount->mem) && (amount->mem < MEMBRIDGE)) @@ -1672,12 +1654,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r list_add (&bus->bus_list, &cur_bus->bus_list); } if (io) { - io_range = kmalloc(sizeof(*io_range), GFP_KERNEL); + io_range = kzalloc(sizeof(*io_range), GFP_KERNEL); if (!io_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (io_range, 0, sizeof (struct range_node)); io_range->start = io->start; io_range->end = io->end; io_range->rangeno = 1; @@ -1685,12 +1666,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r bus->rangeIO = io_range; } if (mem) { - mem_range = kmalloc(sizeof(*mem_range), GFP_KERNEL); + mem_range = kzalloc(sizeof(*mem_range), GFP_KERNEL); if (!mem_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem_range, 0, sizeof (struct range_node)); mem_range->start = mem->start; mem_range->end = mem->end; mem_range->rangeno = 1; @@ -1698,12 +1678,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r bus->rangeMem = mem_range; } if (pfmem) { - pfmem_range = kmalloc(sizeof(*pfmem_range), GFP_KERNEL); + pfmem_range = kzalloc(sizeof(*pfmem_range), GFP_KERNEL); if (!pfmem_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem_range, 0, sizeof (struct range_node)); pfmem_range->start = pfmem->start; pfmem_range->end = pfmem->end; pfmem_range->rangeno = 1; diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index 9c224c94d698..5636b1ac2a2e 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c @@ -55,13 +55,12 @@ static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 return NULL; } - newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL); if (!newbus) { err ("out of system memory\n"); return NULL; } - memset (newbus, 0, sizeof (struct bus_node)); if (flag) newbus->busno = busno; else @@ -79,12 +78,11 @@ static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * cur return NULL; } - rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!rs) { err ("out of system memory\n"); return NULL; } - memset (rs, 0, sizeof (struct resource_node)); rs->busno = curr->bus_num; rs->devfunc = curr->dev_fun; rs->start = curr->start_addr; @@ -100,12 +98,11 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node u8 num_ranges = 0; if (first_bus) { - newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL); if (!newbus) { err ("out of system memory.\n"); return -ENOMEM; } - memset (newbus, 0, sizeof (struct bus_node)); newbus->busno = curr->bus_num; } else { newbus = *new_bus; @@ -122,14 +119,13 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node } } - newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL); + newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!newrange) { if (first_bus) kfree (newbus); err ("out of system memory\n"); return -ENOMEM; } - memset (newrange, 0, sizeof (struct range_node)); newrange->start = curr->start_addr; newrange->end = curr->end_addr; @@ -329,7 +325,7 @@ int __init ibmphp_rsrc_init (void) if (!new_pfmem) return -ENOMEM; new_pfmem->type = PFMEM; - new_pfmem->fromMem = FALSE; + new_pfmem->fromMem = 0; if (ibmphp_add_resource (new_pfmem) < 0) { newbus = alloc_error_bus (curr, 0, 0); if (!newbus) @@ -466,7 +462,7 @@ static int add_range (int type, struct range_node *range, struct bus_node *bus_c static void update_resources (struct bus_node *bus_cur, int type, int rangeno) { struct resource_node *res = NULL; - u8 eol = FALSE; /* end of list indicator */ + u8 eol = 0; /* end of list indicator */ switch (type) { case MEM: @@ -492,7 +488,7 @@ static void update_resources (struct bus_node *bus_cur, int type, int rangeno) else if (res->nextRange) res = res->nextRange; else { - eol = TRUE; + eol = 1; break; } } @@ -983,7 +979,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) int noranges = 0; u32 tmp_start; /* this is to make sure start address is divisible by the length needed */ u32 tmp_divide; - u8 flag = FALSE; + u8 flag = 0; if (!res) return -EINVAL; @@ -1050,17 +1046,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((range->start % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1089,17 +1085,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if (((res_cur->end + 1) % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = res_cur->end + 1; } else { /* Needs adjusting */ tmp_start = res_cur->end + 1; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1127,17 +1123,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1162,17 +1158,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if (((res_prev->end + 1) % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = res_prev->end + 1; } else { /* Needs adjusting */ tmp_start = res_prev->end + 1; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1221,17 +1217,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1285,17 +1281,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1688,7 +1684,7 @@ static int __init once_over (void) bus_cur = list_entry (tmp, struct bus_node, bus_list); if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) { for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) { - pfmem_cur->fromMem = TRUE; + pfmem_cur->fromMem = 1; if (pfmem_prev) pfmem_prev->next = pfmem_cur->next; else @@ -1705,12 +1701,11 @@ static int __init once_over (void) bus_cur->firstPFMemFromMem = pfmem_cur; - mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = pfmem_cur->busno; mem->devfunc = pfmem_cur->devfunc; @@ -1994,12 +1989,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) end_address |= (upper_io_end << 16); if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfff; @@ -2020,13 +2014,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) { - io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + io = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!io) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (io, 0, sizeof (struct resource_node)); io->type = IO; io->busno = bus_cur->busno; io->devfunc = ((device << 3) | (function & 0x7)); @@ -2045,12 +2038,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfffff; @@ -2072,13 +2064,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) { - mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = bus_cur->busno; mem->devfunc = ((device << 3) | (function & 0x7)); @@ -2101,12 +2092,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfffff; @@ -2127,20 +2117,19 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) { - pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + pfmem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!pfmem) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem, 0, sizeof (struct resource_node)); pfmem->type = PFMEM; pfmem->busno = bus_cur->busno; pfmem->devfunc = ((device << 3) | (function & 0x7)); pfmem->start = start_address; pfmem->end = end_address + 0xfffff; pfmem->len = pfmem->end - pfmem->start + 1; - pfmem->fromMem = FALSE; + pfmem->fromMem = 0; ibmphp_add_resource (pfmem); } diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index 88d44f7fef29..eb0d01d47236 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -176,5 +176,21 @@ extern int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info); extern struct subsystem pci_hotplug_slots_subsys; +struct hotplug_params { + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + +#ifdef CONFIG_ACPI +#include <acpi/acpi.h> +#include <acpi/acpi_bus.h> +#include <acpi/actypes.h> +extern acpi_status acpi_run_oshp(acpi_handle handle); +extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp); +int acpi_root_bridge(acpi_handle handle); +#endif #endif diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 0aac6a61337d..92c1f0f1e1ad 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -34,6 +34,7 @@ #include <linux/delay.h> #include <linux/sched.h> /* signal_pending() */ #include <linux/pcieport_if.h> +#include <linux/mutex.h> #include "pci_hotplug.h" #define MY_NAME "pciehp" @@ -49,12 +50,6 @@ extern int pciehp_force; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -struct hotplug_params { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; struct slot { struct slot *next; @@ -96,7 +91,7 @@ struct php_ctlr_state_s { #define MAX_EVENTS 10 struct controller { struct controller *next; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ @@ -191,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); /* pci functions */ extern int pciehp_configure_device (struct slot *p_slot); extern int pciehp_unconfigure_device (struct slot *p_slot); -extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev); -extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp); @@ -285,4 +277,19 @@ struct hpc_ops { int (*check_lnk_status) (struct controller *ctrl); }; + +#ifdef CONFIG_ACPI +#define pciehp_get_hp_hw_control_from_firmware(dev) \ + pciehp_acpi_get_hp_hw_control_from_firmware(dev) +static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) +{ + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + return -ENODEV; + return 0; +} +#else +#define pciehp_get_hp_hw_control_from_firmware(dev) 0 +#define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV) +#endif /* CONFIG_ACPI */ #endif /* _PCIEHP_H */ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 4fb569018a24..601cf9045b20 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -117,27 +117,23 @@ static int init_slots(struct controller *ctrl) slot_number = ctrl->first_slot; while (number_of_slots) { - slot = kmalloc(sizeof(*slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); slot->hotplug_slot = - kmalloc(sizeof(*(slot->hotplug_slot)), + kzalloc(sizeof(*(slot->hotplug_slot)), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; hotplug_slot = slot->hotplug_slot; - memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); hotplug_slot->info = - kmalloc(sizeof(*(hotplug_slot->info)), + kzalloc(sizeof(*(hotplug_slot->info)), GFP_KERNEL); if (!hotplug_slot->info) goto error_hpslot; hotplug_slot_info = hotplug_slot->info; - memset(hotplug_slot_info, 0, - sizeof(struct hotplug_slot_info)); hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); if (!hotplug_slot->name) goto error_info; @@ -373,12 +369,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ u8 value; struct pci_dev *pdev; - ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; } - memset(ctrl, 0, sizeof(struct controller)); pdev = dev->port; ctrl->pci_dev = pdev; @@ -439,7 +434,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ @@ -447,7 +442,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ if (rc) { /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); goto err_out_free_ctrl_slot; } else /* Wait for the command to complete */ @@ -455,7 +450,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 83c4b865718a..33d198768356 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -229,13 +229,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) static void set_slot_off(struct controller *ctrl, struct slot * pslot) { /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ if (POWER_CTRL(ctrl->ctrlcap)) { if (pslot->hpc_ops->power_off_slot(pslot)) { err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return; } wait_for_ctrl_irq (ctrl); @@ -249,14 +249,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) if (ATTN_LED(ctrl->ctrlcap)) { if (pslot->hpc_ops->set_attention_status(pslot, 1)) { err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return; } wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } /** @@ -279,13 +279,13 @@ static int board_added(struct slot *p_slot) ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (POWER_CTRL(ctrl->ctrlcap)) { /* Power on slot */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -301,7 +301,7 @@ static int board_added(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -335,7 +335,7 @@ static int board_added(struct slot *p_slot) pci_fixup_device(pci_fixup_final, ctrl->pci_dev); if (PWR_LED(ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); @@ -343,7 +343,7 @@ static int board_added(struct slot *p_slot) wait_for_ctrl_irq (ctrl); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } return 0; @@ -375,14 +375,14 @@ static int remove_board(struct slot *p_slot) dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (POWER_CTRL(ctrl->ctrlcap)) { /* power off slot */ rc = p_slot->hpc_ops->power_off_slot(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Wait for the command to complete */ @@ -398,7 +398,7 @@ static int remove_board(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; } @@ -445,7 +445,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); @@ -453,7 +453,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) wait_for_ctrl_irq (p_slot->ctrl); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -495,7 +495,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); @@ -503,7 +503,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) wait_for_ctrl_irq (p_slot->ctrl); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -616,7 +616,7 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_on(p_slot); @@ -630,11 +630,11 @@ static void interrupt_event_handler(struct controller *ctrl) wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_off(p_slot); @@ -647,7 +647,7 @@ static void interrupt_event_handler(struct controller *ctrl) wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; default: @@ -676,7 +676,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* blink green LED and turn off amber */ if (PWR_LED(ctrl->ctrlcap)) { @@ -693,7 +693,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ @@ -708,7 +708,7 @@ static void interrupt_event_handler(struct controller *ctrl) if (POWER_CTRL(ctrl->ctrlcap)) { dbg("power fault\n"); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (ATTN_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->set_attention_status(p_slot, 1); @@ -721,7 +721,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } } /***********SURPRISE REMOVAL********************/ @@ -756,19 +756,19 @@ int pciehp_enable_slot(struct slot *p_slot) int rc; /* Check to see if (latch closed, card present, power off) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } if (MRL_SENS(p_slot->ctrl->ctrlcap)) { rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -777,11 +777,11 @@ int pciehp_enable_slot(struct slot *p_slot) rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -806,13 +806,13 @@ int pciehp_disable_slot(struct slot *p_slot) return 1; /* Check to see if (latch closed, card present, power on) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -821,7 +821,7 @@ int pciehp_disable_slot(struct slot *p_slot) ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -830,12 +830,12 @@ int pciehp_disable_slot(struct slot *p_slot) ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); ret = remove_board(p_slot); update_slot_info(p_slot); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 77e530321de2..6c14d9e46b2e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -38,7 +38,10 @@ #include "../pci.h" #include "pciehp.h" - +#include <acpi/acpi.h> +#include <acpi/acpi_bus.h> +#include <acpi/actypes.h> +#include <linux/pci-acpi.h> #ifdef DEBUG #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ #define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ @@ -1236,6 +1239,76 @@ static struct hpc_ops pciehp_hpc_ops = { .check_lnk_status = hpc_check_lnk_status, }; +#ifdef CONFIG_ACPI +int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) +{ + acpi_status status; + acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + struct pci_dev *pdev = dev; + struct pci_bus *parent; + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; + + /* + * Per PCI firmware specification, we should run the ACPI _OSC + * method to get control of hotplug hardware before using it. + * If an _OSC is missing, we look for an OSHP to do the same thing. + * To handle different BIOS behavior, we look for _OSC and OSHP + * within the scope of the hotplug controller and its parents, upto + * the host bridge under which this controller exists. + */ + while (!handle) { + /* + * This hotplug controller was not listed in the ACPI name + * space at all. Try to get acpi handle of parent pci bus. + */ + if (!pdev || !pdev->bus->parent) + break; + parent = pdev->bus->parent; + dbg("Could not find %s in acpi namespace, trying parent\n", + pci_name(pdev)); + if (!parent->self) + /* Parent must be a host bridge */ + handle = acpi_get_pci_rootbridge_handle( + pci_domain_nr(parent), + parent->number); + else + handle = DEVICE_ACPI_HANDLE( + &(parent->self->dev)); + pdev = parent->self; + } + + while (handle) { + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + dbg("Trying to get hotplug control for %s \n", + (char *)string.pointer); + status = pci_osc_control_set(handle, + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + if (status == AE_NOT_FOUND) + status = acpi_run_oshp(handle); + if (ACPI_SUCCESS(status)) { + dbg("Gained control for hotplug HW for pci %s (%s)\n", + pci_name(dev), (char *)string.pointer); + acpi_os_free(string.pointer); + return 0; + } + if (acpi_root_bridge(handle)) + break; + chandle = handle; + status = acpi_get_parent(chandle, &handle); + if (ACPI_FAILURE(status)) + break; + } + + err("Cannot get control of hotplug hardware for pci %s\n", + pci_name(dev)); + + acpi_os_free(string.pointer); + return -1; +} +#endif + + + int pcie_init(struct controller * ctrl, struct pcie_device *dev) { struct php_ctlr_state_s *php_ctlr, *p; @@ -1334,7 +1407,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) if (pci_enable_device(pdev)) goto abort_free_ctlr; - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); /* setup wait queue */ init_waitqueue_head(&ctrl->queue); diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c deleted file mode 100644 index 2bdb30f68bf8..000000000000 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform - * - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to <kristen.c.accardi@intel.com> - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/acpi.h> -#include <linux/pci-acpi.h> -#include <acpi/acpi_bus.h> -#include <acpi/actypes.h> -#include "pciehp.h" - -#define METHOD_NAME__SUN "_SUN" -#define METHOD_NAME__HPP "_HPP" -#define METHOD_NAME_OSHP "OSHP" - -static u8 * acpi_path_name( acpi_handle handle) -{ - acpi_status status; - static u8 path_name[ACPI_PATHNAME_MAX]; - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; - - memset(path_name, 0, sizeof (path_name)); - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); - - if (ACPI_FAILURE(status)) - return NULL; - else - return path_name; -} - -static acpi_status -acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) -{ - acpi_status status; - u8 nui[4]; - struct acpi_buffer ret_buf = { 0, NULL}; - union acpi_object *ext_obj, *package; - u8 *path_name = acpi_path_name(handle); - int i, len = 0; - - /* get _hpp */ - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); - switch (status) { - case AE_BUFFER_OVERFLOW: - ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); - if (!ret_buf.pointer) { - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, - path_name); - return AE_NO_MEMORY; - } - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, - NULL, &ret_buf); - if (ACPI_SUCCESS(status)) - break; - default: - if (ACPI_FAILURE(status)) { - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, - path_name, status); - return status; - } - } - - ext_obj = (union acpi_object *) ret_buf.pointer; - if (ext_obj->type != ACPI_TYPE_PACKAGE) { - err ("%s:%s _HPP obj not a package\n", __FUNCTION__, - path_name); - status = AE_ERROR; - goto free_and_return; - } - - len = ext_obj->package.count; - package = (union acpi_object *) ret_buf.pointer; - for ( i = 0; (i < len) || (i < 4); i++) { - ext_obj = (union acpi_object *) &package->package.elements[i]; - switch (ext_obj->type) { - case ACPI_TYPE_INTEGER: - nui[i] = (u8)ext_obj->integer.value; - break; - default: - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, - path_name); - status = AE_ERROR; - goto free_and_return; - } - } - - hpp->cache_line_size = nui[0]; - hpp->latency_timer = nui[1]; - hpp->enable_serr = nui[2]; - hpp->enable_perr = nui[3]; - - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); - -free_and_return: - kfree(ret_buf.pointer); - return status; -} - -static acpi_status acpi_run_oshp(acpi_handle handle) -{ - acpi_status status; - u8 *path_name = acpi_path_name(handle); - - /* run OSHP */ - status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); - if (ACPI_FAILURE(status)) { - dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, - status); - } else { - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); - } - return status; -} - -static int is_root_bridge(acpi_handle handle) -{ - acpi_status status; - struct acpi_device_info *info; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - int i; - - status = acpi_get_object_info(handle, &buffer); - if (ACPI_SUCCESS(status)) { - info = buffer.pointer; - if ((info->valid & ACPI_VALID_HID) && - !strcmp(PCI_ROOT_HID_STRING, - info->hardware_id.value)) { - acpi_os_free(buffer.pointer); - return 1; - } - if (info->valid & ACPI_VALID_CID) { - for (i=0; i < info->compatibility_id.count; i++) { - if (!strcmp(PCI_ROOT_HID_STRING, - info->compatibility_id.id[i].value)) { - acpi_os_free(buffer.pointer); - return 1; - } - } - } - } - return 0; -} - -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - acpi_status status; - acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); - struct pci_dev *pdev = dev; - struct pci_bus *parent; - u8 *path_name; - - /* - * Per PCI firmware specification, we should run the ACPI _OSC - * method to get control of hotplug hardware before using it. - * If an _OSC is missing, we look for an OSHP to do the same thing. - * To handle different BIOS behavior, we look for _OSC and OSHP - * within the scope of the hotplug controller and its parents, upto - * the host bridge under which this controller exists. - */ - while (!handle) { - /* - * This hotplug controller was not listed in the ACPI name - * space at all. Try to get acpi handle of parent pci bus. - */ - if (!pdev || !pdev->bus->parent) - break; - parent = pdev->bus->parent; - dbg("Could not find %s in acpi namespace, trying parent\n", - pci_name(pdev)); - if (!parent->self) - /* Parent must be a host bridge */ - handle = acpi_get_pci_rootbridge_handle( - pci_domain_nr(parent), - parent->number); - else - handle = DEVICE_ACPI_HANDLE( - &(parent->self->dev)); - pdev = parent->self; - } - - while (handle) { - path_name = acpi_path_name(handle); - dbg("Trying to get hotplug control for %s \n", path_name); - status = pci_osc_control_set(handle, - OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); - if (status == AE_NOT_FOUND) - status = acpi_run_oshp(handle); - if (ACPI_SUCCESS(status)) { - dbg("Gained control for hotplug HW for pci %s (%s)\n", - pci_name(dev), path_name); - return 0; - } - if (is_root_bridge(handle)) - break; - chandle = handle; - status = acpi_get_parent(chandle, &handle); - if (ACPI_FAILURE(status)) - break; - } - - err("Cannot get control of hotplug hardware for pci %s\n", - pci_name(dev)); - return -1; -} - -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = dev; - - /* - * _HPP settings apply to all child buses, until another _HPP is - * encountered. If we don't find an _HPP for the input pci dev, - * look for it in the parent device scope since that would apply to - * this pci dev. If we don't find any _HPP, use hardcoded defaults - */ - while (pdev && (ACPI_FAILURE(status))) { - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); - if (!handle) - break; - status = acpi_run_hpp(handle, hpp); - if (!(pdev->bus->parent)) - break; - /* Check if a parent object supports _HPP */ - pdev = pdev->bus->parent->self; - } -} - diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c deleted file mode 100644 index 29180dfe8493..000000000000 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include "pciehp.h" - -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return 0; -} diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 3194d51c6ec9..0a46f549676a 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c @@ -37,10 +37,12 @@ #include <linux/init.h> #include "pci_hotplug.h" +#define SLOT_NAME_SIZE 10 struct slot { u8 number; struct hotplug_slot *hotplug_slot; struct list_head slot_list; + char name[SLOT_NAME_SIZE]; }; static LIST_HEAD(slot_list); @@ -233,12 +235,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } -#define SLOT_NAME_SIZE 10 static void make_slot_name(struct slot *slot) { /* @@ -257,7 +257,6 @@ static int __init init_slots(void) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; - char *name; int retval = -ENOMEM; int i; @@ -266,31 +265,23 @@ static int __init init_slots(void) * with the pci_hotplug subsystem. */ for (i = 0; i < num_slots; ++i) { - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); - hotplug_slot = kmalloc(sizeof(struct hotplug_slot), - GFP_KERNEL); + hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); if (!hotplug_slot) goto error_slot; - memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) goto error_hpslot; - memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; - name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!name) - goto error_info; - hotplug_slot->name = name; - slot->number = i; + hotplug_slot->name = slot->name; hotplug_slot->private = slot; hotplug_slot->release = &release_slot; make_slot_name(slot); @@ -300,16 +291,16 @@ static int __init init_slots(void) * Initialize the slot info structure with some known * good values. */ - info->power_status = get_power_status(slot); - info->attention_status = get_attention_status(slot); - info->latch_status = get_latch_status(slot); - info->adapter_status = get_adapter_status(slot); + get_power_status(hotplug_slot, &info->power_status); + get_attention_status(hotplug_slot, &info->attention_status); + get_latch_status(hotplug_slot, &info->latch_status); + get_adapter_status(hotplug_slot, &info->adapter_status); dbg("registering slot %d\n", i); retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - goto error_name; + goto error_info; } /* add slot to our internal list */ @@ -317,8 +308,6 @@ static int __init init_slots(void) } return 0; -error_name: - kfree(name); error_info: kfree(info); error_hpslot: diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 78943e064b59..b771196a654e 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -84,19 +84,16 @@ struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_ { struct slot *slot; - slot = kmalloc(sizeof (struct slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct slot), GFP_KERNEL); if (!slot) goto error_nomem; - memset(slot, 0, sizeof (struct slot)); - slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); + slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; - memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); - slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info), + slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!slot->hotplug_slot->info) goto error_hpslot; - memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL); if (!slot->hotplug_slot->name) goto error_info; diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index a32ae82e5922..c402da8e78ae 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved. * * This work was based on the 2.4/2.6 kernel development by Dick Reigner. * Work to add BIOS PROM support was completed by Mike Habeck. @@ -230,6 +230,13 @@ static void sn_bus_free_data(struct pci_dev *dev) list_for_each_entry(child, &subordinate_bus->devices, bus_list) sn_bus_free_data(child); } + /* + * Some drivers may use dma accesses during the + * driver remove function. We release the sysdata + * areas after the driver remove functions have + * been called. + */ + sn_bus_store_sysdata(dev); sn_pci_unfixup_slot(dev); } @@ -429,13 +436,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) PCI_DEVFN(slot->device_num + 1, PCI_FUNC(func))); if (dev) { - /* - * Some drivers may use dma accesses during the - * driver remove function. We release the sysdata - * areas after the driver remove functions have - * been called. - */ - sn_bus_store_sysdata(dev); sn_bus_free_data(dev); pci_remove_bus_device(dev); pci_dev_put(dev); diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 7d6f521d02ea..5c70f43908c4 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -33,6 +33,7 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/sched.h> /* signal_pending(), struct timer_list */ +#include <linux/mutex.h> #include "pci_hotplug.h" @@ -45,6 +46,7 @@ extern int shpchp_poll_mode; extern int shpchp_poll_time; extern int shpchp_debug; +extern struct workqueue_struct *shpchp_wq; /*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ #define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) @@ -52,10 +54,8 @@ extern int shpchp_debug; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -#define SLOT_MAGIC 0x67267321 +#define SLOT_NAME_SIZE 10 struct slot { - u32 magic; - struct slot *next; u8 bus; u8 device; u16 status; @@ -70,26 +70,27 @@ struct slot { struct hpc_ops *hpc_ops; struct hotplug_slot *hotplug_slot; struct list_head slot_list; + char name[SLOT_NAME_SIZE]; + struct work_struct work; /* work for button event */ + struct mutex lock; }; struct event_info { u32 event_type; - u8 hp_slot; + struct slot *p_slot; + struct work_struct work; }; struct controller { - struct controller *next; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ + struct mutex cmd_lock; /* command lock */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; - struct pci_bus *pci_bus; - struct event_info event_queue[10]; - struct slot *slot; + struct list_head slot_list; struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ - u8 next_event; u8 bus; u8 device; u8 function; @@ -105,12 +106,6 @@ struct controller { volatile int cmd_busy; }; -struct hotplug_params { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; /* Define AMD SHPC ID */ #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 @@ -180,11 +175,8 @@ struct hotplug_params { /* sysfs functions for the hotplug controller info */ extern void shpchp_create_ctrl_files (struct controller *ctrl); -/* controller functions */ -extern int shpchp_event_start_thread(void); -extern void shpchp_event_stop_thread(void); -extern int shpchp_enable_slot(struct slot *slot); -extern int shpchp_disable_slot(struct slot *slot); +extern int shpchp_sysfs_enable_slot(struct slot *slot); +extern int shpchp_sysfs_disable_slot(struct slot *slot); extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id); extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); @@ -195,16 +187,28 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); extern int shpchp_configure_device(struct slot *p_slot); extern int shpchp_unconfigure_device(struct slot *p_slot); -extern void get_hp_hw_control_from_firmware(struct pci_dev *dev); -extern void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp); -extern int shpchprm_get_physical_slot_number(struct controller *ctrl, - u32 *sun, u8 busnum, u8 devnum); extern void shpchp_remove_ctrl_files(struct controller *ctrl); +extern void cleanup_slots(struct controller *ctrl); +extern void queue_pushbutton_work(void *data); -/* Global variables */ -extern struct controller *shpchp_ctrl_list; +#ifdef CONFIG_ACPI +static inline int get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) +{ + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + return -ENODEV; + return 0; +} +#define get_hp_hw_control_from_firmware(pdev) \ + do { \ + if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ + acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \ + } while (0) +#else +#define get_hp_params_from_firmware(dev, hpp) (-ENODEV) +#define get_hp_hw_control_from_firmware(dev) do { } while (0) +#endif struct ctrl_reg { volatile u32 base_offset; @@ -286,10 +290,6 @@ static inline int slot_paranoia_check (struct slot *slot, const char *function) dbg("%s - slot == NULL", function); return -1; } - if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); - return -1; - } if (!slot->hotplug_slot) { dbg("%s - slot->hotplug_slot == NULL!", function); return -1; @@ -314,44 +314,19 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) { - struct slot *p_slot, *tmp_slot = NULL; + struct slot *slot; if (!ctrl) return NULL; - p_slot = ctrl->slot; - - while (p_slot && (p_slot->device != device)) { - tmp_slot = p_slot; - p_slot = p_slot->next; + list_for_each_entry(slot, &ctrl->slot_list, slot_list) { + if (slot->device == device) + return slot; } - if (p_slot == NULL) { - err("ERROR: shpchp_find_slot device=0x%x\n", device); - p_slot = tmp_slot; - } - - return (p_slot); -} - -static inline int wait_for_ctrl_irq (struct controller *ctrl) -{ - DECLARE_WAITQUEUE(wait, current); - int retval = 0; - - add_wait_queue(&ctrl->queue, &wait); - if (!shpchp_poll_mode) { - /* Sleep for up to 1 second */ - msleep_interruptible(1000); - } else { - /* Sleep for up to 2 seconds */ - msleep_interruptible(2000); - } - remove_wait_queue(&ctrl->queue, &wait); - if (signal_pending(current)) - retval = -EINTR; + err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device); - return retval; + return NULL; } static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot) @@ -427,13 +402,6 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); } -#define SLOT_NAME_SIZE 10 - -static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) -{ - snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number); -} - enum php_ctlr_type { PCI, ISA, diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a2b3f0010cec..3be4d492ccc2 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -32,13 +32,14 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h> +#include <linux/workqueue.h> #include "shpchp.h" /* Global variables */ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; -struct controller *shpchp_ctrl_list; /* = NULL */ +struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" @@ -57,7 +58,6 @@ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); #define SHPC_MODULE_NAME "shpchp" -static int shpc_start_thread (void); static int set_attention_status (struct hotplug_slot *slot, u8 value); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); @@ -94,107 +94,120 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } +static void make_slot_name(struct slot *slot) +{ + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", + slot->bus, slot->number); +} + + + + +static int +shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, + u8 busnum, u8 devnum) +{ + int offset = devnum - ctrl->slot_device_offset; + + dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, + ctrl->slot_num_inc, offset); + *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); + return 0; +} + + + static int init_slots(struct controller *ctrl) { - struct slot *new_slot; - u8 number_of_slots; - u8 slot_device; - u32 slot_number, sun; - int result = -ENOMEM; - - number_of_slots = ctrl->num_slots; - slot_device = ctrl->slot_device_offset; - slot_number = ctrl->first_slot; - - while (number_of_slots) { - new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); - if (!new_slot) + struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *info; + int retval = -ENOMEM; + int i; + u32 sun; + + for (i = 0; i < ctrl->num_slots; i++) { + slot = kzalloc(sizeof(*slot), GFP_KERNEL); + if (!slot) goto error; - memset(new_slot, 0, sizeof(struct slot)); - new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!new_slot->hotplug_slot) + hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); + if (!hotplug_slot) goto error_slot; - memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + slot->hotplug_slot = hotplug_slot; - new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!new_slot->hotplug_slot->info) + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) goto error_hpslot; - memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); - new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!new_slot->hotplug_slot->name) - goto error_info; + hotplug_slot->info = info; + + hotplug_slot->name = slot->name; - new_slot->magic = SLOT_MAGIC; - new_slot->ctrl = ctrl; - new_slot->bus = ctrl->slot_bus; - new_slot->device = slot_device; - new_slot->hpc_ops = ctrl->hpc_ops; + slot->hp_slot = i; + slot->ctrl = ctrl; + slot->bus = ctrl->slot_bus; + slot->device = ctrl->slot_device_offset + i; + slot->hpc_ops = ctrl->hpc_ops; + mutex_init(&slot->lock); if (shpchprm_get_physical_slot_number(ctrl, &sun, - new_slot->bus, new_slot->device)) - goto error_name; + slot->bus, slot->device)) + goto error_info; - new_slot->number = sun; - new_slot->hp_slot = slot_device - ctrl->slot_device_offset; + slot->number = sun; + INIT_WORK(&slot->work, queue_pushbutton_work, slot); /* register this slot with the hotplug pci core */ - new_slot->hotplug_slot->private = new_slot; - new_slot->hotplug_slot->release = &release_slot; - make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); - new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops; - - new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); - new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); - new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); - new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); - - dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus, - new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); - result = pci_hp_register (new_slot->hotplug_slot); - if (result) { - err ("pci_hp_register failed with error %d\n", result); - goto error_name; + hotplug_slot->private = slot; + hotplug_slot->release = &release_slot; + make_slot_name(slot); + hotplug_slot->ops = &shpchp_hotplug_slot_ops; + + get_power_status(hotplug_slot, &info->power_status); + get_attention_status(hotplug_slot, &info->attention_status); + get_latch_status(hotplug_slot, &info->latch_status); + get_adapter_status(hotplug_slot, &info->adapter_status); + + dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " + "slot_device_offset=%x\n", slot->bus, slot->device, + slot->hp_slot, slot->number, ctrl->slot_device_offset); + retval = pci_hp_register(slot->hotplug_slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); + goto error_info; } - new_slot->next = ctrl->slot; - ctrl->slot = new_slot; - - number_of_slots--; - slot_device++; - slot_number += ctrl->slot_num_inc; + list_add(&slot->slot_list, &ctrl->slot_list); } return 0; - -error_name: - kfree(new_slot->hotplug_slot->name); error_info: - kfree(new_slot->hotplug_slot->info); + kfree(info); error_hpslot: - kfree(new_slot->hotplug_slot); + kfree(hotplug_slot); error_slot: - kfree(new_slot); + kfree(slot); error: - return result; + return retval; } -static void cleanup_slots(struct controller *ctrl) +void cleanup_slots(struct controller *ctrl) { - struct slot *old_slot, *next_slot; - - old_slot = ctrl->slot; - ctrl->slot = NULL; - - while (old_slot) { - next_slot = old_slot->next; - pci_hp_deregister(old_slot->hotplug_slot); - old_slot = next_slot; + struct list_head *tmp; + struct list_head *next; + struct slot *slot; + + list_for_each_safe(tmp, next, &ctrl->slot_list) { + slot = list_entry(tmp, struct slot, slot_list); + list_del(&slot->slot_list); + cancel_delayed_work(&slot->work); + flush_scheduled_work(); + flush_workqueue(shpchp_wq); + pci_hp_deregister(slot->hotplug_slot); } } @@ -207,9 +220,12 @@ static int get_ctlr_slot_config(struct controller *ctrl) int rc; int flags; - rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); + rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, + &first_device_num, &physical_slot_num, + &updown, &flags); if (rc) { - err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); + err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", + __FUNCTION__, ctrl->bus, ctrl->device); return -1; } @@ -218,19 +234,19 @@ static int get_ctlr_slot_config(struct controller *ctrl) ctrl->first_slot = physical_slot_num; ctrl->slot_num_inc = updown; /* either -1 or 1 */ - dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", - __FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device); + dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d " + "(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num, + physical_slot_num, updown, ctrl->bus, ctrl->device); return 0; } - /* * set_attention_status - Turns the Amber LED for a slot on, off or blink */ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -240,29 +256,27 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) return 0; } - static int enable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return shpchp_enable_slot(slot); + return shpchp_sysfs_enable_slot(slot); } - static int disable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return shpchp_disable_slot(slot); + return shpchp_sysfs_disable_slot(slot); } static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -276,7 +290,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -290,7 +304,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -304,7 +318,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -318,7 +332,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -330,11 +344,11 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + retval = slot->hpc_ops->get_max_bus_speed(slot, value); if (retval < 0) *value = PCI_SPEED_UNKNOWN; @@ -344,11 +358,11 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + retval = slot->hpc_ops->get_cur_bus_speed(slot, value); if (retval < 0) *value = PCI_SPEED_UNKNOWN; @@ -372,61 +386,54 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int rc; struct controller *ctrl; struct slot *t_slot; - int first_device_num; /* first PCI device number supported by this SHPC */ - int num_ctlr_slots; /* number of slots supported by this SHPC */ + int first_device_num; /* first PCI device number */ + int num_ctlr_slots; /* number of slots implemented */ if (!is_shpc_capable(pdev)) return -ENODEV; - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; } - memset(ctrl, 0, sizeof(struct controller)); + INIT_LIST_HEAD(&ctrl->slot_list); rc = shpc_init(ctrl, pdev); if (rc) { - dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME); + dbg("%s: controller initialization failed\n", + SHPC_MODULE_NAME); goto err_out_free_ctrl; } pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); - if (!ctrl->pci_bus) { - err("out of memory\n"); - rc = -ENOMEM; - goto err_out_unmap_mmio_region; - } - - memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; ctrl->slot_bus = pdev->subordinate->number; - ctrl->device = PCI_SLOT(pdev->devfn); ctrl->function = PCI_FUNC(pdev->devfn); - dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq); + + dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", + ctrl->bus, ctrl->device, ctrl->function, pdev->irq); /* - * Save configuration headers for this and subordinate PCI buses + * Save configuration headers for this and subordinate PCI buses */ - rc = get_ctlr_slot_config(ctrl); if (rc) { err(msg_initialization_err, rc); - goto err_out_free_ctrl_bus; + goto err_out_release_ctlr; } first_device_num = ctrl->slot_device_offset; num_ctlr_slots = ctrl->num_slots; ctrl->add_support = 1; - + /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { err(msg_initialization_err, 6); - goto err_out_free_ctrl_slot; + goto err_out_release_ctlr; } /* Now hpc_functions (slot->hpc_ops->functions) are ready */ @@ -437,30 +444,16 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot); if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) { - err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n"); + err(SHPC_MODULE_NAME ": Can't get current bus speed. " + "Set to 33MHz PCI.\n"); ctrl->speed = PCI_SPEED_33MHz; } - /* Finish setting up the hot plug ctrl device */ - ctrl->next_event = 0; - - if (!shpchp_ctrl_list) { - shpchp_ctrl_list = ctrl; - ctrl->next = NULL; - } else { - ctrl->next = shpchp_ctrl_list; - shpchp_ctrl_list = ctrl; - } - shpchp_create_ctrl_files(ctrl); return 0; -err_out_free_ctrl_slot: - cleanup_slots(ctrl); -err_out_free_ctrl_bus: - kfree(ctrl->pci_bus); -err_out_unmap_mmio_region: +err_out_release_ctlr: ctrl->hpc_ops->release_ctlr(ctrl); err_out_free_ctrl: kfree(ctrl); @@ -468,74 +461,28 @@ err_out_none: return -ENODEV; } - -static int shpc_start_thread(void) -{ - int retval = 0; - - dbg("Initialize + Start the notification/polling mechanism \n"); - - retval = shpchp_event_start_thread(); - if (retval) { - dbg("shpchp_event_start_thread() failed\n"); - return retval; - } - - return retval; -} - -static void __exit unload_shpchpd(void) +static void shpc_remove(struct pci_dev *dev) { - struct controller *ctrl; - struct controller *tctrl; - - ctrl = shpchp_ctrl_list; - - while (ctrl) { - shpchp_remove_ctrl_files(ctrl); - cleanup_slots(ctrl); - - kfree (ctrl->pci_bus); - ctrl->hpc_ops->release_ctlr(ctrl); - - tctrl = ctrl; - ctrl = ctrl->next; - - kfree(tctrl); - } - - /* Stop the notification mechanism */ - shpchp_event_stop_thread(); + struct controller *ctrl = pci_get_drvdata(dev); + shpchp_remove_ctrl_files(ctrl); + ctrl->hpc_ops->release_ctlr(ctrl); + kfree(ctrl); } - static struct pci_device_id shpcd_pci_tbl[] = { - { - .class = ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), - .class_mask = ~0, - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - + {PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0)}, { /* end: all zeroes */ } }; - MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl); - - static struct pci_driver shpc_driver = { .name = SHPC_MODULE_NAME, .id_table = shpcd_pci_tbl, .probe = shpc_probe, - /* remove: shpc_remove_one, */ + .remove = shpc_remove, }; - - static int __init shpcd_init(void) { int retval = 0; @@ -544,17 +491,15 @@ static int __init shpcd_init(void) shpchp_poll_mode = 1; #endif - retval = shpc_start_thread(); - if (retval) - goto error_hpc_init; + shpchp_wq = create_singlethread_workqueue("shpchpd"); + if (!shpchp_wq) + return -ENOMEM; retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - -error_hpc_init: if (retval) { - shpchp_event_stop_thread(); + destroy_workqueue(shpchp_wq); } return retval; } @@ -562,10 +507,8 @@ error_hpc_init: static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); - unload_shpchpd(); - pci_unregister_driver(&shpc_driver); - + destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 643252d9bf3b..4e6381481c55 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -32,65 +32,50 @@ #include <linux/types.h> #include <linux/smp_lock.h> #include <linux/pci.h> +#include <linux/workqueue.h> #include "../pci.h" #include "shpchp.h" -static void interrupt_event_handler(struct controller *ctrl); +static void interrupt_event_handler(void *data); +static int shpchp_enable_slot(struct slot *p_slot); +static int shpchp_disable_slot(struct slot *p_slot); -static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ -static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ -static int event_finished; -static unsigned long pushbutton_pending; /* = 0 */ +static int queue_interrupt_event(struct slot *p_slot, u32 event_type) +{ + struct event_info *info; + + info = kmalloc(sizeof(*info), GFP_ATOMIC); + if (!info) + return -ENOMEM; + + info->event_type = event_type; + info->p_slot = p_slot; + INIT_WORK(&info->work, interrupt_event_handler, info); + + schedule_work(&info->work); + + return 0; +} u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Attention Button Change */ dbg("shpchp: Attention button interrupt received.\n"); - /* This is the structure that tells the worker thread what to do */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); - p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; /* * Button pressed - See if need to TAKE ACTION!!! */ info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_BUTTON_PRESS; - - if ((p_slot->state == BLINKINGON_STATE) - || (p_slot->state == BLINKINGOFF_STATE)) { - /* Cancel if we are still blinking; this means that we press the - * attention again before the 5 sec. limit expires to cancel hot-add - * or hot-remove - */ - taskInfo->event_type = INT_BUTTON_CANCEL; - info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); - } else if ((p_slot->state == POWERON_STATE) - || (p_slot->state == POWEROFF_STATE)) { - /* Ignore if the slot is on power-on or power-off state; this - * means that the previous attention button action to hot-add or - * hot-remove is undergoing - */ - taskInfo->event_type = INT_BUTTON_IGNORE; - info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); - } + event_type = INT_BUTTON_PRESS; - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); return 0; @@ -100,21 +85,12 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Switch Change */ dbg("shpchp: Switch interrupt received.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -126,9 +102,9 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) * Switch opened */ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_SWITCH_OPEN; + event_type = INT_SWITCH_OPEN; if (p_slot->pwr_save && p_slot->presence_save) { - taskInfo->event_type = INT_POWER_FAULT; + event_type = INT_POWER_FAULT; err("Surprise Removal of card\n"); } } else { @@ -136,34 +112,23 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) * Switch closed */ info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_SWITCH_CLOSE; + event_type = INT_SWITCH_CLOSE; } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); - return rc; + return 1; } u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - /*u8 temp_byte;*/ - struct event_info *taskInfo; + u32 event_type; /* Presence Change */ dbg("shpchp: Presence/Notify input change.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); /* @@ -175,39 +140,29 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) * Card Present */ info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_PRESENCE_ON; + event_type = INT_PRESENCE_ON; } else { /* * Not Present */ info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_PRESENCE_OFF; + event_type = INT_PRESENCE_OFF; } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); - return rc; + return 1; } u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - struct event_info *taskInfo; + u32 event_type; /* Power fault */ dbg("shpchp: Power fault interrupt received.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { @@ -216,21 +171,21 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) */ info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); p_slot->status = 0x00; - taskInfo->event_type = INT_POWER_FAULT_CLEAR; + event_type = INT_POWER_FAULT_CLEAR; } else { /* * Power fault */ info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_POWER_FAULT; + event_type = INT_POWER_FAULT; /* set power fault status for this board */ p_slot->status = 0xFF; info("power fault bit %x set\n", hp_slot); } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ - return rc; + queue_interrupt_event(p_slot, event_type); + + return 1; } /* The following routines constitute the bulk of the @@ -242,21 +197,11 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, int rc = 0; dbg("%s: change to speed %d\n", __FUNCTION__, speed); - down(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + err("%s: Issue of set bus speed mode command failed\n", + __FUNCTION__); return WRONG_BUS_FREQUENCY; } - - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - up(&ctrl->crit_sect); return rc; } @@ -265,33 +210,26 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, enum pci_bus_speed msp) { int rc = 0; - - if (flag != 0) { /* Other slots on the same bus are occupied */ - if ( asp < bsp ) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp); - return WRONG_BUS_FREQUENCY; + + /* + * If other slots on the same bus are occupied, we cannot + * change the bus speed. + */ + if (flag) { + if (asp < bsp) { + err("%s: speed of bus %x and adapter %x mismatch\n", + __FUNCTION__, bsp, asp); + rc = WRONG_BUS_FREQUENCY; } + return rc; + } + + if (asp < msp) { + if (bsp != asp) + rc = change_bus_speed(ctrl, pslot, asp); } else { - /* Other slots on the same bus are empty */ - if (msp == bsp) { - /* if adapter_speed >= bus_speed, do nothing */ - if (asp < bsp) { - /* - * Try to lower bus speed to accommodate the adapter if other slots - * on the same controller are empty - */ - if ((rc = change_bus_speed(ctrl, pslot, asp))) - return rc; - } - } else { - if (asp < msp) { - if ((rc = change_bus_speed(ctrl, pslot, asp))) - return rc; - } else { - if ((rc = change_bus_speed(ctrl, pslot, msp))) - return rc; - } - } + if (bsp != msp) + rc = change_bus_speed(ctrl, pslot, msp); } return rc; } @@ -308,8 +246,7 @@ static int board_added(struct slot *p_slot) u8 hp_slot; u8 slots_not_empty = 0; int rc = 0; - enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; - u8 pi, mode; + enum pci_bus_speed asp, bsp, msp; struct controller *ctrl = p_slot->ctrl; hp_slot = p_slot->device - ctrl->slot_device_offset; @@ -318,187 +255,68 @@ static int board_added(struct slot *p_slot) __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot); - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - /* Power on slot without connecting to bus */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { err("%s: Failed to power on slot\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); return -1; } - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return -1; - } - - if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { if (slots_not_empty) return WRONG_BUS_FREQUENCY; if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); return rc; } - - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); - return rc; - } } - rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); - /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ - /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ - /* 0xd = PCI-X 133 Mhz 533 */ - /* This encoding is different from the one used in cur_bus_speed & */ - /* max_bus_speed */ - - if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { - err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); + if (rc) { + err("%s: Can't get adapter speed or bus mode mismatch\n", + __FUNCTION__); return WRONG_BUS_FREQUENCY; } - rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); - if (rc || bus_speed == PCI_SPEED_UNKNOWN) { + rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); + if (rc) { err("%s: Can't get bus operation speed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } - rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); - if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { + rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); + if (rc) { err("%s: Can't get max bus operation speed\n", __FUNCTION__); - max_bus_speed = bus_speed; - } - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - - if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { - err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); - pi = 1; + msp = bsp; } /* Check if there are other slots or devices on the same bus */ if (!list_empty(&ctrl->pci_dev->subordinate->devices)) slots_not_empty = 1; - dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, - slots_not_empty, pi); - dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", - adapter_speed, bus_speed, max_bus_speed); - - if (pi == 2) { - dbg("%s: In PI = %d\n", __FUNCTION__, pi); - if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) { - err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__); - mode = 0; - } + dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, " + "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp, + bsp, msp); - switch (adapter_speed) { - case PCI_SPEED_133MHz_PCIX_533: - case PCI_SPEED_133MHz_PCIX_266: - if ((bus_speed != adapter_speed) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - break; - case PCI_SPEED_133MHz_PCIX_ECC: - case PCI_SPEED_133MHz_PCIX: - if (mode) { /* Bus - Mode 1 ECC */ - if ((bus_speed != 0x7) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } else { - if ((bus_speed != 0x4) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } - break; - case PCI_SPEED_66MHz_PCIX_ECC: - case PCI_SPEED_66MHz_PCIX: - if (mode) { /* Bus - Mode 1 ECC */ - if ((bus_speed != 0x5) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } else { - if ((bus_speed != 0x2) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } - break; - case PCI_SPEED_66MHz: - if ((bus_speed != 0x1) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - break; - case PCI_SPEED_33MHz: - if (bus_speed > 0x0) { - if (slots_not_empty == 0) { - if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed))) - return rc; - } else { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - } - break; - default: - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - } else { - /* If adpater_speed == bus_speed, nothing to do here */ - dbg("%s: In PI = %d\n", __FUNCTION__, pi); - if ((adapter_speed != bus_speed) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } + rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); + if (rc) + return rc; - down(&ctrl->crit_sect); /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); return rc; } - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); - return rc; - } - - up(&ctrl->crit_sect); - /* Wait for ~1 second */ - wait_for_ctrl_irq (ctrl); + msleep(1000); dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); /* Check for a power fault */ @@ -520,40 +338,18 @@ static int board_added(struct slot *p_slot) p_slot->is_a_board = 0x01; p_slot->pwr_save = 1; - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_on(p_slot); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return 0; err_exit: - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return rc; - } - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); return rc; } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return(rc); } @@ -580,37 +376,19 @@ static int remove_board(struct slot *p_slot) if (p_slot->is_a_board) p_slot->status = 0x01; - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); return rc; } - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return rc; - } rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); if (rc) { err("%s: Issue of Set Attention command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); return rc; } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - p_slot->pwr_save = 0; p_slot->is_a_board = 0; @@ -618,13 +396,10 @@ static int remove_board(struct slot *p_slot) } -static void pushbutton_helper_thread (unsigned long data) -{ - pushbutton_pending = data; - - up(&event_semaphore); -} - +struct pushbutton_work_info { + struct slot *p_slot; + struct work_struct work; +}; /** * shpchp_pushbutton_thread @@ -633,96 +408,63 @@ static void pushbutton_helper_thread (unsigned long data) * Handles all pending events and exits. * */ -static void shpchp_pushbutton_thread (unsigned long slot) +static void shpchp_pushbutton_thread(void *data) { - struct slot *p_slot = (struct slot *) slot; - u8 getstatus; - - pushbutton_pending = 0; - - if (!p_slot) { - dbg("%s: Error! slot NULL\n", __FUNCTION__); - return; - } - - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - p_slot->state = POWEROFF_STATE; + struct pushbutton_work_info *info = data; + struct slot *p_slot = info->p_slot; + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case POWEROFF_STATE: + mutex_unlock(&p_slot->lock); shpchp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; - } else { - p_slot->state = POWERON_STATE; - - if (shpchp_enable_slot(p_slot)) { - /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); - + break; + case POWERON_STATE: + mutex_unlock(&p_slot->lock); + if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); - - /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); - } + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; + break; + default: + break; } + mutex_unlock(&p_slot->lock); - return; -} - - -/* this is the main worker thread */ -static int event_thread(void* data) -{ - struct controller *ctrl; - lock_kernel(); - daemonize("shpchpd_event"); - unlock_kernel(); - - while (1) { - dbg("!!!!event_thread sleeping\n"); - down_interruptible (&event_semaphore); - dbg("event_thread woken finished = %d\n", event_finished); - if (event_finished || signal_pending(current)) - break; - /* Do stuff here */ - if (pushbutton_pending) - shpchp_pushbutton_thread(pushbutton_pending); - else - for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next) - interrupt_event_handler(ctrl); - } - dbg("event_thread signals exit\n"); - up(&event_exit); - return 0; + kfree(info); } -int shpchp_event_start_thread (void) +void queue_pushbutton_work(void *data) { - int pid; + struct slot *p_slot = data; + struct pushbutton_work_info *info; - /* initialize our semaphores */ - init_MUTEX_LOCKED(&event_exit); - event_finished=0; - - init_MUTEX_LOCKED(&event_semaphore); - pid = kernel_thread(event_thread, NULL, 0); - - if (pid < 0) { - err ("Can't start up our event thread\n"); - return -1; + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + err("%s: Cannot allocate memory\n", __FUNCTION__); + return; } - return 0; -} - + info->p_slot = p_slot; + INIT_WORK(&info->work, shpchp_pushbutton_thread, info); -void shpchp_event_stop_thread (void) -{ - event_finished = 1; - up(&event_semaphore); - down(&event_exit); + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + p_slot->state = POWEROFF_STATE; + break; + case BLINKINGON_STATE: + p_slot->state = POWERON_STATE; + break; + default: + goto out; + } + queue_work(shpchp_wq, &info->work); + out: + mutex_unlock(&p_slot->lock); } - static int update_slot_info (struct slot *slot) { struct hotplug_slot_info *info; @@ -742,149 +484,110 @@ static int update_slot_info (struct slot *slot) return result; } -static void interrupt_event_handler(struct controller *ctrl) +/* + * Note: This function must be called with slot->lock held + */ +static void handle_button_press_event(struct slot *p_slot) { - int loop = 0; - int change = 1; - u8 hp_slot; u8 getstatus; - struct slot *p_slot; - while (change) { - change = 0; - - for (loop = 0; loop < 10; loop++) { - if (ctrl->event_queue[loop].event_type != 0) { - dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, - ctrl->event_queue[loop].event_type); - hp_slot = ctrl->event_queue[loop].hp_slot; - - p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - - if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { - dbg("%s: button cancel\n", __FUNCTION__); - del_timer(&p_slot->task_event); - - switch (p_slot->state) { - case BLINKINGOFF_STATE: - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - p_slot->hpc_ops->green_led_on(p_slot); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - break; - case BLINKINGON_STATE: - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - p_slot->hpc_ops->green_led_off(p_slot); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - - break; - default: - warn("Not a valid state\n"); - return; - } - info(msg_button_cancel, p_slot->number); - p_slot->state = STATIC_STATE; - } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { - /* Button Pressed (No action on 1st press...) */ - dbg("%s: Button pressed\n", __FUNCTION__); - - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - /* slot is on */ - dbg("%s: slot is on\n", __FUNCTION__); - p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->number); - } else { - /* slot is off */ - dbg("%s: slot is off\n", __FUNCTION__); - p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->number); - } - - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - /* blink green LED and turn off amber */ - p_slot->hpc_ops->green_led_blink(p_slot); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - - init_timer(&p_slot->task_event); - p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ - p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; - p_slot->task_event.data = (unsigned long) p_slot; - - dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot); - add_timer(&p_slot->task_event); - } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { - /***********POWER FAULT********************/ - dbg("%s: power fault\n", __FUNCTION__); - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - p_slot->hpc_ops->set_attention_status(p_slot, 1); - - p_slot->hpc_ops->green_led_off(p_slot); - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - } else { - /* refresh notification */ - if (p_slot) - update_slot_info(p_slot); - } - - ctrl->event_queue[loop].event_type = 0; - - change = 1; - } - } /* End of FOR loop */ + switch (p_slot->state) { + case STATIC_STATE: + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + p_slot->state = BLINKINGOFF_STATE; + info(msg_button_off, p_slot->number); + } else { + p_slot->state = BLINKINGON_STATE; + info(msg_button_on, p_slot->number); + } + /* blink green LED and turn off amber */ + p_slot->hpc_ops->green_led_blink(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + schedule_delayed_work(&p_slot->work, 5*HZ); + break; + case BLINKINGOFF_STATE: + case BLINKINGON_STATE: + /* + * Cancel if we are still blinking; this means that we + * press the attention again before the 5 sec. limit + * expires to cancel hot-add or hot-remove + */ + info("Button cancel on Slot(%s)\n", p_slot->name); + dbg("%s: button cancel\n", __FUNCTION__); + cancel_delayed_work(&p_slot->work); + if (p_slot->state == BLINKINGOFF_STATE) + p_slot->hpc_ops->green_led_on(p_slot); + else + p_slot->hpc_ops->green_led_off(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + info(msg_button_cancel, p_slot->number); + p_slot->state = STATIC_STATE; + break; + case POWEROFF_STATE: + case POWERON_STATE: + /* + * Ignore if the slot is on power-on or power-off state; + * this means that the previous attention button action + * to hot-add or hot-remove is undergoing + */ + info("Button ignore on Slot(%s)\n", p_slot->name); + update_slot_info(p_slot); + break; + default: + warn("Not a valid state\n"); + break; } +} + +static void interrupt_event_handler(void *data) +{ + struct event_info *info = data; + struct slot *p_slot = info->p_slot; + + mutex_lock(&p_slot->lock); + switch (info->event_type) { + case INT_BUTTON_PRESS: + handle_button_press_event(p_slot); + break; + case INT_POWER_FAULT: + dbg("%s: power fault\n", __FUNCTION__); + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); + break; + default: + update_slot_info(p_slot); + break; + } + mutex_unlock(&p_slot->lock); - return; + kfree(info); } -int shpchp_enable_slot (struct slot *p_slot) +static int shpchp_enable_slot (struct slot *p_slot) { u8 getstatus = 0; - int rc; + int rc, retval = -ENODEV; /* Check to see if (latch closed, card present, power off) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - up(&p_slot->ctrl->crit_sect); p_slot->is_a_board = 1; @@ -899,56 +602,119 @@ int shpchp_enable_slot (struct slot *p_slot) && p_slot->ctrl->num_slots == 1) { /* handle amd pogo errata; this must be done before enable */ amd_pogo_errata_save_misc_reg(p_slot); - rc = board_added(p_slot); + retval = board_added(p_slot); /* handle amd pogo errata; this must be done after enable */ amd_pogo_errata_restore_misc_reg(p_slot); } else - rc = board_added(p_slot); + retval = board_added(p_slot); - if (rc) { + if (retval) { p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); } update_slot_info(p_slot); - return rc; + out: + mutex_unlock(&p_slot->ctrl->crit_sect); + return retval; } -int shpchp_disable_slot (struct slot *p_slot) +static int shpchp_disable_slot (struct slot *p_slot) { u8 getstatus = 0; - int ret = 0; + int rc, retval = -ENODEV; if (!p_slot->ctrl) return -ENODEV; /* Check to see if (latch closed, card present, power on) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); - ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); - if (ret || !getstatus) { + rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (ret || getstatus) { + rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (ret || !getstatus) { + rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (rc || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - up(&p_slot->ctrl->crit_sect); - ret = remove_board(p_slot); + retval = remove_board(p_slot); update_slot_info(p_slot); - return ret; + out: + mutex_unlock(&p_slot->ctrl->crit_sect); + return retval; } +int shpchp_sysfs_enable_slot(struct slot *p_slot) +{ + int retval = -ENODEV; + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGON_STATE: + cancel_delayed_work(&p_slot->work); + case STATIC_STATE: + p_slot->state = POWERON_STATE; + mutex_unlock(&p_slot->lock); + retval = shpchp_enable_slot(p_slot); + mutex_lock(&p_slot->lock); + p_slot->state = STATIC_STATE; + break; + case POWERON_STATE: + info("Slot %s is already in powering on state\n", + p_slot->name); + break; + case BLINKINGOFF_STATE: + case POWEROFF_STATE: + info("Already enabled on slot %s\n", p_slot->name); + break; + default: + err("Not a valid state on slot %s\n", p_slot->name); + break; + } + mutex_unlock(&p_slot->lock); + + return retval; +} + +int shpchp_sysfs_disable_slot(struct slot *p_slot) +{ + int retval = -ENODEV; + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + cancel_delayed_work(&p_slot->work); + case STATIC_STATE: + p_slot->state = POWEROFF_STATE; + mutex_unlock(&p_slot->lock); + retval = shpchp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); + p_slot->state = STATIC_STATE; + break; + case POWEROFF_STATE: + info("Slot %s is already in powering off state\n", + p_slot->name); + break; + case BLINKINGON_STATE: + case POWERON_STATE: + info("Already disabled on slot %s\n", p_slot->name); + break; + default: + err("Not a valid state on slot %s\n", p_slot->name); + break; + } + mutex_unlock(&p_slot->lock); + + return retval; +} diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index b4226ff3a854..66123cf4deaa 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -82,31 +82,6 @@ #define SLOT_100MHZ_PCIX_533 0x0f000000 #define SLOT_133MHZ_PCIX_533 0xf0000000 - -/* Secondary Bus Configuration Register */ -/* For PI = 1, Bits 0 to 2 have been encoded as follows to show current bus speed/mode */ -#define PCI_33MHZ 0x0 -#define PCI_66MHZ 0x1 -#define PCIX_66MHZ 0x2 -#define PCIX_100MHZ 0x3 -#define PCIX_133MHZ 0x4 - -/* For PI = 2, Bits 0 to 3 have been encoded as follows to show current bus speed/mode */ -#define PCI_33MHZ 0x0 -#define PCI_66MHZ 0x1 -#define PCIX_66MHZ 0x2 -#define PCIX_100MHZ 0x3 -#define PCIX_133MHZ 0x4 -#define PCIX_66MHZ_ECC 0x5 -#define PCIX_100MHZ_ECC 0x6 -#define PCIX_133MHZ_ECC 0x7 -#define PCIX_66MHZ_266 0x9 -#define PCIX_100MHZ_266 0xa -#define PCIX_133MHZ_266 0xb -#define PCIX_66MHZ_533 0x11 -#define PCIX_100MHZ_533 0x12 -#define PCIX_133MHZ_533 0x13 - /* Slot Configuration */ #define SLOT_NUM 0x0000001F #define FIRST_DEV_NUM 0x00001F00 @@ -231,6 +206,7 @@ static spinlock_t list_lock; static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); +static int hpc_check_cmd_status(struct controller *ctrl); /* This is the interrupt polling timeout function. */ static void int_poll_timeout(unsigned long lphp_ctlr) @@ -303,10 +279,13 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) int i; DBG_ENTER_ROUTINE - + + mutex_lock(&slot->ctrl->cmd_lock); + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; + retval = -EINVAL; + goto out; } for (i = 0; i < 10; i++) { @@ -323,7 +302,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) if (cmd_status & 0x1) { /* After 1 sec and and the controller is still busy */ err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); - return -1; + retval = -EBUSY; + goto out; } ++t_slot; @@ -340,6 +320,17 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) * Wait for command completion. */ retval = shpc_wait_cmd(slot->ctrl); + if (retval) + goto out; + + cmd_status = hpc_check_cmd_status(slot->ctrl); + if (cmd_status) { + err("%s: Failed to issued command 0x%x (error code = %d)\n", + __FUNCTION__, cmd, cmd_status); + retval = -EIO; + } + out: + mutex_unlock(&slot->ctrl->cmd_lock); DBG_LEAVE_ROUTINE return retval; @@ -532,81 +523,41 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u32 slot_reg; - u16 slot_status, sec_bus_status; - u8 m66_cap, pcix_cap, pi; int retval = 0; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot); + u8 pcix_cap = (slot_reg >> 12) & 7; + u8 m66_cap = (slot_reg >> 9) & 1; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - - pi = readb(php_ctlr->creg + PROG_INTERFACE); - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); - dbg("%s: pi = %d, slot_reg = %x\n", __FUNCTION__, pi, slot_reg); - slot_status = (u16) slot_reg; - dbg("%s: slot_status = %x\n", __FUNCTION__, slot_status); - sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); - - pcix_cap = (u8) ((slot_status & 0x3000) >> 12); - dbg("%s: pcix_cap = %x\n", __FUNCTION__, pcix_cap); - m66_cap = (u8) ((slot_status & 0x0200) >> 9); - dbg("%s: m66_cap = %x\n", __FUNCTION__, m66_cap); - + dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", + __FUNCTION__, slot_reg, pcix_cap, m66_cap); - if (pi == 2) { - switch (pcix_cap) { - case 0: - *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; - break; - case 1: - *value = PCI_SPEED_66MHz_PCIX; - break; - case 3: - *value = PCI_SPEED_133MHz_PCIX; - break; - case 4: - *value = PCI_SPEED_133MHz_PCIX_266; - break; - case 5: - *value = PCI_SPEED_133MHz_PCIX_533; - break; - case 2: /* Reserved */ - default: - *value = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - break; - } - } else { - switch (pcix_cap) { - case 0: - *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; - break; - case 1: - *value = PCI_SPEED_66MHz_PCIX; - break; - case 3: - *value = PCI_SPEED_133MHz_PCIX; - break; - case 2: /* Reserved */ - default: - *value = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - break; - } + switch (pcix_cap) { + case 0x0: + *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; + break; + case 0x1: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 0x3: + *value = PCI_SPEED_133MHz_PCIX; + break; + case 0x4: + *value = PCI_SPEED_133MHz_PCIX_266; + break; + case 0x5: + *value = PCI_SPEED_133MHz_PCIX_533; + break; + case 0x2: + default: + *value = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + break; } dbg("Adapter speed = %d\n", *value); - DBG_LEAVE_ROUTINE return retval; } @@ -797,6 +748,7 @@ static void hpc_release_ctlr(struct controller *ctrl) { struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *p, *p_prev; + int i; DBG_ENTER_ROUTINE @@ -805,6 +757,14 @@ static void hpc_release_ctlr(struct controller *ctrl) return ; } + /* + * Mask all slot event interrupts + */ + for (i = 0; i < ctrl->num_slots; i++) + writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i)); + + cleanup_slots(ctrl); + if (shpchp_poll_mode) { del_timer(&php_ctlr->int_poll_timer); } else { @@ -814,6 +774,7 @@ static void hpc_release_ctlr(struct controller *ctrl) pci_disable_msi(php_ctlr->pci_dev); } } + if (php_ctlr->pci_dev) { iounmap(php_ctlr->creg); release_mem_region(ctrl->mmio_base, ctrl->mmio_size); @@ -939,98 +900,66 @@ static int hpc_slot_disable(struct slot * slot) static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) { - u8 slot_cmd; - u8 pi; - int retval = 0; + int retval; struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + u8 pi, cmd; DBG_ENTER_ROUTINE - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } pi = readb(php_ctlr->creg + PROG_INTERFACE); - - if (pi == 1) { - switch (value) { - case 0: - slot_cmd = SETA_PCI_33MHZ; - break; - case 1: - slot_cmd = SETA_PCI_66MHZ; - break; - case 2: - slot_cmd = SETA_PCIX_66MHZ; - break; - case 3: - slot_cmd = SETA_PCIX_100MHZ; - break; - case 4: - slot_cmd = SETA_PCIX_133MHZ; - break; - default: - slot_cmd = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - return retval; - } - } else { - switch (value) { - case 0: - slot_cmd = SETB_PCI_33MHZ; - break; - case 1: - slot_cmd = SETB_PCI_66MHZ; - break; - case 2: - slot_cmd = SETB_PCIX_66MHZ_PM; - break; - case 3: - slot_cmd = SETB_PCIX_100MHZ_PM; - break; - case 4: - slot_cmd = SETB_PCIX_133MHZ_PM; - break; - case 5: - slot_cmd = SETB_PCIX_66MHZ_EM; - break; - case 6: - slot_cmd = SETB_PCIX_100MHZ_EM; - break; - case 7: - slot_cmd = SETB_PCIX_133MHZ_EM; - break; - case 8: - slot_cmd = SETB_PCIX_66MHZ_266; - break; - case 0x9: - slot_cmd = SETB_PCIX_100MHZ_266; - break; - case 0xa: - slot_cmd = SETB_PCIX_133MHZ_266; - break; - case 0xb: - slot_cmd = SETB_PCIX_66MHZ_533; - break; - case 0xc: - slot_cmd = SETB_PCIX_100MHZ_533; - break; - case 0xd: - slot_cmd = SETB_PCIX_133MHZ_533; - break; - default: - slot_cmd = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - return retval; - } + if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) + return -EINVAL; + switch (value) { + case PCI_SPEED_33MHz: + cmd = SETA_PCI_33MHZ; + break; + case PCI_SPEED_66MHz: + cmd = SETA_PCI_66MHZ; + break; + case PCI_SPEED_66MHz_PCIX: + cmd = SETA_PCIX_66MHZ; + break; + case PCI_SPEED_100MHz_PCIX: + cmd = SETA_PCIX_100MHZ; + break; + case PCI_SPEED_133MHz_PCIX: + cmd = SETA_PCIX_133MHZ; + break; + case PCI_SPEED_66MHz_PCIX_ECC: + cmd = SETB_PCIX_66MHZ_EM; + break; + case PCI_SPEED_100MHz_PCIX_ECC: + cmd = SETB_PCIX_100MHZ_EM; + break; + case PCI_SPEED_133MHz_PCIX_ECC: + cmd = SETB_PCIX_133MHZ_EM; + break; + case PCI_SPEED_66MHz_PCIX_266: + cmd = SETB_PCIX_66MHZ_266; + break; + case PCI_SPEED_100MHz_PCIX_266: + cmd = SETB_PCIX_100MHZ_266; + break; + case PCI_SPEED_133MHz_PCIX_266: + cmd = SETB_PCIX_133MHZ_266; + break; + case PCI_SPEED_66MHz_PCIX_533: + cmd = SETB_PCIX_66MHZ_533; + break; + case PCI_SPEED_100MHz_PCIX_533: + cmd = SETB_PCIX_100MHZ_533; + break; + case PCI_SPEED_133MHz_PCIX_533: + cmd = SETB_PCIX_133MHZ_533; + break; + default: + return -EINVAL; } - retval = shpc_write_cmd(slot, 0, slot_cmd); - if (retval) { + + retval = shpc_write_cmd(slot, 0, cmd); + if (retval) err("%s: Write command failed!\n", __FUNCTION__); - return -1; - } DBG_LEAVE_ROUTINE return retval; @@ -1093,14 +1022,8 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) wake_up_interruptible(&ctrl->queue); } - if ((intr_loc = (intr_loc >> 1)) == 0) { - /* Unmask Global Interrupt Mask */ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - temp_dword &= 0xfffffffe; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); - - return IRQ_NONE; - } + if ((intr_loc = (intr_loc >> 1)) == 0) + goto out; for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { /* To find out which slot has interrupt pending */ @@ -1130,6 +1053,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } } + out: if (!shpchp_poll_mode) { /* Unmask Global Interrupt Mask */ temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); @@ -1142,64 +1066,43 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) { + int retval = 0; struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - int retval = 0; - u8 pi; - u32 slot_avail1, slot_avail2; + u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); + u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); + u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - - pi = readb(php_ctlr->creg + PROG_INTERFACE); - slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); - slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); - if (pi == 2) { if (slot_avail2 & SLOT_133MHZ_PCIX_533) - bus_speed = PCIX_133MHZ_533; + bus_speed = PCI_SPEED_133MHz_PCIX_533; else if (slot_avail2 & SLOT_100MHZ_PCIX_533) - bus_speed = PCIX_100MHZ_533; + bus_speed = PCI_SPEED_100MHz_PCIX_533; else if (slot_avail2 & SLOT_66MHZ_PCIX_533) - bus_speed = PCIX_66MHZ_533; + bus_speed = PCI_SPEED_66MHz_PCIX_533; else if (slot_avail2 & SLOT_133MHZ_PCIX_266) - bus_speed = PCIX_133MHZ_266; + bus_speed = PCI_SPEED_133MHz_PCIX_266; else if (slot_avail2 & SLOT_100MHZ_PCIX_266) - bus_speed = PCIX_100MHZ_266; + bus_speed = PCI_SPEED_100MHz_PCIX_266; else if (slot_avail2 & SLOT_66MHZ_PCIX_266) - bus_speed = PCIX_66MHZ_266; - else if (slot_avail1 & SLOT_133MHZ_PCIX) - bus_speed = PCIX_133MHZ; - else if (slot_avail1 & SLOT_100MHZ_PCIX) - bus_speed = PCIX_100MHZ; - else if (slot_avail1 & SLOT_66MHZ_PCIX) - bus_speed = PCIX_66MHZ; - else if (slot_avail2 & SLOT_66MHZ) - bus_speed = PCI_66MHZ; - else if (slot_avail1 & SLOT_33MHZ) - bus_speed = PCI_33MHZ; - else bus_speed = PCI_SPEED_UNKNOWN; - } else { + bus_speed = PCI_SPEED_66MHz_PCIX_266; + } + + if (bus_speed == PCI_SPEED_UNKNOWN) { if (slot_avail1 & SLOT_133MHZ_PCIX) - bus_speed = PCIX_133MHZ; + bus_speed = PCI_SPEED_133MHz_PCIX; else if (slot_avail1 & SLOT_100MHZ_PCIX) - bus_speed = PCIX_100MHZ; + bus_speed = PCI_SPEED_100MHz_PCIX; else if (slot_avail1 & SLOT_66MHZ_PCIX) - bus_speed = PCIX_66MHZ; + bus_speed = PCI_SPEED_66MHz_PCIX; else if (slot_avail2 & SLOT_66MHZ) - bus_speed = PCI_66MHZ; + bus_speed = PCI_SPEED_66MHz; else if (slot_avail1 & SLOT_33MHZ) - bus_speed = PCI_33MHZ; - else bus_speed = PCI_SPEED_UNKNOWN; + bus_speed = PCI_SPEED_33MHz; + else + retval = -ENODEV; } *value = bus_speed; @@ -1210,111 +1113,69 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) { + int retval = 0; struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - u16 sec_bus_status; - int retval = 0; - u8 pi; + u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG); + u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); + u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; + if ((pi == 1) && (speed_mode > 4)) { + *value = PCI_SPEED_UNKNOWN; + return -ENODEV; } - pi = readb(php_ctlr->creg + PROG_INTERFACE); - sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); - - if (pi == 2) { - switch (sec_bus_status & 0x000f) { - case 0: - bus_speed = PCI_SPEED_33MHz; - break; - case 1: - bus_speed = PCI_SPEED_66MHz; - break; - case 2: - bus_speed = PCI_SPEED_66MHz_PCIX; - break; - case 3: - bus_speed = PCI_SPEED_100MHz_PCIX; - break; - case 4: - bus_speed = PCI_SPEED_133MHz_PCIX; - break; - case 5: - bus_speed = PCI_SPEED_66MHz_PCIX_ECC; - break; - case 6: - bus_speed = PCI_SPEED_100MHz_PCIX_ECC; - break; - case 7: - bus_speed = PCI_SPEED_133MHz_PCIX_ECC; - break; - case 8: - bus_speed = PCI_SPEED_66MHz_PCIX_266; - break; - case 9: - bus_speed = PCI_SPEED_100MHz_PCIX_266; - break; - case 0xa: - bus_speed = PCI_SPEED_133MHz_PCIX_266; - break; - case 0xb: - bus_speed = PCI_SPEED_66MHz_PCIX_533; - break; - case 0xc: - bus_speed = PCI_SPEED_100MHz_PCIX_533; - break; - case 0xd: - bus_speed = PCI_SPEED_133MHz_PCIX_533; - break; - case 0xe: - case 0xf: - default: - bus_speed = PCI_SPEED_UNKNOWN; - break; - } - } else { - /* In the case where pi is undefined, default it to 1 */ - switch (sec_bus_status & 0x0007) { - case 0: - bus_speed = PCI_SPEED_33MHz; - break; - case 1: - bus_speed = PCI_SPEED_66MHz; - break; - case 2: - bus_speed = PCI_SPEED_66MHz_PCIX; - break; - case 3: - bus_speed = PCI_SPEED_100MHz_PCIX; - break; - case 4: - bus_speed = PCI_SPEED_133MHz_PCIX; - break; - case 5: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - case 6: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - case 7: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - default: - bus_speed = PCI_SPEED_UNKNOWN; - break; - } + switch (speed_mode) { + case 0x0: + *value = PCI_SPEED_33MHz; + break; + case 0x1: + *value = PCI_SPEED_66MHz; + break; + case 0x2: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 0x3: + *value = PCI_SPEED_100MHz_PCIX; + break; + case 0x4: + *value = PCI_SPEED_133MHz_PCIX; + break; + case 0x5: + *value = PCI_SPEED_66MHz_PCIX_ECC; + break; + case 0x6: + *value = PCI_SPEED_100MHz_PCIX_ECC; + break; + case 0x7: + *value = PCI_SPEED_133MHz_PCIX_ECC; + break; + case 0x8: + *value = PCI_SPEED_66MHz_PCIX_266; + break; + case 0x9: + *value = PCI_SPEED_100MHz_PCIX_266; + break; + case 0xa: + *value = PCI_SPEED_133MHz_PCIX_266; + break; + case 0xb: + *value = PCI_SPEED_66MHz_PCIX_533; + break; + case 0xc: + *value = PCI_SPEED_100MHz_PCIX_533; + break; + case 0xd: + *value = PCI_SPEED_133MHz_PCIX_533; + break; + default: + *value = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + break; } - *value = bus_speed; dbg("Current bus speed = %d\n", bus_speed); DBG_LEAVE_ROUTINE return retval; @@ -1343,7 +1204,6 @@ static struct hpc_ops shpchp_hpc_ops = { .green_led_blink = hpc_set_green_led_blink, .release_ctlr = hpc_release_ctlr, - .check_cmd_status = hpc_check_cmd_status, }; inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, @@ -1375,15 +1235,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ spin_lock_init(&list_lock); - php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); + php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL); if (!php_ctlr) { /* allocate controller state data */ err("%s: HPC controller memory allocation error!\n", __FUNCTION__); goto abort; } - memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s)); - php_ctlr->pci_dev = pdev; /* save pci_dev in context */ if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == @@ -1454,7 +1312,9 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) } dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); + mutex_init(&ctrl->cmd_lock); + /* Setup wait queue */ init_waitqueue_head(&ctrl->queue); diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 19e1a5e1e30b..257adc233996 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -38,7 +38,7 @@ static void program_fw_provided_values(struct pci_dev *dev) { u16 pci_cmd, pci_bctl; struct pci_dev *cdev; - struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */ + struct hotplug_params hpp; /* Program hpp values for this device */ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || @@ -46,7 +46,13 @@ static void program_fw_provided_values(struct pci_dev *dev) (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) return; - get_hp_params_from_firmware(dev, &hpp); + /* use default values if we can't get them from firmware */ + if (get_hp_params_from_firmware(dev, &hpp)) { + hpp.cache_line_size = 8; + hpp.latency_timer = 0x40; + hpp.enable_serr = 0; + hpp.enable_perr = 0; + } pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c deleted file mode 100644 index ed6c1254bf6f..000000000000 --- a/drivers/pci/hotplug/shpchprm_legacy.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com> - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include "shpchp.h" - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); - return 0; -} - -void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return; -} - diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c deleted file mode 100644 index c6b40998eeb3..000000000000 --- a/drivers/pci/hotplug/shpchprm_nonacpi.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> - * - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/slab.h> - -#include "shpchp.h" - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); - return 0; -} - -void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return; -} diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 48723d6fa60f..a77e79c8c82e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -103,9 +103,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) switch (entry->msi_attrib.type) { case PCI_CAP_ID_MSI: { - int pos; + int pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI); - if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI))) + if (!pos) return; pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), @@ -347,9 +347,9 @@ static int assign_msi_vector(void) static int get_new_vector(void) { - int vector; + int vector = assign_msi_vector(); - if ((vector = assign_msi_vector()) > 0) + if (vector > 0) set_intr_gate(vector, interrupt[vector]); return vector; @@ -369,7 +369,8 @@ static int msi_init(void) return status; } - if ((status = msi_cache_init()) < 0) { + status = msi_cache_init(); + if (status < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: MSI cache init failed\n"); return status; @@ -523,10 +524,12 @@ static int msi_capability_init(struct pci_dev *dev) pos = pci_find_capability(dev, PCI_CAP_ID_MSI); pci_read_config_word(dev, msi_control_reg(pos), &control); /* MSI Entry Initialization */ - if (!(entry = alloc_msi_entry())) + entry = alloc_msi_entry(); + if (!entry) return -ENOMEM; - if ((vector = get_msi_vector(dev)) < 0) { + vector = get_msi_vector(dev); + if (vector < 0) { kmem_cache_free(msi_cachep, entry); return -EBUSY; } @@ -597,7 +600,8 @@ static int msix_capability_init(struct pci_dev *dev, struct msg_address address; struct msg_data data; int vector, pos, i, j, nr_entries, temp = 0; - u32 phys_addr, table_offset; + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; void __iomem *base; @@ -606,11 +610,11 @@ static int msix_capability_init(struct pci_dev *dev, /* Request & Map MSI-X table region */ pci_read_config_word(dev, msi_control_reg(pos), &control); nr_entries = multi_msix_capable(control); - pci_read_config_dword(dev, msix_table_offset_reg(pos), - &table_offset); + + pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK); + table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; + phys_addr = pci_resource_start (dev, bir) + table_offset; base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); if (base == NULL) return -ENOMEM; @@ -620,7 +624,8 @@ static int msix_capability_init(struct pci_dev *dev, entry = alloc_msi_entry(); if (!entry) break; - if ((vector = get_msi_vector(dev)) < 0) + vector = get_msi_vector(dev); + if (vector < 0) break; j = entries[i].entry; @@ -699,12 +704,17 @@ int pci_enable_msi(struct pci_dev* dev) if (dev->no_msi) return status; + if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) + return -EINVAL; + temp = dev->irq; - if ((status = msi_init()) < 0) + status = msi_init(); + if (status < 0) return status; - if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSI))) + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!pos) return -EINVAL; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -728,8 +738,8 @@ int pci_enable_msi(struct pci_dev* dev) dev->irq = temp; } /* Check whether driver already requested for MSI-X vectors */ - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { printk(KERN_INFO "PCI: %s: Can't enable MSI. " "Device already has MSI-X vectors assigned\n", pci_name(dev)); @@ -755,7 +765,13 @@ void pci_disable_msi(struct pci_dev* dev) u16 control; unsigned long flags; - if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSI))) + if (!pci_msi_enable) + return; + if (!dev) + return; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!pos) return; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -826,8 +842,10 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) * Detect last MSI-X vector to be released. * Release the MSI-X memory-mapped table. */ +#if 0 int pos, nr_entries; - u32 phys_addr, table_offset; + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; @@ -838,9 +856,12 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(table_offset & - ~PCI_MSIX_FLAGS_BIRMASK); + table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; + phys_addr = pci_resource_start(dev, bir) + table_offset; +/* + * FIXME! and what did you want to do with phys_addr? + */ +#endif iounmap(base); } } @@ -924,10 +945,12 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) if (!pci_msi_enable || !dev || !entries) return -EINVAL; - if ((status = msi_init()) < 0) + status = msi_init(); + if (status < 0) return status; - if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX))) + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (!pos) return -EINVAL; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -1006,7 +1029,13 @@ void pci_disable_msix(struct pci_dev* dev) int pos, temp; u16 control; - if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX))) + if (!pci_msi_enable) + return; + if (!dev) + return; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (!pos) return; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -1066,8 +1095,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) return; temp = dev->irq; /* Save IOAPIC IRQ */ - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { spin_lock_irqsave(&msi_lock, flags); state = msi_desc[dev->irq]->msi_attrib.state; spin_unlock_irqrestore(&msi_lock, flags); @@ -1080,8 +1109,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) msi_free_vector(dev, dev->irq, 0); dev->irq = temp; /* Restore IOAPIC IRQ */ } - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { int vector, head, tail = 0, warning = 0; void __iomem *base = NULL; @@ -1101,7 +1130,9 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) msi_free_vector(dev, vector, 0); if (warning) { /* Force to release the MSI-X memory-mapped table */ - u32 phys_addr, table_offset; +#if 0 + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; @@ -1110,9 +1141,12 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(table_offset & - ~PCI_MSIX_FLAGS_BIRMASK); + table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; + phys_addr = pci_resource_start(dev, bir) + table_offset; +/* + * FIXME! and what did you want to do with phys_addr? + */ +#endif iounmap(base); printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " "called without free_irq() on all MSI-X vectors\n", @@ -1123,6 +1157,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) } } +void pci_no_msi(void) +{ + pci_msi_enable = 0; +} + EXPORT_SYMBOL(pci_enable_msi); EXPORT_SYMBOL(pci_disable_msi); EXPORT_SYMBOL(pci_enable_msix); diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 0aa14c92b570..f22f69ac6445 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -53,11 +53,10 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) if (fields < 0) return -EINVAL; - dynid = kmalloc(sizeof(*dynid), GFP_KERNEL); + dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); if (!dynid) return -ENOMEM; - memset(dynid, 0, sizeof(*dynid)); INIT_LIST_HEAD(&dynid->node); dynid->id.vendor = vendor; dynid->id.device = device; @@ -380,14 +379,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; - /* FIXME, once all of the existing PCI drivers have been fixed to set - * the pci shutdown function, this test can go away. */ - if (!drv->driver.shutdown) - drv->driver.shutdown = pci_device_shutdown; - else - printk(KERN_WARNING "Warning: PCI driver %s has a struct " - "device_driver shutdown method, please update!\n", - drv->name); drv->driver.owner = owner; drv->driver.kobj.ktype = &pci_driver_kobj_type; @@ -514,6 +505,7 @@ struct bus_type pci_bus_type = { .probe = pci_device_probe, .remove = pci_device_remove, .suspend = pci_device_suspend, + .shutdown = pci_device_shutdown, .resume = pci_device_resume, .dev_attrs = pci_dev_attrs, }; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 965a5934623a..56ac2bc003c7 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -501,9 +501,8 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev) if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { struct bin_attribute *rom_attr; - rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC); + rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); if (rom_attr) { - memset(rom_attr, 0x00, sizeof(*rom_attr)); pdev->rom_attr = rom_attr; rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); rom_attr->attr.name = "rom"; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d2d187916643..bea1ad1ad5ba 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -19,7 +19,6 @@ #include <asm/dma.h> /* isa_dma_bridge_buggy */ #include "pci.h" -#if 0 /** * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children @@ -34,7 +33,7 @@ pci_bus_max_busnr(struct pci_bus* bus) struct list_head *tmp; unsigned char max, n; - max = bus->number; + max = bus->subordinate; list_for_each(tmp, &bus->children) { n = pci_bus_max_busnr(pci_bus_b(tmp)); if(n > max) @@ -42,7 +41,9 @@ pci_bus_max_busnr(struct pci_bus* bus) } return max; } +EXPORT_SYMBOL_GPL(pci_bus_max_busnr); +#if 0 /** * pci_max_busnr - returns maximum PCI bus number * @@ -495,9 +496,8 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) int pci_enable_device(struct pci_dev *dev) { - int err; - - if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1))) + int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + if (err) return err; pci_fixup_device(pci_fixup_enable, dev); dev->is_enabled = 1; @@ -639,7 +639,7 @@ void pci_release_region(struct pci_dev *pdev, int bar) * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */ -int pci_request_region(struct pci_dev *pdev, int bar, char *res_name) +int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) { if (pci_resource_len(pdev, bar) == 0) return 0; @@ -697,7 +697,7 @@ void pci_release_regions(struct pci_dev *pdev) * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */ -int pci_request_regions(struct pci_dev *pdev, char *res_name) +int pci_request_regions(struct pci_dev *pdev, const char *res_name) { int i; @@ -900,8 +900,12 @@ static int __devinit pci_setup(char *str) if (k) *k++ = 0; if (*str && (str = pcibios_setup(str)) && *str) { - /* PCI layer options should be handled here */ - printk(KERN_ERR "PCI: Unknown option `%s'\n", str); + if (!strcmp(str, "nomsi")) { + pci_no_msi(); + } else { + printk(KERN_ERR "PCI: Unknown option `%s'\n", + str); + } } str = k; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index a6dfee2f6d2b..8f3fb47ea671 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -50,8 +50,10 @@ extern int pci_msi_quirk; #ifdef CONFIG_PCI_MSI void disable_msi_mode(struct pci_dev *dev, int pos, int type); +void pci_no_msi(void); #else static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } +static inline void pci_no_msi(void) { } #endif extern int pcie_mch_quirk; diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index a63bd8f72601..1d317d22ee89 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -29,7 +29,6 @@ struct pcie_port_device_ext { int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */ - unsigned int saved_msi_config_space[5]; }; extern struct bus_type pcie_port_bus_type; diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index e4e5f1e8d816..55c662267868 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -248,11 +248,10 @@ static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, { struct pcie_device *device; - device = kmalloc(sizeof(struct pcie_device), GFP_KERNEL); + device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL); if (!device) return NULL; - memset(device, 0, sizeof(struct pcie_device)); pcie_device_init(parent, device, port_type, service_type, irq,irq_mode); printk(KERN_DEBUG "Allocate Port Service[%s]\n", device->device.bus_id); return device; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 02260141dc81..50bfc1b2f3bf 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -30,75 +30,16 @@ MODULE_LICENSE("GPL"); /* global data */ static const char device_name[] = "pcieport-driver"; -static void pci_save_msi_state(struct pci_dev *dev) +static int pcie_portdrv_save_config(struct pci_dev *dev) { - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - int i = 0, pos; - u16 control; - - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0) - return; - - pci_read_config_dword(dev, pos, &p_ext->saved_msi_config_space[i++]); - control = p_ext->saved_msi_config_space[0] >> 16; - pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, - &p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_64BIT) { - pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, - &p_ext->saved_msi_config_space[i++]); - pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, - &p_ext->saved_msi_config_space[i++]); - } else - pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, - &p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_MASKBIT) - pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, - &p_ext->saved_msi_config_space[i++]); -} - -static void pci_restore_msi_state(struct pci_dev *dev) -{ - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - int i = 0, pos; - u16 control; - - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0) - return; - - control = p_ext->saved_msi_config_space[i++] >> 16; - pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, - p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_64BIT) { - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, - p_ext->saved_msi_config_space[i++]); - pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, - p_ext->saved_msi_config_space[i++]); - } else - pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, - p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_MASKBIT) - pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, - p_ext->saved_msi_config_space[i++]); -} - -static void pcie_portdrv_save_config(struct pci_dev *dev) -{ - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - - pci_save_state(dev); - if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE) - pci_save_msi_state(dev); + return pci_save_state(dev); } static int pcie_portdrv_restore_config(struct pci_dev *dev) { - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); int retval; pci_restore_state(dev); - if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE) - pci_restore_msi_state(dev); retval = pci_enable_device(dev); if (retval) return retval; @@ -149,7 +90,8 @@ static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) { int ret = pcie_port_device_suspend(dev, state); - pcie_portdrv_save_config(dev); + if (!ret) + ret = pcie_portdrv_save_config(dev); return ret; } diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index adfad4fd6a13..a10ed9dab2c2 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -33,10 +33,9 @@ LIST_HEAD(pci_devices); */ static void pci_create_legacy_files(struct pci_bus *b) { - b->legacy_io = kmalloc(sizeof(struct bin_attribute) * 2, + b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2, GFP_ATOMIC); if (b->legacy_io) { - memset(b->legacy_io, 0, sizeof(struct bin_attribute) * 2); b->legacy_io->attr.name = "legacy_io"; b->legacy_io->size = 0xffff; b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; @@ -320,9 +319,8 @@ static struct pci_bus * __devinit pci_alloc_bus(void) { struct pci_bus *b; - b = kmalloc(sizeof(*b), GFP_KERNEL); + b = kzalloc(sizeof(*b), GFP_KERNEL); if (b) { - memset(b, 0, sizeof(*b)); INIT_LIST_HEAD(&b->node); INIT_LIST_HEAD(&b->children); INIT_LIST_HEAD(&b->devices); @@ -347,6 +345,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) child->parent = parent; child->ops = parent->ops; child->sysdata = parent->sysdata; + child->bus_flags = parent->bus_flags; child->bridge = get_device(&bridge->dev); child->class_dev.class = &pcibus_class; @@ -456,7 +455,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max * pass and just note the configuration. */ if (pass) - return max; + goto out; busnr = (buses >> 8) & 0xFF; /* @@ -466,12 +465,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max if (pci_find_bus(pci_domain_nr(bus), busnr)) { printk(KERN_INFO "PCI: Bus %04x:%02x already known\n", pci_domain_nr(bus), busnr); - return max; + goto out; } child = pci_add_new_bus(bus, dev, busnr); if (!child) - return max; + goto out; child->primary = buses & 0xFF; child->subordinate = (buses >> 16) & 0xFF; child->bridge_ctl = bctl; @@ -496,7 +495,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max bus ranges. */ pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses & ~0xffffff); - return max; + goto out; } /* Clear errors */ @@ -505,7 +504,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max /* Prevent assigning a bus number that already exists. * This can happen when a bridge is hot-plugged */ if (pci_find_bus(pci_domain_nr(bus), max+1)) - return max; + goto out; child = pci_add_new_bus(bus, dev, ++max); buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) @@ -537,6 +536,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_fixup_parent_subordinate_busnr(child, max); /* Now we can scan all subordinate buses... */ max = pci_scan_child_bus(child); + /* + * now fix it up again since we have found + * the real value of max. + */ + pci_fixup_parent_subordinate_busnr(child, max); } else { /* * For CardBus bridges, we leave 4 bus numbers @@ -576,8 +580,6 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); - sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); while (bus->parent) { @@ -585,17 +587,22 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max (child->number > bus->subordinate) || (child->number < bus->number) || (child->subordinate < bus->number)) { - printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be " + printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) is " "hidden behind%s bridge #%02x (-#%02x)%s\n", child->number, child->subordinate, bus->self->transparent ? " transparent" : " ", bus->number, bus->subordinate, pcibios_assign_all_busses() ? " " : " (try 'pci=assign-busses')"); + printk(KERN_WARNING "Please report the result to " + "linux-kernel to fix this permanently\n"); } bus = bus->parent; } +out: + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); + return max; } @@ -788,11 +795,10 @@ pci_scan_device(struct pci_bus *bus, int devfn) if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type)) return NULL; - dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; - memset(dev, 0, sizeof(struct pci_dev)); dev->bus = bus; dev->sysdata = bus->sysdata; dev->dev.parent = bus->bridge; diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 92a885760832..54b2ebc9c91a 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -458,131 +458,6 @@ int pci_proc_detach_bus(struct pci_bus* bus) return 0; } -#ifdef CONFIG_PCI_LEGACY_PROC - -/* - * Backward compatible /proc/pci interface. - */ - -/* - * Convert some of the configuration space registers of the device at - * address (bus,devfn) into a string (possibly several lines each). - * The configuration string is stored starting at buf[len]. If the - * string would exceed the size of the buffer (SIZE), 0 is returned. - */ -static int show_dev_config(struct seq_file *m, void *v) -{ - struct pci_dev *dev = v; - struct pci_dev *first_dev; - struct pci_driver *drv; - u32 class_rev; - unsigned char latency, min_gnt, max_lat; - int reg; - - first_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev == first_dev) - seq_puts(m, "PCI devices found:\n"); - pci_dev_put(first_dev); - - drv = pci_dev_driver(dev); - - pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); - pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt); - pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat); - seq_printf(m, " Bus %2d, device %3d, function %2d:\n", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - seq_printf(m, " Class %04x", class_rev >> 16); - seq_printf(m, ": PCI device %04x:%04x", dev->vendor, dev->device); - seq_printf(m, " (rev %d).\n", class_rev & 0xff); - - if (dev->irq) - seq_printf(m, " IRQ %d.\n", dev->irq); - - if (latency || min_gnt || max_lat) { - seq_printf(m, " Master Capable. "); - if (latency) - seq_printf(m, "Latency=%d. ", latency); - else - seq_puts(m, "No bursts. "); - if (min_gnt) - seq_printf(m, "Min Gnt=%d.", min_gnt); - if (max_lat) - seq_printf(m, "Max Lat=%d.", max_lat); - seq_putc(m, '\n'); - } - - for (reg = 0; reg < 6; reg++) { - struct resource *res = dev->resource + reg; - unsigned long base, end, flags; - - base = res->start; - end = res->end; - flags = res->flags; - if (!end) - continue; - - if (flags & PCI_BASE_ADDRESS_SPACE_IO) { - seq_printf(m, " I/O at 0x%lx [0x%lx].\n", - base, end); - } else { - const char *pref, *type = "unknown"; - - if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) - pref = "P"; - else - pref = "Non-p"; - switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { - case PCI_BASE_ADDRESS_MEM_TYPE_32: - type = "32 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_1M: - type = "20 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_64: - type = "64 bit"; break; - } - seq_printf(m, " %srefetchable %s memory at " - "0x%lx [0x%lx].\n", pref, type, - base, - end); - } - } - return 0; -} - -static struct seq_operations proc_pci_op = { - .start = pci_seq_start, - .next = pci_seq_next, - .stop = pci_seq_stop, - .show = show_dev_config -}; - -static int proc_pci_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &proc_pci_op); -} -static struct file_operations proc_pci_operations = { - .open = proc_pci_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static void legacy_proc_init(void) -{ - struct proc_dir_entry * entry = create_proc_entry("pci", 0, NULL); - if (entry) - entry->proc_fops = &proc_pci_operations; -} - -#else - -static void legacy_proc_init(void) -{ - -} - -#endif /* CONFIG_PCI_LEGACY_PROC */ - static int proc_bus_pci_dev_open(struct inode *inode, struct file *file) { return seq_open(file, &proc_bus_pci_devices_op); @@ -606,7 +481,6 @@ static int __init pci_proc_init(void) while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_proc_attach_device(dev); } - legacy_proc_init(); return 0; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index dda6099903c1..4970f47be72c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -575,8 +575,11 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) { unsigned char revid, tmp; - pci_msi_quirk = 1; - printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n"); + if (dev->subordinate) { + printk(KERN_WARNING "PCI: MSI quirk detected. " + "PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n"); + dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + } if (nr_ioapics == 0) return; @@ -934,6 +937,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x12bd: /* HP D530 */ asus_hides_smbus = 1; } + if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { + switch (dev->subsystem_device) { + case 0x099c: /* HP Compaq nx6110 */ + asus_hides_smbus = 1; + } + } } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) { if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) switch(dev->subsystem_device) { @@ -1068,6 +1077,37 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); +/* + * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller + * and MC97 modem controller are disabled when a second PCI soundcard is + * present. This patch, tweaking the VT8237 ISA bridge, enables them. + * -- bjd + */ +static void __init asus_hides_ac97_lpc(struct pci_dev *dev) +{ + u8 val; + int asus_hides_ac97 = 0; + + if (likely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) { + if (dev->device == PCI_DEVICE_ID_VIA_8237) + asus_hides_ac97 = 1; + } + + if (!asus_hides_ac97) + return; + + pci_read_config_byte(dev, 0x50, &val); + if (val & 0xc0) { + pci_write_config_byte(dev, 0x50, val & (~0xc0)); + pci_read_config_byte(dev, 0x50, &val); + if (val & 0xc0) + printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val); + else + printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n"); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); @@ -1242,6 +1282,33 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_pc DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_pcie_pxh); +/* + * Fixup the cardbus bridges on the IBM Dock II docking station + */ +static void __devinit quirk_ibm_dock2_cardbus(struct pci_dev *dev) +{ + u32 val; + + /* + * tie the 2 interrupt pins to INTA, and configure the + * multifunction routing register to handle this. + */ + if ((dev->subsystem_vendor == PCI_VENDOR_ID_IBM) && + (dev->subsystem_device == 0x0148)) { + printk(KERN_INFO "PCI: Found IBM Dock II Cardbus Bridge " + "applying quirk\n"); + pci_read_config_dword(dev, 0x8c, &val); + val = ((val & 0xffffff00) | 0x1002); + pci_write_config_dword(dev, 0x8c, val); + pci_read_config_dword(dev, 0x80, &val); + val = ((val & 0x00ffff00) | 0x2864c077); + pci_write_config_dword(dev, 0x80, val); + } +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, + quirk_ibm_dock2_cardbus); + static void __devinit quirk_netmos(struct pci_dev *dev) { unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 05fa91a31c62..ce7dd6e7be60 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -246,9 +246,9 @@ pci_get_subsys(unsigned int vendor, unsigned int device, } dev = NULL; exit: - pci_dev_put(from); dev = pci_dev_get(dev); spin_unlock(&pci_bus_lock); + pci_dev_put(from); return dev; } @@ -339,9 +339,9 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) } dev = NULL; exit: - pci_dev_put(from); dev = pci_dev_get(dev); spin_unlock(&pci_bus_lock); + pci_dev_put(from); return dev; } diff --git a/fs/Kconfig b/fs/Kconfig index e9749b0eecd8..c8d0a209120c 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -859,18 +859,6 @@ config RAMFS To compile this as a module, choose M here: the module will be called ramfs. -config RELAYFS_FS - tristate "Relayfs file system support" - ---help--- - Relayfs is a high-speed data relay filesystem designed to provide - an efficient mechanism for tools and facilities to relay large - amounts of data from kernel space to user space. - - To compile this code as a module, choose M here: the module will be - called relayfs. - - If unsure, say N. - config CONFIGFS_FS tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/fs/Makefile b/fs/Makefile index 1db711319c80..080b3867be4d 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -91,7 +91,6 @@ obj-$(CONFIG_AUTOFS4_FS) += autofs4/ obj-$(CONFIG_ADFS_FS) += adfs/ obj-$(CONFIG_FUSE_FS) += fuse/ obj-$(CONFIG_UDF_FS) += udf/ -obj-$(CONFIG_RELAYFS_FS) += relayfs/ obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ obj-$(CONFIG_JFS_FS) += jfs/ obj-$(CONFIG_XFS_FS) += xfs/ @@ -25,6 +25,7 @@ #include <linux/module.h> #include <linux/mempool.h> #include <linux/workqueue.h> +#include <linux/blktrace_api.h> #include <scsi/sg.h> /* for struct sg_iovec */ #define BIO_POOL_SIZE 256 @@ -1095,6 +1096,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) if (!bp) return bp; + blk_add_trace_pdu_int(bdev_get_queue(bi->bi_bdev), BLK_TA_SPLIT, bi, + bi->bi_sector + first_sectors); + BUG_ON(bi->bi_vcnt != 1); BUG_ON(bi->bi_idx != 0); atomic_set(&bp->cnt, 3); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c666769a875d..7c031f00fd79 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -72,6 +72,7 @@ #include <linux/i2c-dev.h> #include <linux/wireless.h> #include <linux/atalk.h> +#include <linux/blktrace_api.h> #include <net/sock.h> /* siocdevprivate_ioctl */ #include <net/bluetooth/bluetooth.h> diff --git a/fs/relayfs/Makefile b/fs/relayfs/Makefile deleted file mode 100644 index e76e182cdb38..000000000000 --- a/fs/relayfs/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_RELAYFS_FS) += relayfs.o - -relayfs-y := relay.o inode.o buffers.o - diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c deleted file mode 100644 index 10187812771e..000000000000 --- a/fs/relayfs/buffers.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * RelayFS buffer management code. - * - * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com) - * - * This file is released under the GPL. - */ - -#include <linux/module.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> -#include <linux/relayfs_fs.h> -#include "relay.h" -#include "buffers.h" - -/* - * close() vm_op implementation for relayfs file mapping. - */ -static void relay_file_mmap_close(struct vm_area_struct *vma) -{ - struct rchan_buf *buf = vma->vm_private_data; - buf->chan->cb->buf_unmapped(buf, vma->vm_file); -} - -/* - * nopage() vm_op implementation for relayfs file mapping. - */ -static struct page *relay_buf_nopage(struct vm_area_struct *vma, - unsigned long address, - int *type) -{ - struct page *page; - struct rchan_buf *buf = vma->vm_private_data; - unsigned long offset = address - vma->vm_start; - - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!buf) - return NOPAGE_OOM; - - page = vmalloc_to_page(buf->start + offset); - if (!page) - return NOPAGE_OOM; - get_page(page); - - if (type) - *type = VM_FAULT_MINOR; - - return page; -} - -/* - * vm_ops for relay file mappings. - */ -static struct vm_operations_struct relay_file_mmap_ops = { - .nopage = relay_buf_nopage, - .close = relay_file_mmap_close, -}; - -/** - * relay_mmap_buf: - mmap channel buffer to process address space - * @buf: relay channel buffer - * @vma: vm_area_struct describing memory to be mapped - * - * Returns 0 if ok, negative on error - * - * Caller should already have grabbed mmap_sem. - */ -int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma) -{ - unsigned long length = vma->vm_end - vma->vm_start; - struct file *filp = vma->vm_file; - - if (!buf) - return -EBADF; - - if (length != (unsigned long)buf->chan->alloc_size) - return -EINVAL; - - vma->vm_ops = &relay_file_mmap_ops; - vma->vm_private_data = buf; - buf->chan->cb->buf_mapped(buf, filp); - - return 0; -} - -/** - * relay_alloc_buf - allocate a channel buffer - * @buf: the buffer struct - * @size: total size of the buffer - * - * Returns a pointer to the resulting buffer, NULL if unsuccessful - */ -static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size) -{ - void *mem; - unsigned int i, j, n_pages; - - size = PAGE_ALIGN(size); - n_pages = size >> PAGE_SHIFT; - - buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL); - if (!buf->page_array) - return NULL; - - for (i = 0; i < n_pages; i++) { - buf->page_array[i] = alloc_page(GFP_KERNEL); - if (unlikely(!buf->page_array[i])) - goto depopulate; - } - mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL); - if (!mem) - goto depopulate; - - memset(mem, 0, size); - buf->page_count = n_pages; - return mem; - -depopulate: - for (j = 0; j < i; j++) - __free_page(buf->page_array[j]); - kfree(buf->page_array); - return NULL; -} - -/** - * relay_create_buf - allocate and initialize a channel buffer - * @alloc_size: size of the buffer to allocate - * @n_subbufs: number of sub-buffers in the channel - * - * Returns channel buffer if successful, NULL otherwise - */ -struct rchan_buf *relay_create_buf(struct rchan *chan) -{ - struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL); - if (!buf) - return NULL; - - buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL); - if (!buf->padding) - goto free_buf; - - buf->start = relay_alloc_buf(buf, chan->alloc_size); - if (!buf->start) - goto free_buf; - - buf->chan = chan; - kref_get(&buf->chan->kref); - return buf; - -free_buf: - kfree(buf->padding); - kfree(buf); - return NULL; -} - -/** - * relay_destroy_buf - destroy an rchan_buf struct and associated buffer - * @buf: the buffer struct - */ -void relay_destroy_buf(struct rchan_buf *buf) -{ - struct rchan *chan = buf->chan; - unsigned int i; - - if (likely(buf->start)) { - vunmap(buf->start); - for (i = 0; i < buf->page_count; i++) - __free_page(buf->page_array[i]); - kfree(buf->page_array); - } - kfree(buf->padding); - kfree(buf); - kref_put(&chan->kref, relay_destroy_channel); -} - -/** - * relay_remove_buf - remove a channel buffer - * - * Removes the file from the relayfs fileystem, which also frees the - * rchan_buf_struct and the channel buffer. Should only be called from - * kref_put(). - */ -void relay_remove_buf(struct kref *kref) -{ - struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref); - buf->chan->cb->remove_buf_file(buf->dentry); - relay_destroy_buf(buf); -} diff --git a/fs/relayfs/buffers.h b/fs/relayfs/buffers.h deleted file mode 100644 index 37a12493f641..000000000000 --- a/fs/relayfs/buffers.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _BUFFERS_H -#define _BUFFERS_H - -/* This inspired by rtai/shmem */ -#define FIX_SIZE(x) (((x) - 1) & PAGE_MASK) + PAGE_SIZE - -extern int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma); -extern struct rchan_buf *relay_create_buf(struct rchan *chan); -extern void relay_destroy_buf(struct rchan_buf *buf); -extern void relay_remove_buf(struct kref *kref); - -#endif/* _BUFFERS_H */ diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c deleted file mode 100644 index 383523011aad..000000000000 --- a/fs/relayfs/inode.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * VFS-related code for RelayFS, a high-speed data relay filesystem. - * - * Copyright (C) 2003-2005 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp - * Copyright (C) 2003-2005 - Karim Yaghmour <karim@opersys.com> - * - * Based on ramfs, Copyright (C) 2002 - Linus Torvalds - * - * This file is released under the GPL. - */ - -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/mount.h> -#include <linux/pagemap.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/backing-dev.h> -#include <linux/namei.h> -#include <linux/poll.h> -#include <linux/relayfs_fs.h> -#include "relay.h" -#include "buffers.h" - -#define RELAYFS_MAGIC 0xF0B4A981 - -static struct vfsmount * relayfs_mount; -static int relayfs_mount_count; - -static struct backing_dev_info relayfs_backing_dev_info = { - .ra_pages = 0, /* No readahead */ - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, -}; - -static struct inode *relayfs_get_inode(struct super_block *sb, - int mode, - struct file_operations *fops, - void *data) -{ - struct inode *inode; - - inode = new_inode(sb); - if (!inode) - return NULL; - - inode->i_mode = mode; - inode->i_uid = 0; - inode->i_gid = 0; - inode->i_blksize = PAGE_CACHE_SIZE; - inode->i_blocks = 0; - inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - switch (mode & S_IFMT) { - case S_IFREG: - inode->i_fop = fops; - if (data) - inode->u.generic_ip = data; - break; - case S_IFDIR: - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; - break; - default: - break; - } - - return inode; -} - -/** - * relayfs_create_entry - create a relayfs directory or file - * @name: the name of the file to create - * @parent: parent directory - * @mode: mode - * @fops: file operations to use for the file - * @data: user-associated data for this file - * - * Returns the new dentry, NULL on failure - * - * Creates a file or directory with the specifed permissions. - */ -static struct dentry *relayfs_create_entry(const char *name, - struct dentry *parent, - int mode, - struct file_operations *fops, - void *data) -{ - struct dentry *d; - struct inode *inode; - int error = 0; - - BUG_ON(!name || !(S_ISREG(mode) || S_ISDIR(mode))); - - error = simple_pin_fs("relayfs", &relayfs_mount, &relayfs_mount_count); - if (error) { - printk(KERN_ERR "Couldn't mount relayfs: errcode %d\n", error); - return NULL; - } - - if (!parent && relayfs_mount && relayfs_mount->mnt_sb) - parent = relayfs_mount->mnt_sb->s_root; - - if (!parent) { - simple_release_fs(&relayfs_mount, &relayfs_mount_count); - return NULL; - } - - parent = dget(parent); - mutex_lock(&parent->d_inode->i_mutex); - d = lookup_one_len(name, parent, strlen(name)); - if (IS_ERR(d)) { - d = NULL; - goto release_mount; - } - - if (d->d_inode) { - d = NULL; - goto release_mount; - } - - inode = relayfs_get_inode(parent->d_inode->i_sb, mode, fops, data); - if (!inode) { - d = NULL; - goto release_mount; - } - - d_instantiate(d, inode); - dget(d); /* Extra count - pin the dentry in core */ - - if (S_ISDIR(mode)) - parent->d_inode->i_nlink++; - - goto exit; - -release_mount: - simple_release_fs(&relayfs_mount, &relayfs_mount_count); - -exit: - mutex_unlock(&parent->d_inode->i_mutex); - dput(parent); - return d; -} - -/** - * relayfs_create_file - create a file in the relay filesystem - * @name: the name of the file to create - * @parent: parent directory - * @mode: mode, if not specied the default perms are used - * @fops: file operations to use for the file - * @data: user-associated data for this file - * - * Returns file dentry if successful, NULL otherwise. - * - * The file will be created user r on behalf of current user. - */ -struct dentry *relayfs_create_file(const char *name, - struct dentry *parent, - int mode, - struct file_operations *fops, - void *data) -{ - BUG_ON(!fops); - - if (!mode) - mode = S_IRUSR; - mode = (mode & S_IALLUGO) | S_IFREG; - - return relayfs_create_entry(name, parent, mode, fops, data); -} - -/** - * relayfs_create_dir - create a directory in the relay filesystem - * @name: the name of the directory to create - * @parent: parent directory, NULL if parent should be fs root - * - * Returns directory dentry if successful, NULL otherwise. - * - * The directory will be created world rwx on behalf of current user. - */ -struct dentry *relayfs_create_dir(const char *name, struct dentry *parent) -{ - int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; - return relayfs_create_entry(name, parent, mode, NULL, NULL); -} - -/** - * relayfs_remove - remove a file or directory in the relay filesystem - * @dentry: file or directory dentry - * - * Returns 0 if successful, negative otherwise. - */ -int relayfs_remove(struct dentry *dentry) -{ - struct dentry *parent; - int error = 0; - - if (!dentry) - return -EINVAL; - parent = dentry->d_parent; - if (!parent) - return -EINVAL; - - parent = dget(parent); - mutex_lock(&parent->d_inode->i_mutex); - if (dentry->d_inode) { - if (S_ISDIR(dentry->d_inode->i_mode)) - error = simple_rmdir(parent->d_inode, dentry); - else - error = simple_unlink(parent->d_inode, dentry); - if (!error) - d_delete(dentry); - } - if (!error) - dput(dentry); - mutex_unlock(&parent->d_inode->i_mutex); - dput(parent); - - if (!error) - simple_release_fs(&relayfs_mount, &relayfs_mount_count); - - return error; -} - -/** - * relayfs_remove_file - remove a file from relay filesystem - * @dentry: directory dentry - * - * Returns 0 if successful, negative otherwise. - */ -int relayfs_remove_file(struct dentry *dentry) -{ - return relayfs_remove(dentry); -} - -/** - * relayfs_remove_dir - remove a directory in the relay filesystem - * @dentry: directory dentry - * - * Returns 0 if successful, negative otherwise. - */ -int relayfs_remove_dir(struct dentry *dentry) -{ - return relayfs_remove(dentry); -} - -/** - * relay_file_open - open file op for relay files - * @inode: the inode - * @filp: the file - * - * Increments the channel buffer refcount. - */ -static int relay_file_open(struct inode *inode, struct file *filp) -{ - struct rchan_buf *buf = inode->u.generic_ip; - kref_get(&buf->kref); - filp->private_data = buf; - - return 0; -} - -/** - * relay_file_mmap - mmap file op for relay files - * @filp: the file - * @vma: the vma describing what to map - * - * Calls upon relay_mmap_buf to map the file into user space. - */ -static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct rchan_buf *buf = filp->private_data; - return relay_mmap_buf(buf, vma); -} - -/** - * relay_file_poll - poll file op for relay files - * @filp: the file - * @wait: poll table - * - * Poll implemention. - */ -static unsigned int relay_file_poll(struct file *filp, poll_table *wait) -{ - unsigned int mask = 0; - struct rchan_buf *buf = filp->private_data; - - if (buf->finalized) - return POLLERR; - - if (filp->f_mode & FMODE_READ) { - poll_wait(filp, &buf->read_wait, wait); - if (!relay_buf_empty(buf)) - mask |= POLLIN | POLLRDNORM; - } - - return mask; -} - -/** - * relay_file_release - release file op for relay files - * @inode: the inode - * @filp: the file - * - * Decrements the channel refcount, as the filesystem is - * no longer using it. - */ -static int relay_file_release(struct inode *inode, struct file *filp) -{ - struct rchan_buf *buf = filp->private_data; - kref_put(&buf->kref, relay_remove_buf); - - return 0; -} - -/** - * relay_file_read_consume - update the consumed count for the buffer - */ -static void relay_file_read_consume(struct rchan_buf *buf, - size_t read_pos, - size_t bytes_consumed) -{ - size_t subbuf_size = buf->chan->subbuf_size; - size_t n_subbufs = buf->chan->n_subbufs; - size_t read_subbuf; - - if (buf->bytes_consumed + bytes_consumed > subbuf_size) { - relay_subbufs_consumed(buf->chan, buf->cpu, 1); - buf->bytes_consumed = 0; - } - - buf->bytes_consumed += bytes_consumed; - read_subbuf = read_pos / buf->chan->subbuf_size; - if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) { - if ((read_subbuf == buf->subbufs_produced % n_subbufs) && - (buf->offset == subbuf_size)) - return; - relay_subbufs_consumed(buf->chan, buf->cpu, 1); - buf->bytes_consumed = 0; - } -} - -/** - * relay_file_read_avail - boolean, are there unconsumed bytes available? - */ -static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos) -{ - size_t bytes_produced, bytes_consumed, write_offset; - size_t subbuf_size = buf->chan->subbuf_size; - size_t n_subbufs = buf->chan->n_subbufs; - size_t produced = buf->subbufs_produced % n_subbufs; - size_t consumed = buf->subbufs_consumed % n_subbufs; - - write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset; - - if (consumed > produced) { - if ((produced > n_subbufs) && - (produced + n_subbufs - consumed <= n_subbufs)) - produced += n_subbufs; - } else if (consumed == produced) { - if (buf->offset > subbuf_size) { - produced += n_subbufs; - if (buf->subbufs_produced == buf->subbufs_consumed) - consumed += n_subbufs; - } - } - - if (buf->offset > subbuf_size) - bytes_produced = (produced - 1) * subbuf_size + write_offset; - else - bytes_produced = produced * subbuf_size + write_offset; - bytes_consumed = consumed * subbuf_size + buf->bytes_consumed; - - if (bytes_produced == bytes_consumed) - return 0; - - relay_file_read_consume(buf, read_pos, 0); - - return 1; -} - -/** - * relay_file_read_subbuf_avail - return bytes available in sub-buffer - */ -static size_t relay_file_read_subbuf_avail(size_t read_pos, - struct rchan_buf *buf) -{ - size_t padding, avail = 0; - size_t read_subbuf, read_offset, write_subbuf, write_offset; - size_t subbuf_size = buf->chan->subbuf_size; - - write_subbuf = (buf->data - buf->start) / subbuf_size; - write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset; - read_subbuf = read_pos / subbuf_size; - read_offset = read_pos % subbuf_size; - padding = buf->padding[read_subbuf]; - - if (read_subbuf == write_subbuf) { - if (read_offset + padding < write_offset) - avail = write_offset - (read_offset + padding); - } else - avail = (subbuf_size - padding) - read_offset; - - return avail; -} - -/** - * relay_file_read_start_pos - find the first available byte to read - * - * If the read_pos is in the middle of padding, return the - * position of the first actually available byte, otherwise - * return the original value. - */ -static size_t relay_file_read_start_pos(size_t read_pos, - struct rchan_buf *buf) -{ - size_t read_subbuf, padding, padding_start, padding_end; - size_t subbuf_size = buf->chan->subbuf_size; - size_t n_subbufs = buf->chan->n_subbufs; - - read_subbuf = read_pos / subbuf_size; - padding = buf->padding[read_subbuf]; - padding_start = (read_subbuf + 1) * subbuf_size - padding; - padding_end = (read_subbuf + 1) * subbuf_size; - if (read_pos >= padding_start && read_pos < padding_end) { - read_subbuf = (read_subbuf + 1) % n_subbufs; - read_pos = read_subbuf * subbuf_size; - } - - return read_pos; -} - -/** - * relay_file_read_end_pos - return the new read position - */ -static size_t relay_file_read_end_pos(struct rchan_buf *buf, - size_t read_pos, - size_t count) -{ - size_t read_subbuf, padding, end_pos; - size_t subbuf_size = buf->chan->subbuf_size; - size_t n_subbufs = buf->chan->n_subbufs; - - read_subbuf = read_pos / subbuf_size; - padding = buf->padding[read_subbuf]; - if (read_pos % subbuf_size + count + padding == subbuf_size) - end_pos = (read_subbuf + 1) * subbuf_size; - else - end_pos = read_pos + count; - if (end_pos >= subbuf_size * n_subbufs) - end_pos = 0; - - return end_pos; -} - -/** - * relay_file_read - read file op for relay files - * @filp: the file - * @buffer: the userspace buffer - * @count: number of bytes to read - * @ppos: position to read from - * - * Reads count bytes or the number of bytes available in the - * current sub-buffer being read, whichever is smaller. - */ -static ssize_t relay_file_read(struct file *filp, - char __user *buffer, - size_t count, - loff_t *ppos) -{ - struct rchan_buf *buf = filp->private_data; - struct inode *inode = filp->f_dentry->d_inode; - size_t read_start, avail; - ssize_t ret = 0; - void *from; - - mutex_lock(&inode->i_mutex); - if(!relay_file_read_avail(buf, *ppos)) - goto out; - - read_start = relay_file_read_start_pos(*ppos, buf); - avail = relay_file_read_subbuf_avail(read_start, buf); - if (!avail) - goto out; - - from = buf->start + read_start; - ret = count = min(count, avail); - if (copy_to_user(buffer, from, count)) { - ret = -EFAULT; - goto out; - } - relay_file_read_consume(buf, read_start, count); - *ppos = relay_file_read_end_pos(buf, read_start, count); -out: - mutex_unlock(&inode->i_mutex); - return ret; -} - -struct file_operations relay_file_operations = { - .open = relay_file_open, - .poll = relay_file_poll, - .mmap = relay_file_mmap, - .read = relay_file_read, - .llseek = no_llseek, - .release = relay_file_release, -}; - -static struct super_operations relayfs_ops = { - .statfs = simple_statfs, - .drop_inode = generic_delete_inode, -}; - -static int relayfs_fill_super(struct super_block * sb, void * data, int silent) -{ - struct inode *inode; - struct dentry *root; - int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; - - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - sb->s_magic = RELAYFS_MAGIC; - sb->s_op = &relayfs_ops; - inode = relayfs_get_inode(sb, mode, NULL, NULL); - - if (!inode) - return -ENOMEM; - - root = d_alloc_root(inode); - if (!root) { - iput(inode); - return -ENOMEM; - } - sb->s_root = root; - - return 0; -} - -static struct super_block * relayfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) -{ - return get_sb_single(fs_type, flags, data, relayfs_fill_super); -} - -static struct file_system_type relayfs_fs_type = { - .owner = THIS_MODULE, - .name = "relayfs", - .get_sb = relayfs_get_sb, - .kill_sb = kill_litter_super, -}; - -static int __init init_relayfs_fs(void) -{ - return register_filesystem(&relayfs_fs_type); -} - -static void __exit exit_relayfs_fs(void) -{ - - - - - - unregister_filesystem(&relayfs_fs_type); -} - -module_init(init_relayfs_fs) -module_exit(exit_relayfs_fs) - -EXPORT_SYMBOL_GPL(relay_file_operations); -EXPORT_SYMBOL_GPL(relayfs_create_dir); -EXPORT_SYMBOL_GPL(relayfs_remove_dir); -EXPORT_SYMBOL_GPL(relayfs_create_file); -EXPORT_SYMBOL_GPL(relayfs_remove_file); - -MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>"); -MODULE_DESCRIPTION("Relay Filesystem"); -MODULE_LICENSE("GPL"); - diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c deleted file mode 100644 index abf3ceaace49..000000000000 --- a/fs/relayfs/relay.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Public API and common code for RelayFS. - * - * See Documentation/filesystems/relayfs.txt for an overview of relayfs. - * - * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com) - * - * This file is released under the GPL. - */ - -#include <linux/errno.h> -#include <linux/stddef.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/string.h> -#include <linux/relayfs_fs.h> -#include "relay.h" -#include "buffers.h" - -/** - * relay_buf_empty - boolean, is the channel buffer empty? - * @buf: channel buffer - * - * Returns 1 if the buffer is empty, 0 otherwise. - */ -int relay_buf_empty(struct rchan_buf *buf) -{ - return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1; -} - -/** - * relay_buf_full - boolean, is the channel buffer full? - * @buf: channel buffer - * - * Returns 1 if the buffer is full, 0 otherwise. - */ -int relay_buf_full(struct rchan_buf *buf) -{ - size_t ready = buf->subbufs_produced - buf->subbufs_consumed; - return (ready >= buf->chan->n_subbufs) ? 1 : 0; -} - -/* - * High-level relayfs kernel API and associated functions. - */ - -/* - * rchan_callback implementations defining default channel behavior. Used - * in place of corresponding NULL values in client callback struct. - */ - -/* - * subbuf_start() default callback. Does nothing. - */ -static int subbuf_start_default_callback (struct rchan_buf *buf, - void *subbuf, - void *prev_subbuf, - size_t prev_padding) -{ - if (relay_buf_full(buf)) - return 0; - - return 1; -} - -/* - * buf_mapped() default callback. Does nothing. - */ -static void buf_mapped_default_callback(struct rchan_buf *buf, - struct file *filp) -{ -} - -/* - * buf_unmapped() default callback. Does nothing. - */ -static void buf_unmapped_default_callback(struct rchan_buf *buf, - struct file *filp) -{ -} - -/* - * create_buf_file_create() default callback. Creates file to represent buf. - */ -static struct dentry *create_buf_file_default_callback(const char *filename, - struct dentry *parent, - int mode, - struct rchan_buf *buf, - int *is_global) -{ - return relayfs_create_file(filename, parent, mode, - &relay_file_operations, buf); -} - -/* - * remove_buf_file() default callback. Removes file representing relay buffer. - */ -static int remove_buf_file_default_callback(struct dentry *dentry) -{ - return relayfs_remove(dentry); -} - -/* relay channel default callbacks */ -static struct rchan_callbacks default_channel_callbacks = { - .subbuf_start = subbuf_start_default_callback, - .buf_mapped = buf_mapped_default_callback, - .buf_unmapped = buf_unmapped_default_callback, - .create_buf_file = create_buf_file_default_callback, - .remove_buf_file = remove_buf_file_default_callback, -}; - -/** - * wakeup_readers - wake up readers waiting on a channel - * @private: the channel buffer - * - * This is the work function used to defer reader waking. The - * reason waking is deferred is that calling directly from write - * causes problems if you're writing from say the scheduler. - */ -static void wakeup_readers(void *private) -{ - struct rchan_buf *buf = private; - wake_up_interruptible(&buf->read_wait); -} - -/** - * __relay_reset - reset a channel buffer - * @buf: the channel buffer - * @init: 1 if this is a first-time initialization - * - * See relay_reset for description of effect. - */ -static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) -{ - size_t i; - - if (init) { - init_waitqueue_head(&buf->read_wait); - kref_init(&buf->kref); - INIT_WORK(&buf->wake_readers, NULL, NULL); - } else { - cancel_delayed_work(&buf->wake_readers); - flush_scheduled_work(); - } - - buf->subbufs_produced = 0; - buf->subbufs_consumed = 0; - buf->bytes_consumed = 0; - buf->finalized = 0; - buf->data = buf->start; - buf->offset = 0; - - for (i = 0; i < buf->chan->n_subbufs; i++) - buf->padding[i] = 0; - - buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0); -} - -/** - * relay_reset - reset the channel - * @chan: the channel - * - * This has the effect of erasing all data from all channel buffers - * and restarting the channel in its initial state. The buffers - * are not freed, so any mappings are still in effect. - * - * NOTE: Care should be taken that the channel isn't actually - * being used by anything when this call is made. - */ -void relay_reset(struct rchan *chan) -{ - unsigned int i; - struct rchan_buf *prev = NULL; - - if (!chan) - return; - - for (i = 0; i < NR_CPUS; i++) { - if (!chan->buf[i] || chan->buf[i] == prev) - break; - __relay_reset(chan->buf[i], 0); - prev = chan->buf[i]; - } -} - -/** - * relay_open_buf - create a new channel buffer in relayfs - * - * Internal - used by relay_open(). - */ -static struct rchan_buf *relay_open_buf(struct rchan *chan, - const char *filename, - struct dentry *parent, - int *is_global) -{ - struct rchan_buf *buf; - struct dentry *dentry; - - if (*is_global) - return chan->buf[0]; - - buf = relay_create_buf(chan); - if (!buf) - return NULL; - - /* Create file in fs */ - dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR, - buf, is_global); - if (!dentry) { - relay_destroy_buf(buf); - return NULL; - } - - buf->dentry = dentry; - __relay_reset(buf, 1); - - return buf; -} - -/** - * relay_close_buf - close a channel buffer - * @buf: channel buffer - * - * Marks the buffer finalized and restores the default callbacks. - * The channel buffer and channel buffer data structure are then freed - * automatically when the last reference is given up. - */ -static inline void relay_close_buf(struct rchan_buf *buf) -{ - buf->finalized = 1; - buf->chan->cb = &default_channel_callbacks; - cancel_delayed_work(&buf->wake_readers); - flush_scheduled_work(); - kref_put(&buf->kref, relay_remove_buf); -} - -static inline void setup_callbacks(struct rchan *chan, - struct rchan_callbacks *cb) -{ - if (!cb) { - chan->cb = &default_channel_callbacks; - return; - } - - if (!cb->subbuf_start) - cb->subbuf_start = subbuf_start_default_callback; - if (!cb->buf_mapped) - cb->buf_mapped = buf_mapped_default_callback; - if (!cb->buf_unmapped) - cb->buf_unmapped = buf_unmapped_default_callback; - if (!cb->create_buf_file) - cb->create_buf_file = create_buf_file_default_callback; - if (!cb->remove_buf_file) - cb->remove_buf_file = remove_buf_file_default_callback; - chan->cb = cb; -} - -/** - * relay_open - create a new relayfs channel - * @base_filename: base name of files to create - * @parent: dentry of parent directory, NULL for root directory - * @subbuf_size: size of sub-buffers - * @n_subbufs: number of sub-buffers - * @cb: client callback functions - * - * Returns channel pointer if successful, NULL otherwise. - * - * Creates a channel buffer for each cpu using the sizes and - * attributes specified. The created channel buffer files - * will be named base_filename0...base_filenameN-1. File - * permissions will be S_IRUSR. - */ -struct rchan *relay_open(const char *base_filename, - struct dentry *parent, - size_t subbuf_size, - size_t n_subbufs, - struct rchan_callbacks *cb) -{ - unsigned int i; - struct rchan *chan; - char *tmpname; - int is_global = 0; - - if (!base_filename) - return NULL; - - if (!(subbuf_size && n_subbufs)) - return NULL; - - chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL); - if (!chan) - return NULL; - - chan->version = RELAYFS_CHANNEL_VERSION; - chan->n_subbufs = n_subbufs; - chan->subbuf_size = subbuf_size; - chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs); - setup_callbacks(chan, cb); - kref_init(&chan->kref); - - tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL); - if (!tmpname) - goto free_chan; - - for_each_online_cpu(i) { - sprintf(tmpname, "%s%d", base_filename, i); - chan->buf[i] = relay_open_buf(chan, tmpname, parent, - &is_global); - chan->buf[i]->cpu = i; - if (!chan->buf[i]) - goto free_bufs; - } - - kfree(tmpname); - return chan; - -free_bufs: - for (i = 0; i < NR_CPUS; i++) { - if (!chan->buf[i]) - break; - relay_close_buf(chan->buf[i]); - if (is_global) - break; - } - kfree(tmpname); - -free_chan: - kref_put(&chan->kref, relay_destroy_channel); - return NULL; -} - -/** - * relay_switch_subbuf - switch to a new sub-buffer - * @buf: channel buffer - * @length: size of current event - * - * Returns either the length passed in or 0 if full. - - * Performs sub-buffer-switch tasks such as invoking callbacks, - * updating padding counts, waking up readers, etc. - */ -size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) -{ - void *old, *new; - size_t old_subbuf, new_subbuf; - - if (unlikely(length > buf->chan->subbuf_size)) - goto toobig; - - if (buf->offset != buf->chan->subbuf_size + 1) { - buf->prev_padding = buf->chan->subbuf_size - buf->offset; - old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; - buf->padding[old_subbuf] = buf->prev_padding; - buf->subbufs_produced++; - if (waitqueue_active(&buf->read_wait)) { - PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf); - schedule_delayed_work(&buf->wake_readers, 1); - } - } - - old = buf->data; - new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; - new = buf->start + new_subbuf * buf->chan->subbuf_size; - buf->offset = 0; - if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) { - buf->offset = buf->chan->subbuf_size + 1; - return 0; - } - buf->data = new; - buf->padding[new_subbuf] = 0; - - if (unlikely(length + buf->offset > buf->chan->subbuf_size)) - goto toobig; - - return length; - -toobig: - buf->chan->last_toobig = length; - return 0; -} - -/** - * relay_subbufs_consumed - update the buffer's sub-buffers-consumed count - * @chan: the channel - * @cpu: the cpu associated with the channel buffer to update - * @subbufs_consumed: number of sub-buffers to add to current buf's count - * - * Adds to the channel buffer's consumed sub-buffer count. - * subbufs_consumed should be the number of sub-buffers newly consumed, - * not the total consumed. - * - * NOTE: kernel clients don't need to call this function if the channel - * mode is 'overwrite'. - */ -void relay_subbufs_consumed(struct rchan *chan, - unsigned int cpu, - size_t subbufs_consumed) -{ - struct rchan_buf *buf; - - if (!chan) - return; - - if (cpu >= NR_CPUS || !chan->buf[cpu]) - return; - - buf = chan->buf[cpu]; - buf->subbufs_consumed += subbufs_consumed; - if (buf->subbufs_consumed > buf->subbufs_produced) - buf->subbufs_consumed = buf->subbufs_produced; -} - -/** - * relay_destroy_channel - free the channel struct - * - * Should only be called from kref_put(). - */ -void relay_destroy_channel(struct kref *kref) -{ - struct rchan *chan = container_of(kref, struct rchan, kref); - kfree(chan); -} - -/** - * relay_close - close the channel - * @chan: the channel - * - * Closes all channel buffers and frees the channel. - */ -void relay_close(struct rchan *chan) -{ - unsigned int i; - struct rchan_buf *prev = NULL; - - if (!chan) - return; - - for (i = 0; i < NR_CPUS; i++) { - if (!chan->buf[i] || chan->buf[i] == prev) - break; - relay_close_buf(chan->buf[i]); - prev = chan->buf[i]; - } - - if (chan->last_toobig) - printk(KERN_WARNING "relayfs: one or more items not logged " - "[item size (%Zd) > sub-buffer size (%Zd)]\n", - chan->last_toobig, chan->subbuf_size); - - kref_put(&chan->kref, relay_destroy_channel); -} - -/** - * relay_flush - close the channel - * @chan: the channel - * - * Flushes all channel buffers i.e. forces buffer switch. - */ -void relay_flush(struct rchan *chan) -{ - unsigned int i; - struct rchan_buf *prev = NULL; - - if (!chan) - return; - - for (i = 0; i < NR_CPUS; i++) { - if (!chan->buf[i] || chan->buf[i] == prev) - break; - relay_switch_subbuf(chan->buf[i], 0); - prev = chan->buf[i]; - } -} - -EXPORT_SYMBOL_GPL(relay_open); -EXPORT_SYMBOL_GPL(relay_close); -EXPORT_SYMBOL_GPL(relay_flush); -EXPORT_SYMBOL_GPL(relay_reset); -EXPORT_SYMBOL_GPL(relay_subbufs_consumed); -EXPORT_SYMBOL_GPL(relay_switch_subbuf); -EXPORT_SYMBOL_GPL(relay_buf_full); diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h deleted file mode 100644 index 0993d3e5753b..000000000000 --- a/fs/relayfs/relay.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _RELAY_H -#define _RELAY_H - -extern int relayfs_remove(struct dentry *dentry); -extern int relay_buf_empty(struct rchan_buf *buf); -extern void relay_destroy_channel(struct kref *kref); - -#endif /* _RELAY_H */ diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index 97bd4743b461..5d73eaa1971f 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 @@ -1,33 +1,19 @@ # -# Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (c) 2000-2005 Silicon Graphics, Inc. +# All Rights Reserved. # -# This program is free software; you can redistribute it and/or modify it -# under the terms of version 2 of the GNU General Public License as +# 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. # -# This program is distributed in the hope that it would be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# This program is distributed in the hope that it would 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. # -# Further, this software is distributed without any warranty that it is -# free of the rightful claim of any third person regarding infringement -# or the like. Any license provided herein, whether implied or -# otherwise, applies only to this software file. Patent licenses, if -# any, provided herein do not apply to combinations of this program with -# other software, or any other product whatsoever. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write the Free Software Foundation, Inc., 59 -# Temple Place - Suite 330, Boston MA 02111-1307, USA. -# -# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, -# Mountain View, CA 94043, or: -# -# http://www.sgi.com -# -# For further information regarding this notice, see: -# -# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char @@ -36,7 +22,7 @@ XFS_LINUX := linux-2.6 ifeq ($(CONFIG_XFS_DEBUG),y) EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG - EXTRA_CFLAGS += -DPAGEBUF_LOCK_TRACKING + EXTRA_CFLAGS += -DXFS_BUF_LOCK_TRACKING endif ifeq ($(CONFIG_XFS_TRACE),y) EXTRA_CFLAGS += -DXFS_ALLOC_TRACE @@ -50,7 +36,7 @@ ifeq ($(CONFIG_XFS_TRACE),y) EXTRA_CFLAGS += -DXFS_ILOCK_TRACE EXTRA_CFLAGS += -DXFS_LOG_TRACE EXTRA_CFLAGS += -DXFS_RW_TRACE - EXTRA_CFLAGS += -DPAGEBUF_TRACE + EXTRA_CFLAGS += -DXFS_BUF_TRACE EXTRA_CFLAGS += -DXFS_VNODE_TRACE endif diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index c64a29cdfff3..f0268a84e6fd 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h @@ -23,17 +23,8 @@ #include <linux/mm.h> /* - * memory management routines + * Process flags handling */ -#define KM_SLEEP 0x0001u -#define KM_NOSLEEP 0x0002u -#define KM_NOFS 0x0004u -#define KM_MAYFAIL 0x0008u - -#define kmem_zone kmem_cache -#define kmem_zone_t struct kmem_cache - -typedef unsigned long xfs_pflags_t; #define PFLAGS_TEST_NOIO() (current->flags & PF_NOIO) #define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS) @@ -67,74 +58,102 @@ typedef unsigned long xfs_pflags_t; *(NSTATEP) = *(OSTATEP); \ } while (0) -static __inline gfp_t kmem_flags_convert(unsigned int __nocast flags) +/* + * General memory allocation interfaces + */ + +#define KM_SLEEP 0x0001u +#define KM_NOSLEEP 0x0002u +#define KM_NOFS 0x0004u +#define KM_MAYFAIL 0x0008u + +/* + * We use a special process flag to avoid recursive callbacks into + * the filesystem during transactions. We will also issue our own + * warnings, so we explicitly skip any generic ones (silly of us). + */ +static inline gfp_t +kmem_flags_convert(unsigned int __nocast flags) { - gfp_t lflags = __GFP_NOWARN; /* we'll report problems, if need be */ + gfp_t lflags; -#ifdef DEBUG - if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL))) { - printk(KERN_WARNING - "XFS: memory allocation with wrong flags (%x)\n", flags); - BUG(); - } -#endif + BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL)); if (flags & KM_NOSLEEP) { - lflags |= GFP_ATOMIC; + lflags = GFP_ATOMIC | __GFP_NOWARN; } else { - lflags |= GFP_KERNEL; - - /* avoid recusive callbacks to filesystem during transactions */ + lflags = GFP_KERNEL | __GFP_NOWARN; if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS)) lflags &= ~__GFP_FS; } - - return lflags; + return lflags; } -static __inline kmem_zone_t * +extern void *kmem_alloc(size_t, unsigned int __nocast); +extern void *kmem_realloc(void *, size_t, size_t, unsigned int __nocast); +extern void *kmem_zalloc(size_t, unsigned int __nocast); +extern void kmem_free(void *, size_t); + +/* + * Zone interfaces + */ + +#define KM_ZONE_HWALIGN SLAB_HWCACHE_ALIGN +#define KM_ZONE_RECLAIM SLAB_RECLAIM_ACCOUNT +#define KM_ZONE_SPREAD 0 + +#define kmem_zone kmem_cache +#define kmem_zone_t struct kmem_cache + +static inline kmem_zone_t * kmem_zone_init(int size, char *zone_name) { return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL); } -static __inline void +static inline kmem_zone_t * +kmem_zone_init_flags(int size, char *zone_name, unsigned long flags, + void (*construct)(void *, kmem_zone_t *, unsigned long)) +{ + return kmem_cache_create(zone_name, size, 0, flags, construct, NULL); +} + +static inline void kmem_zone_free(kmem_zone_t *zone, void *ptr) { kmem_cache_free(zone, ptr); } -static __inline void +static inline void kmem_zone_destroy(kmem_zone_t *zone) { if (zone && kmem_cache_destroy(zone)) BUG(); } -extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast); +extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); -extern void *kmem_alloc(size_t, unsigned int __nocast); -extern void *kmem_realloc(void *, size_t, size_t, unsigned int __nocast); -extern void *kmem_zalloc(size_t, unsigned int __nocast); -extern void kmem_free(void *, size_t); +/* + * Low memory cache shrinkers + */ typedef struct shrinker *kmem_shaker_t; typedef int (*kmem_shake_func_t)(int, gfp_t); -static __inline kmem_shaker_t +static inline kmem_shaker_t kmem_shake_register(kmem_shake_func_t sfunc) { return set_shrinker(DEFAULT_SEEKS, sfunc); } -static __inline void +static inline void kmem_shake_deregister(kmem_shaker_t shrinker) { remove_shrinker(shrinker); } -static __inline int +static inline int kmem_shake_allow(gfp_t gfp_mask) { return (gfp_mask & __GFP_WAIT); diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 74d8be87f983..97fc056130eb 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -43,7 +43,29 @@ #include <linux/pagevec.h> #include <linux/writeback.h> -STATIC void xfs_count_page_state(struct page *, int *, int *, int *); +STATIC void +xfs_count_page_state( + struct page *page, + int *delalloc, + int *unmapped, + int *unwritten) +{ + struct buffer_head *bh, *head; + + *delalloc = *unmapped = *unwritten = 0; + + bh = head = page_buffers(page); + do { + if (buffer_uptodate(bh) && !buffer_mapped(bh)) + (*unmapped) = 1; + else if (buffer_unwritten(bh) && !buffer_delay(bh)) + clear_buffer_unwritten(bh); + else if (buffer_unwritten(bh)) + (*unwritten) = 1; + else if (buffer_delay(bh)) + (*delalloc) = 1; + } while ((bh = bh->b_this_page) != head); +} #if defined(XFS_RW_TRACE) void @@ -54,7 +76,7 @@ xfs_page_trace( int mask) { xfs_inode_t *ip; - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); loff_t isize = i_size_read(inode); loff_t offset = page_offset(page); int delalloc = -1, unmapped = -1, unwritten = -1; @@ -81,7 +103,7 @@ xfs_page_trace( (void *)((unsigned long)delalloc), (void *)((unsigned long)unmapped), (void *)((unsigned long)unwritten), - (void *)NULL, + (void *)((unsigned long)current_pid()), (void *)NULL); } #else @@ -192,7 +214,7 @@ xfs_alloc_ioend( ioend->io_uptodate = 1; /* cleared if any I/O fails */ ioend->io_list = NULL; ioend->io_type = type; - ioend->io_vnode = LINVFS_GET_VP(inode); + ioend->io_vnode = vn_from_inode(inode); ioend->io_buffer_head = NULL; ioend->io_buffer_tail = NULL; atomic_inc(&ioend->io_vnode->v_iocount); @@ -217,7 +239,7 @@ xfs_map_blocks( xfs_iomap_t *mapp, int flags) { - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error, nmaps = 1; VOP_BMAP(vp, offset, count, flags, mapp, &nmaps, error); @@ -462,28 +484,37 @@ xfs_add_to_ioend( } STATIC void +xfs_map_buffer( + struct buffer_head *bh, + xfs_iomap_t *mp, + xfs_off_t offset, + uint block_bits) +{ + sector_t bn; + + ASSERT(mp->iomap_bn != IOMAP_DADDR_NULL); + + bn = (mp->iomap_bn >> (block_bits - BBSHIFT)) + + ((offset - mp->iomap_offset) >> block_bits); + + ASSERT(bn || (mp->iomap_flags & IOMAP_REALTIME)); + + bh->b_blocknr = bn; + set_buffer_mapped(bh); +} + +STATIC void xfs_map_at_offset( struct buffer_head *bh, loff_t offset, int block_bits, xfs_iomap_t *iomapp) { - xfs_daddr_t bn; - int sector_shift; - ASSERT(!(iomapp->iomap_flags & IOMAP_HOLE)); ASSERT(!(iomapp->iomap_flags & IOMAP_DELAY)); - ASSERT(iomapp->iomap_bn != IOMAP_DADDR_NULL); - - sector_shift = block_bits - BBSHIFT; - bn = (iomapp->iomap_bn >> sector_shift) + - ((offset - iomapp->iomap_offset) >> block_bits); - - ASSERT(bn || (iomapp->iomap_flags & IOMAP_REALTIME)); - ASSERT((bn << sector_shift) >= iomapp->iomap_bn); lock_buffer(bh); - bh->b_blocknr = bn; + xfs_map_buffer(bh, iomapp, offset, block_bits); bh->b_bdev = iomapp->iomap_target->bt_bdev; set_buffer_mapped(bh); clear_buffer_delay(bh); @@ -616,7 +647,7 @@ xfs_is_delayed_page( acceptable = (type == IOMAP_UNWRITTEN); else if (buffer_delay(bh)) acceptable = (type == IOMAP_DELAY); - else if (buffer_mapped(bh)) + else if (buffer_dirty(bh) && buffer_mapped(bh)) acceptable = (type == 0); else break; @@ -1040,8 +1071,159 @@ error: return err; } +/* + * writepage: Called from one of two places: + * + * 1. we are flushing a delalloc buffer head. + * + * 2. we are writing out a dirty page. Typically the page dirty + * state is cleared before we get here. In this case is it + * conceivable we have no buffer heads. + * + * For delalloc space on the page we need to allocate space and + * flush it. For unmapped buffer heads on the page we should + * allocate space if the page is uptodate. For any other dirty + * buffer heads on the page we should flush them. + * + * If we detect that a transaction would be required to flush + * the page, we have to check the process flags first, if we + * are already in a transaction or disk I/O during allocations + * is off, we need to fail the writepage and redirty the page. + */ + +STATIC int +xfs_vm_writepage( + struct page *page, + struct writeback_control *wbc) +{ + int error; + int need_trans; + int delalloc, unmapped, unwritten; + struct inode *inode = page->mapping->host; + + xfs_page_trace(XFS_WRITEPAGE_ENTER, inode, page, 0); + + /* + * We need a transaction if: + * 1. There are delalloc buffers on the page + * 2. The page is uptodate and we have unmapped buffers + * 3. The page is uptodate and we have no buffers + * 4. There are unwritten buffers on the page + */ + + if (!page_has_buffers(page)) { + unmapped = 1; + need_trans = 1; + } else { + xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); + if (!PageUptodate(page)) + unmapped = 0; + need_trans = delalloc + unmapped + unwritten; + } + + /* + * If we need a transaction and the process flags say + * we are already in a transaction, or no IO is allowed + * then mark the page dirty again and leave the page + * as is. + */ + if (PFLAGS_TEST_FSTRANS() && need_trans) + goto out_fail; + + /* + * Delay hooking up buffer heads until we have + * made our go/no-go decision. + */ + if (!page_has_buffers(page)) + create_empty_buffers(page, 1 << inode->i_blkbits, 0); + + /* + * Convert delayed allocate, unwritten or unmapped space + * to real space and flush out to disk. + */ + error = xfs_page_state_convert(inode, page, wbc, 1, unmapped); + if (error == -EAGAIN) + goto out_fail; + if (unlikely(error < 0)) + goto out_unlock; + + return 0; + +out_fail: + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return 0; +out_unlock: + unlock_page(page); + return error; +} + +/* + * Called to move a page into cleanable state - and from there + * to be released. Possibly the page is already clean. We always + * have buffer heads in this call. + * + * Returns 0 if the page is ok to release, 1 otherwise. + * + * Possible scenarios are: + * + * 1. We are being called to release a page which has been written + * to via regular I/O. buffer heads will be dirty and possibly + * delalloc. If no delalloc buffer heads in this case then we + * can just return zero. + * + * 2. We are called to release a page which has been written via + * mmap, all we need to do is ensure there is no delalloc + * state in the buffer heads, if not we can let the caller + * free them and we should come back later via writepage. + */ STATIC int -__linvfs_get_block( +xfs_vm_releasepage( + struct page *page, + gfp_t gfp_mask) +{ + struct inode *inode = page->mapping->host; + int dirty, delalloc, unmapped, unwritten; + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = 1, + }; + + xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask); + + if (!page_has_buffers(page)) + return 0; + + xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); + if (!delalloc && !unwritten) + goto free_buffers; + + if (!(gfp_mask & __GFP_FS)) + return 0; + + /* If we are already inside a transaction or the thread cannot + * do I/O, we cannot release this page. + */ + if (PFLAGS_TEST_FSTRANS()) + return 0; + + /* + * Convert delalloc space to real space, do not flush the + * data out to disk, that will be done by the caller. + * Never need to allocate space here - we will always + * come back to writepage in that case. + */ + dirty = xfs_page_state_convert(inode, page, &wbc, 0, 0); + if (dirty == 0 && !unwritten) + goto free_buffers; + return 0; + +free_buffers: + return try_to_free_buffers(page); +} + +STATIC int +__xfs_get_block( struct inode *inode, sector_t iblock, unsigned long blocks, @@ -1050,7 +1232,7 @@ __linvfs_get_block( int direct, bmapi_flags_t flags) { - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); xfs_iomap_t iomap; xfs_off_t offset; ssize_t size; @@ -1073,21 +1255,13 @@ __linvfs_get_block( return 0; if (iomap.iomap_bn != IOMAP_DADDR_NULL) { - xfs_daddr_t bn; - xfs_off_t delta; - - /* For unwritten extents do not report a disk address on + /* + * For unwritten extents do not report a disk address on * the read case (treat as if we're reading into a hole). */ if (create || !(iomap.iomap_flags & IOMAP_UNWRITTEN)) { - delta = offset - iomap.iomap_offset; - delta >>= inode->i_blkbits; - - bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT); - bn += delta; - BUG_ON(!bn && !(iomap.iomap_flags & IOMAP_REALTIME)); - bh_result->b_blocknr = bn; - set_buffer_mapped(bh_result); + xfs_map_buffer(bh_result, &iomap, offset, + inode->i_blkbits); } if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) { if (direct) @@ -1130,30 +1304,30 @@ __linvfs_get_block( } int -linvfs_get_block( +xfs_get_block( struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { - return __linvfs_get_block(inode, iblock, 0, bh_result, + return __xfs_get_block(inode, iblock, 0, bh_result, create, 0, BMAPI_WRITE); } STATIC int -linvfs_get_blocks_direct( +xfs_get_blocks_direct( struct inode *inode, sector_t iblock, unsigned long max_blocks, struct buffer_head *bh_result, int create) { - return __linvfs_get_block(inode, iblock, max_blocks, bh_result, + return __xfs_get_block(inode, iblock, max_blocks, bh_result, create, 1, BMAPI_WRITE|BMAPI_DIRECT); } STATIC void -linvfs_end_io_direct( +xfs_end_io_direct( struct kiocb *iocb, loff_t offset, ssize_t size, @@ -1191,7 +1365,7 @@ linvfs_end_io_direct( } STATIC ssize_t -linvfs_direct_IO( +xfs_vm_direct_IO( int rw, struct kiocb *iocb, const struct iovec *iov, @@ -1200,7 +1374,7 @@ linvfs_direct_IO( { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); xfs_iomap_t iomap; int maps = 1; int error; @@ -1215,164 +1389,61 @@ linvfs_direct_IO( ret = blockdev_direct_IO_own_locking(rw, iocb, inode, iomap.iomap_target->bt_bdev, iov, offset, nr_segs, - linvfs_get_blocks_direct, - linvfs_end_io_direct); + xfs_get_blocks_direct, + xfs_end_io_direct); if (unlikely(ret <= 0 && iocb->private)) xfs_destroy_ioend(iocb->private); return ret; } +STATIC int +xfs_vm_prepare_write( + struct file *file, + struct page *page, + unsigned int from, + unsigned int to) +{ + return block_prepare_write(page, from, to, xfs_get_block); +} STATIC sector_t -linvfs_bmap( +xfs_vm_bmap( struct address_space *mapping, sector_t block) { struct inode *inode = (struct inode *)mapping->host; - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error; - vn_trace_entry(vp, "linvfs_bmap", (inst_t *)__return_address); + vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); VOP_RWLOCK(vp, VRWLOCK_READ); VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); VOP_RWUNLOCK(vp, VRWLOCK_READ); - return generic_block_bmap(mapping, block, linvfs_get_block); + return generic_block_bmap(mapping, block, xfs_get_block); } STATIC int -linvfs_readpage( +xfs_vm_readpage( struct file *unused, struct page *page) { - return mpage_readpage(page, linvfs_get_block); + return mpage_readpage(page, xfs_get_block); } STATIC int -linvfs_readpages( +xfs_vm_readpages( struct file *unused, struct address_space *mapping, struct list_head *pages, unsigned nr_pages) { - return mpage_readpages(mapping, pages, nr_pages, linvfs_get_block); -} - -STATIC void -xfs_count_page_state( - struct page *page, - int *delalloc, - int *unmapped, - int *unwritten) -{ - struct buffer_head *bh, *head; - - *delalloc = *unmapped = *unwritten = 0; - - bh = head = page_buffers(page); - do { - if (buffer_uptodate(bh) && !buffer_mapped(bh)) - (*unmapped) = 1; - else if (buffer_unwritten(bh) && !buffer_delay(bh)) - clear_buffer_unwritten(bh); - else if (buffer_unwritten(bh)) - (*unwritten) = 1; - else if (buffer_delay(bh)) - (*delalloc) = 1; - } while ((bh = bh->b_this_page) != head); + return mpage_readpages(mapping, pages, nr_pages, xfs_get_block); } - -/* - * writepage: Called from one of two places: - * - * 1. we are flushing a delalloc buffer head. - * - * 2. we are writing out a dirty page. Typically the page dirty - * state is cleared before we get here. In this case is it - * conceivable we have no buffer heads. - * - * For delalloc space on the page we need to allocate space and - * flush it. For unmapped buffer heads on the page we should - * allocate space if the page is uptodate. For any other dirty - * buffer heads on the page we should flush them. - * - * If we detect that a transaction would be required to flush - * the page, we have to check the process flags first, if we - * are already in a transaction or disk I/O during allocations - * is off, we need to fail the writepage and redirty the page. - */ - STATIC int -linvfs_writepage( - struct page *page, - struct writeback_control *wbc) -{ - int error; - int need_trans; - int delalloc, unmapped, unwritten; - struct inode *inode = page->mapping->host; - - xfs_page_trace(XFS_WRITEPAGE_ENTER, inode, page, 0); - - /* - * We need a transaction if: - * 1. There are delalloc buffers on the page - * 2. The page is uptodate and we have unmapped buffers - * 3. The page is uptodate and we have no buffers - * 4. There are unwritten buffers on the page - */ - - if (!page_has_buffers(page)) { - unmapped = 1; - need_trans = 1; - } else { - xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); - if (!PageUptodate(page)) - unmapped = 0; - need_trans = delalloc + unmapped + unwritten; - } - - /* - * If we need a transaction and the process flags say - * we are already in a transaction, or no IO is allowed - * then mark the page dirty again and leave the page - * as is. - */ - if (PFLAGS_TEST_FSTRANS() && need_trans) - goto out_fail; - - /* - * Delay hooking up buffer heads until we have - * made our go/no-go decision. - */ - if (!page_has_buffers(page)) - create_empty_buffers(page, 1 << inode->i_blkbits, 0); - - /* - * Convert delayed allocate, unwritten or unmapped space - * to real space and flush out to disk. - */ - error = xfs_page_state_convert(inode, page, wbc, 1, unmapped); - if (error == -EAGAIN) - goto out_fail; - if (unlikely(error < 0)) - goto out_unlock; - - return 0; - -out_fail: - redirty_page_for_writepage(wbc, page); - unlock_page(page); - return 0; -out_unlock: - unlock_page(page); - return error; -} - -STATIC int -linvfs_invalidate_page( +xfs_vm_invalidatepage( struct page *page, unsigned long offset) { @@ -1381,87 +1452,16 @@ linvfs_invalidate_page( return block_invalidatepage(page, offset); } -/* - * Called to move a page into cleanable state - and from there - * to be released. Possibly the page is already clean. We always - * have buffer heads in this call. - * - * Returns 0 if the page is ok to release, 1 otherwise. - * - * Possible scenarios are: - * - * 1. We are being called to release a page which has been written - * to via regular I/O. buffer heads will be dirty and possibly - * delalloc. If no delalloc buffer heads in this case then we - * can just return zero. - * - * 2. We are called to release a page which has been written via - * mmap, all we need to do is ensure there is no delalloc - * state in the buffer heads, if not we can let the caller - * free them and we should come back later via writepage. - */ -STATIC int -linvfs_release_page( - struct page *page, - gfp_t gfp_mask) -{ - struct inode *inode = page->mapping->host; - int dirty, delalloc, unmapped, unwritten; - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 1, - }; - - xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask); - - xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); - if (!delalloc && !unwritten) - goto free_buffers; - - if (!(gfp_mask & __GFP_FS)) - return 0; - - /* If we are already inside a transaction or the thread cannot - * do I/O, we cannot release this page. - */ - if (PFLAGS_TEST_FSTRANS()) - return 0; - - /* - * Convert delalloc space to real space, do not flush the - * data out to disk, that will be done by the caller. - * Never need to allocate space here - we will always - * come back to writepage in that case. - */ - dirty = xfs_page_state_convert(inode, page, &wbc, 0, 0); - if (dirty == 0 && !unwritten) - goto free_buffers; - return 0; - -free_buffers: - return try_to_free_buffers(page); -} - -STATIC int -linvfs_prepare_write( - struct file *file, - struct page *page, - unsigned int from, - unsigned int to) -{ - return block_prepare_write(page, from, to, linvfs_get_block); -} - -struct address_space_operations linvfs_aops = { - .readpage = linvfs_readpage, - .readpages = linvfs_readpages, - .writepage = linvfs_writepage, +struct address_space_operations xfs_address_space_operations = { + .readpage = xfs_vm_readpage, + .readpages = xfs_vm_readpages, + .writepage = xfs_vm_writepage, .sync_page = block_sync_page, - .releasepage = linvfs_release_page, - .invalidatepage = linvfs_invalidate_page, - .prepare_write = linvfs_prepare_write, + .releasepage = xfs_vm_releasepage, + .invalidatepage = xfs_vm_invalidatepage, + .prepare_write = xfs_vm_prepare_write, .commit_write = generic_commit_write, - .bmap = linvfs_bmap, - .direct_IO = linvfs_direct_IO, + .bmap = xfs_vm_bmap, + .direct_IO = xfs_vm_direct_IO, .migratepage = buffer_migrate_page, }; diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 55339dd5a30d..795699f121d2 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -40,7 +40,7 @@ typedef struct xfs_ioend { struct work_struct io_work; /* xfsdatad work queue */ } xfs_ioend_t; -extern struct address_space_operations linvfs_aops; -extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int); +extern struct address_space_operations xfs_address_space_operations; +extern int xfs_get_block(struct inode *, sector_t, struct buffer_head *, int); #endif /* __XFS_IOPS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 8cdfa4151659..9fb0312665ca 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -1806,13 +1806,12 @@ xfs_flush_buftarg( int __init xfs_buf_init(void) { - int error = -ENOMEM; - #ifdef XFS_BUF_TRACE xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_SLEEP); #endif - xfs_buf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf"); + xfs_buf_zone = kmem_zone_init_flags(sizeof(xfs_buf_t), "xfs_buf", + KM_ZONE_HWALIGN, NULL); if (!xfs_buf_zone) goto out_free_trace_buf; @@ -1840,7 +1839,7 @@ xfs_buf_init(void) #ifdef XFS_BUF_TRACE ktrace_free(xfs_buf_trace_buf); #endif - return error; + return -ENOMEM; } void diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 80eb249f2fa0..b768ea910bbe 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -25,6 +25,8 @@ #include "xfs_mount.h" #include "xfs_export.h" +STATIC struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; + /* * XFS encodes and decodes the fileid portion of NFS filehandles * itself instead of letting the generic NFS code do it. This @@ -37,7 +39,7 @@ */ STATIC struct dentry * -linvfs_decode_fh( +xfs_fs_decode_fh( struct super_block *sb, __u32 *fh, int fh_len, @@ -78,12 +80,12 @@ linvfs_decode_fh( } fh = (__u32 *)&ifid; - return find_exported_dentry(sb, fh, parent, acceptable, context); + return sb->s_export_op->find_exported_dentry(sb, fh, parent, acceptable, context); } STATIC int -linvfs_encode_fh( +xfs_fs_encode_fh( struct dentry *dentry, __u32 *fh, int *max_len, @@ -95,7 +97,7 @@ linvfs_encode_fh( int len; int is64 = 0; #if XFS_BIG_INUMS - vfs_t *vfs = LINVFS_GET_VFS(inode->i_sb); + vfs_t *vfs = vfs_from_sb(inode->i_sb); if (!(vfs->vfs_flag & VFS_32BITINODES)) { /* filesystem may contain 64bit inode numbers */ @@ -130,21 +132,21 @@ linvfs_encode_fh( } STATIC struct dentry * -linvfs_get_dentry( +xfs_fs_get_dentry( struct super_block *sb, void *data) { vnode_t *vp; struct inode *inode; struct dentry *result; - vfs_t *vfsp = LINVFS_GET_VFS(sb); + vfs_t *vfsp = vfs_from_sb(sb); int error; VFS_VGET(vfsp, &vp, (fid_t *)data, error); if (error || vp == NULL) return ERR_PTR(-ESTALE) ; - inode = LINVFS_GET_IP(vp); + inode = vn_to_inode(vp); result = d_alloc_anon(inode); if (!result) { iput(inode); @@ -154,25 +156,20 @@ linvfs_get_dentry( } STATIC struct dentry * -linvfs_get_parent( +xfs_fs_get_parent( struct dentry *child) { int error; vnode_t *vp, *cvp; struct dentry *parent; - struct dentry dotdot; - - dotdot.d_name.name = ".."; - dotdot.d_name.len = 2; - dotdot.d_inode = NULL; cvp = NULL; - vp = LINVFS_GET_VP(child->d_inode); + vp = vn_from_inode(child->d_inode); VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error); if (unlikely(error)) return ERR_PTR(-error); - parent = d_alloc_anon(LINVFS_GET_IP(cvp)); + parent = d_alloc_anon(vn_to_inode(cvp)); if (unlikely(!parent)) { VN_RELE(cvp); return ERR_PTR(-ENOMEM); @@ -180,9 +177,9 @@ linvfs_get_parent( return parent; } -struct export_operations linvfs_export_ops = { - .decode_fh = linvfs_decode_fh, - .encode_fh = linvfs_encode_fh, - .get_parent = linvfs_get_parent, - .get_dentry = linvfs_get_dentry, +struct export_operations xfs_export_operations = { + .decode_fh = xfs_fs_decode_fh, + .encode_fh = xfs_fs_encode_fh, + .get_parent = xfs_fs_get_parent, + .get_dentry = xfs_fs_get_dentry, }; diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index ced4404339c7..185567a6a561 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -43,13 +43,13 @@ #include <linux/dcache.h> #include <linux/smp_lock.h> -static struct vm_operations_struct linvfs_file_vm_ops; +static struct vm_operations_struct xfs_file_vm_ops; #ifdef CONFIG_XFS_DMAPI -static struct vm_operations_struct linvfs_dmapi_file_vm_ops; +static struct vm_operations_struct xfs_dmapi_file_vm_ops; #endif STATIC inline ssize_t -__linvfs_read( +__xfs_file_read( struct kiocb *iocb, char __user *buf, int ioflags, @@ -58,7 +58,7 @@ __linvfs_read( { struct iovec iov = {buf, count}; struct file *file = iocb->ki_filp; - vnode_t *vp = LINVFS_GET_VP(file->f_dentry->d_inode); + vnode_t *vp = vn_from_inode(file->f_dentry->d_inode); ssize_t rval; BUG_ON(iocb->ki_pos != pos); @@ -71,28 +71,28 @@ __linvfs_read( STATIC ssize_t -linvfs_aio_read( +xfs_file_aio_read( struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) { - return __linvfs_read(iocb, buf, IO_ISAIO, count, pos); + return __xfs_file_read(iocb, buf, IO_ISAIO, count, pos); } STATIC ssize_t -linvfs_aio_read_invis( +xfs_file_aio_read_invis( struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) { - return __linvfs_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); + return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); } STATIC inline ssize_t -__linvfs_write( +__xfs_file_write( struct kiocb *iocb, const char __user *buf, int ioflags, @@ -102,7 +102,7 @@ __linvfs_write( struct iovec iov = {(void __user *)buf, count}; struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); ssize_t rval; BUG_ON(iocb->ki_pos != pos); @@ -115,28 +115,28 @@ __linvfs_write( STATIC ssize_t -linvfs_aio_write( +xfs_file_aio_write( struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) { - return __linvfs_write(iocb, buf, IO_ISAIO, count, pos); + return __xfs_file_write(iocb, buf, IO_ISAIO, count, pos); } STATIC ssize_t -linvfs_aio_write_invis( +xfs_file_aio_write_invis( struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) { - return __linvfs_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); + return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); } STATIC inline ssize_t -__linvfs_readv( +__xfs_file_readv( struct file *file, const struct iovec *iov, int ioflags, @@ -144,8 +144,8 @@ __linvfs_readv( loff_t *ppos) { struct inode *inode = file->f_mapping->host; - vnode_t *vp = LINVFS_GET_VP(inode); - struct kiocb kiocb; + vnode_t *vp = vn_from_inode(inode); + struct kiocb kiocb; ssize_t rval; init_sync_kiocb(&kiocb, file); @@ -160,28 +160,28 @@ __linvfs_readv( } STATIC ssize_t -linvfs_readv( +xfs_file_readv( struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *ppos) { - return __linvfs_readv(file, iov, 0, nr_segs, ppos); + return __xfs_file_readv(file, iov, 0, nr_segs, ppos); } STATIC ssize_t -linvfs_readv_invis( +xfs_file_readv_invis( struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *ppos) { - return __linvfs_readv(file, iov, IO_INVIS, nr_segs, ppos); + return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos); } STATIC inline ssize_t -__linvfs_writev( +__xfs_file_writev( struct file *file, const struct iovec *iov, int ioflags, @@ -189,8 +189,8 @@ __linvfs_writev( loff_t *ppos) { struct inode *inode = file->f_mapping->host; - vnode_t *vp = LINVFS_GET_VP(inode); - struct kiocb kiocb; + vnode_t *vp = vn_from_inode(inode); + struct kiocb kiocb; ssize_t rval; init_sync_kiocb(&kiocb, file); @@ -206,34 +206,34 @@ __linvfs_writev( STATIC ssize_t -linvfs_writev( +xfs_file_writev( struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *ppos) { - return __linvfs_writev(file, iov, 0, nr_segs, ppos); + return __xfs_file_writev(file, iov, 0, nr_segs, ppos); } STATIC ssize_t -linvfs_writev_invis( +xfs_file_writev_invis( struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *ppos) { - return __linvfs_writev(file, iov, IO_INVIS, nr_segs, ppos); + return __xfs_file_writev(file, iov, IO_INVIS, nr_segs, ppos); } STATIC ssize_t -linvfs_sendfile( +xfs_file_sendfile( struct file *filp, loff_t *ppos, size_t count, read_actor_t actor, void *target) { - vnode_t *vp = LINVFS_GET_VP(filp->f_dentry->d_inode); + vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); ssize_t rval; VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval); @@ -242,11 +242,11 @@ linvfs_sendfile( STATIC int -linvfs_open( +xfs_file_open( struct inode *inode, struct file *filp) { - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error; if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) @@ -259,11 +259,11 @@ linvfs_open( STATIC int -linvfs_release( +xfs_file_release( struct inode *inode, struct file *filp) { - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error = 0; if (vp) @@ -273,13 +273,13 @@ linvfs_release( STATIC int -linvfs_fsync( +xfs_file_fsync( struct file *filp, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error; int flags = FSYNC_WAIT; @@ -292,7 +292,7 @@ linvfs_fsync( } /* - * linvfs_readdir maps to VOP_READDIR(). + * xfs_file_readdir maps to VOP_READDIR(). * We need to build a uio, cred, ... */ @@ -301,13 +301,13 @@ linvfs_fsync( #ifdef CONFIG_XFS_DMAPI STATIC struct page * -linvfs_filemap_nopage( +xfs_vm_nopage( struct vm_area_struct *area, unsigned long address, int *type) { struct inode *inode = area->vm_file->f_dentry->d_inode; - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); int error; @@ -324,7 +324,7 @@ linvfs_filemap_nopage( STATIC int -linvfs_readdir( +xfs_file_readdir( struct file *filp, void *dirent, filldir_t filldir) @@ -340,7 +340,7 @@ linvfs_readdir( xfs_off_t start_offset, curr_offset; xfs_dirent_t *dbp = NULL; - vp = LINVFS_GET_VP(filp->f_dentry->d_inode); + vp = vn_from_inode(filp->f_dentry->d_inode); ASSERT(vp); /* Try fairly hard to get memory */ @@ -404,39 +404,40 @@ done: STATIC int -linvfs_file_mmap( +xfs_file_mmap( struct file *filp, struct vm_area_struct *vma) { struct inode *ip = filp->f_dentry->d_inode; - vnode_t *vp = LINVFS_GET_VP(ip); - vattr_t va = { .va_mask = XFS_AT_UPDATIME }; + vnode_t *vp = vn_from_inode(ip); + vattr_t vattr; int error; - vma->vm_ops = &linvfs_file_vm_ops; + vma->vm_ops = &xfs_file_vm_ops; #ifdef CONFIG_XFS_DMAPI if (vp->v_vfsp->vfs_flag & VFS_DMI) { - vma->vm_ops = &linvfs_dmapi_file_vm_ops; + vma->vm_ops = &xfs_dmapi_file_vm_ops; } #endif /* CONFIG_XFS_DMAPI */ - VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error); - if (!error) - vn_revalidate(vp); /* update Linux inode flags */ + vattr.va_mask = XFS_AT_UPDATIME; + VOP_SETATTR(vp, &vattr, XFS_AT_UPDATIME, NULL, error); + if (likely(!error)) + __vn_revalidate(vp, &vattr); /* update flags */ return 0; } STATIC long -linvfs_ioctl( +xfs_file_ioctl( struct file *filp, unsigned int cmd, unsigned long arg) { int error; - struct inode *inode = filp->f_dentry->d_inode; - vnode_t *vp = LINVFS_GET_VP(inode); + struct inode *inode = filp->f_dentry->d_inode; + vnode_t *vp = vn_from_inode(inode); VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error); VMODIFY(vp); @@ -451,14 +452,14 @@ linvfs_ioctl( } STATIC long -linvfs_ioctl_invis( +xfs_file_ioctl_invis( struct file *filp, unsigned int cmd, unsigned long arg) { int error; - struct inode *inode = filp->f_dentry->d_inode; - vnode_t *vp = LINVFS_GET_VP(inode); + struct inode *inode = filp->f_dentry->d_inode; + vnode_t *vp = vn_from_inode(inode); ASSERT(vp); VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); @@ -476,11 +477,11 @@ linvfs_ioctl_invis( #ifdef CONFIG_XFS_DMAPI #ifdef HAVE_VMOP_MPROTECT STATIC int -linvfs_mprotect( +xfs_vm_mprotect( struct vm_area_struct *vma, unsigned int newflags) { - vnode_t *vp = LINVFS_GET_VP(vma->vm_file->f_dentry->d_inode); + vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode); int error = 0; if (vp->v_vfsp->vfs_flag & VFS_DMI) { @@ -503,10 +504,10 @@ linvfs_mprotect( * it back online. */ STATIC int -linvfs_open_exec( +xfs_file_open_exec( struct inode *inode) { - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); int error = 0; xfs_inode_t *ip; @@ -527,69 +528,69 @@ open_exec_out: } #endif /* HAVE_FOP_OPEN_EXEC */ -struct file_operations linvfs_file_operations = { +struct file_operations xfs_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, - .readv = linvfs_readv, - .writev = linvfs_writev, - .aio_read = linvfs_aio_read, - .aio_write = linvfs_aio_write, - .sendfile = linvfs_sendfile, - .unlocked_ioctl = linvfs_ioctl, + .readv = xfs_file_readv, + .writev = xfs_file_writev, + .aio_read = xfs_file_aio_read, + .aio_write = xfs_file_aio_write, + .sendfile = xfs_file_sendfile, + .unlocked_ioctl = xfs_file_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = linvfs_compat_ioctl, + .compat_ioctl = xfs_file_compat_ioctl, #endif - .mmap = linvfs_file_mmap, - .open = linvfs_open, - .release = linvfs_release, - .fsync = linvfs_fsync, + .mmap = xfs_file_mmap, + .open = xfs_file_open, + .release = xfs_file_release, + .fsync = xfs_file_fsync, #ifdef HAVE_FOP_OPEN_EXEC - .open_exec = linvfs_open_exec, + .open_exec = xfs_file_open_exec, #endif }; -struct file_operations linvfs_invis_file_operations = { +struct file_operations xfs_invis_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, - .readv = linvfs_readv_invis, - .writev = linvfs_writev_invis, - .aio_read = linvfs_aio_read_invis, - .aio_write = linvfs_aio_write_invis, - .sendfile = linvfs_sendfile, - .unlocked_ioctl = linvfs_ioctl_invis, + .readv = xfs_file_readv_invis, + .writev = xfs_file_writev_invis, + .aio_read = xfs_file_aio_read_invis, + .aio_write = xfs_file_aio_write_invis, + .sendfile = xfs_file_sendfile, + .unlocked_ioctl = xfs_file_ioctl_invis, #ifdef CONFIG_COMPAT - .compat_ioctl = linvfs_compat_invis_ioctl, + .compat_ioctl = xfs_file_compat_invis_ioctl, #endif - .mmap = linvfs_file_mmap, - .open = linvfs_open, - .release = linvfs_release, - .fsync = linvfs_fsync, + .mmap = xfs_file_mmap, + .open = xfs_file_open, + .release = xfs_file_release, + .fsync = xfs_file_fsync, }; -struct file_operations linvfs_dir_operations = { +struct file_operations xfs_dir_file_operations = { .read = generic_read_dir, - .readdir = linvfs_readdir, - .unlocked_ioctl = linvfs_ioctl, + .readdir = xfs_file_readdir, + .unlocked_ioctl = xfs_file_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = linvfs_compat_ioctl, + .compat_ioctl = xfs_file_compat_ioctl, #endif - .fsync = linvfs_fsync, + .fsync = xfs_file_fsync, }; -static struct vm_operations_struct linvfs_file_vm_ops = { +static struct vm_operations_struct xfs_file_vm_ops = { .nopage = filemap_nopage, .populate = filemap_populate, }; #ifdef CONFIG_XFS_DMAPI -static struct vm_operations_struct linvfs_dmapi_file_vm_ops = { - .nopage = linvfs_filemap_nopage, +static struct vm_operations_struct xfs_dmapi_file_vm_ops = { + .nopage = xfs_vm_nopage, .populate = filemap_populate, #ifdef HAVE_VMOP_MPROTECT - .mprotect = linvfs_mprotect, + .mprotect = xfs_vm_mprotect, #endif }; #endif /* CONFIG_XFS_DMAPI */ diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index 4fa4b1a5187e..575f2a790f31 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c @@ -57,7 +57,7 @@ fs_tosspages( int fiopt) { vnode_t *vp = BHV_TO_VNODE(bdp); - struct inode *ip = LINVFS_GET_IP(vp); + struct inode *ip = vn_to_inode(vp); if (VN_CACHED(vp)) truncate_inode_pages(ip->i_mapping, first); @@ -76,7 +76,7 @@ fs_flushinval_pages( int fiopt) { vnode_t *vp = BHV_TO_VNODE(bdp); - struct inode *ip = LINVFS_GET_IP(vp); + struct inode *ip = vn_to_inode(vp); if (VN_CACHED(vp)) { filemap_write_and_wait(ip->i_mapping); @@ -98,7 +98,7 @@ fs_flush_pages( int fiopt) { vnode_t *vp = BHV_TO_VNODE(bdp); - struct inode *ip = LINVFS_GET_IP(vp); + struct inode *ip = vn_to_inode(vp); if (VN_CACHED(vp)) { filemap_fdatawrite(ip->i_mapping); diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 4db47790415c..84478491609b 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -138,7 +138,7 @@ xfs_find_handle( } /* we need the vnode */ - vp = LINVFS_GET_VP(inode); + vp = vn_from_inode(inode); /* now we can grab the fsid */ memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t)); @@ -256,7 +256,7 @@ xfs_vget_fsop_handlereq( } vpp = XFS_ITOV(ip); - inodep = LINVFS_GET_IP(vpp); + inodep = vn_to_inode(vpp); xfs_iunlock(ip, XFS_ILOCK_SHARED); *vp = vpp; @@ -344,7 +344,7 @@ xfs_open_by_handle( return -XFS_ERROR(-PTR_ERR(filp)); } if (inode->i_mode & S_IFREG) - filp->f_op = &linvfs_invis_file_operations; + filp->f_op = &xfs_invis_file_operations; fd_install(new_fd, filp); return new_fd; @@ -715,7 +715,7 @@ xfs_ioctl( xfs_inode_t *ip; xfs_mount_t *mp; - vp = LINVFS_GET_VP(inode); + vp = vn_from_inode(inode); vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address); @@ -1160,105 +1160,129 @@ xfs_ioc_xattr( void __user *arg) { struct fsxattr fa; - vattr_t va; - int error; + struct vattr *vattr; + int error = 0; int attr_flags; unsigned int flags; + vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); + if (unlikely(!vattr)) + return -ENOMEM; + switch (cmd) { case XFS_IOC_FSGETXATTR: { - va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ - XFS_AT_NEXTENTS | XFS_AT_PROJID; - VOP_GETATTR(vp, &va, 0, NULL, error); - if (error) - return -error; + vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ + XFS_AT_NEXTENTS | XFS_AT_PROJID; + VOP_GETATTR(vp, vattr, 0, NULL, error); + if (unlikely(error)) { + error = -error; + break; + } - fa.fsx_xflags = va.va_xflags; - fa.fsx_extsize = va.va_extsize; - fa.fsx_nextents = va.va_nextents; - fa.fsx_projid = va.va_projid; + fa.fsx_xflags = vattr->va_xflags; + fa.fsx_extsize = vattr->va_extsize; + fa.fsx_nextents = vattr->va_nextents; + fa.fsx_projid = vattr->va_projid; - if (copy_to_user(arg, &fa, sizeof(fa))) - return -XFS_ERROR(EFAULT); - return 0; + if (copy_to_user(arg, &fa, sizeof(fa))) { + error = -EFAULT; + break; + } + break; } case XFS_IOC_FSSETXATTR: { - if (copy_from_user(&fa, arg, sizeof(fa))) - return -XFS_ERROR(EFAULT); + if (copy_from_user(&fa, arg, sizeof(fa))) { + error = -EFAULT; + break; + } attr_flags = 0; if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) attr_flags |= ATTR_NONBLOCK; - va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; - va.va_xflags = fa.fsx_xflags; - va.va_extsize = fa.fsx_extsize; - va.va_projid = fa.fsx_projid; + vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; + vattr->va_xflags = fa.fsx_xflags; + vattr->va_extsize = fa.fsx_extsize; + vattr->va_projid = fa.fsx_projid; - VOP_SETATTR(vp, &va, attr_flags, NULL, error); - if (!error) - vn_revalidate(vp); /* update Linux inode flags */ - return -error; + VOP_SETATTR(vp, vattr, attr_flags, NULL, error); + if (likely(!error)) + __vn_revalidate(vp, vattr); /* update flags */ + error = -error; + break; } case XFS_IOC_FSGETXATTRA: { - va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ - XFS_AT_ANEXTENTS | XFS_AT_PROJID; - VOP_GETATTR(vp, &va, 0, NULL, error); - if (error) - return -error; + vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ + XFS_AT_ANEXTENTS | XFS_AT_PROJID; + VOP_GETATTR(vp, vattr, 0, NULL, error); + if (unlikely(error)) { + error = -error; + break; + } - fa.fsx_xflags = va.va_xflags; - fa.fsx_extsize = va.va_extsize; - fa.fsx_nextents = va.va_anextents; - fa.fsx_projid = va.va_projid; + fa.fsx_xflags = vattr->va_xflags; + fa.fsx_extsize = vattr->va_extsize; + fa.fsx_nextents = vattr->va_anextents; + fa.fsx_projid = vattr->va_projid; - if (copy_to_user(arg, &fa, sizeof(fa))) - return -XFS_ERROR(EFAULT); - return 0; + if (copy_to_user(arg, &fa, sizeof(fa))) { + error = -EFAULT; + break; + } + break; } case XFS_IOC_GETXFLAGS: { flags = xfs_di2lxflags(ip->i_d.di_flags); if (copy_to_user(arg, &flags, sizeof(flags))) - return -XFS_ERROR(EFAULT); - return 0; + error = -EFAULT; + break; } case XFS_IOC_SETXFLAGS: { - if (copy_from_user(&flags, arg, sizeof(flags))) - return -XFS_ERROR(EFAULT); + if (copy_from_user(&flags, arg, sizeof(flags))) { + error = -EFAULT; + break; + } if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ - LINUX_XFLAG_SYNC)) - return -XFS_ERROR(EOPNOTSUPP); + LINUX_XFLAG_SYNC)) { + error = -EOPNOTSUPP; + break; + } attr_flags = 0; if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) attr_flags |= ATTR_NONBLOCK; - va.va_mask = XFS_AT_XFLAGS; - va.va_xflags = xfs_merge_ioc_xflags(flags, - xfs_ip2xflags(ip)); + vattr->va_mask = XFS_AT_XFLAGS; + vattr->va_xflags = xfs_merge_ioc_xflags(flags, + xfs_ip2xflags(ip)); - VOP_SETATTR(vp, &va, attr_flags, NULL, error); - if (!error) - vn_revalidate(vp); /* update Linux inode flags */ - return -error; + VOP_SETATTR(vp, vattr, attr_flags, NULL, error); + if (likely(!error)) + __vn_revalidate(vp, vattr); /* update flags */ + error = -error; + break; } case XFS_IOC_GETVERSION: { - flags = LINVFS_GET_IP(vp)->i_generation; + flags = vn_to_inode(vp)->i_generation; if (copy_to_user(arg, &flags, sizeof(flags))) - return -XFS_ERROR(EFAULT); - return 0; + error = -EFAULT; + break; } default: - return -ENOTTY; + error = -ENOTTY; + break; } + + kfree(vattr); + return error; } STATIC int diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index a7c9ba1a9f7b..b6321abd9a81 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -107,11 +107,11 @@ xfs_ioctl32_bulkstat( #endif STATIC long -__linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) +xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) { int error; struct inode *inode = f->f_dentry->d_inode; - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_to_inode(inode); switch (cmd) { case XFS_IOC_DIOINFO: @@ -196,19 +196,19 @@ __linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) } long -linvfs_compat_ioctl( +xfs_file_compat_ioctl( struct file *f, unsigned cmd, unsigned long arg) { - return __linvfs_compat_ioctl(0, f, cmd, arg); + return xfs_compat_ioctl(0, f, cmd, arg); } long -linvfs_compat_invis_ioctl( +xfs_file_compat_invis_ioctl( struct file *f, unsigned cmd, unsigned long arg) { - return __linvfs_compat_ioctl(IO_INVIS, f, cmd, arg); + return xfs_compat_ioctl(IO_INVIS, f, cmd, arg); } diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h index 011c273bec50..02de6e62ee37 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.h +++ b/fs/xfs/linux-2.6/xfs_ioctl32.h @@ -18,7 +18,7 @@ #ifndef __XFS_IOCTL32_H__ #define __XFS_IOCTL32_H__ -extern long linvfs_compat_ioctl(struct file *, unsigned, unsigned long); -extern long linvfs_compat_invis_ioctl(struct file *f, unsigned, unsigned long); +extern long xfs_file_compat_ioctl(struct file *, unsigned, unsigned long); +extern long xfs_file_compat_invis_ioctl(struct file *, unsigned, unsigned long); #endif /* __XFS_IOCTL32_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index d7f6f2d8ac8e..af487437bd7e 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -106,7 +106,7 @@ xfs_ichgtime( xfs_inode_t *ip, int flags) { - struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); + struct inode *inode = vn_to_inode(XFS_ITOV(ip)); timespec_t tv; nanotime(&tv); @@ -198,22 +198,22 @@ xfs_ichgtime_fast( * Pull the link count and size up from the xfs inode to the linux inode */ STATIC void -validate_fields( - struct inode *ip) +xfs_validate_fields( + struct inode *ip, + struct vattr *vattr) { - vnode_t *vp = LINVFS_GET_VP(ip); - vattr_t va; + vnode_t *vp = vn_from_inode(ip); int error; - va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; - VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error); - if (likely(!error)) { - ip->i_nlink = va.va_nlink; - ip->i_blocks = va.va_nblocks; + vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; + VOP_GETATTR(vp, vattr, ATTR_LAZY, NULL, error); + if (likely(!error)) { + ip->i_nlink = vattr->va_nlink; + ip->i_blocks = vattr->va_nblocks; - /* we're under i_mutex so i_size can't change under us */ - if (i_size_read(ip) != va.va_size) - i_size_write(ip, va.va_size); + /* we're under i_sem so i_size can't change under us */ + if (i_size_read(ip) != vattr->va_size) + i_size_write(ip, vattr->va_size); } } @@ -224,11 +224,11 @@ validate_fields( * inode, of course, such that log replay can't cause these to be lost). */ STATIC int -linvfs_init_security( +xfs_init_security( struct vnode *vp, struct inode *dir) { - struct inode *ip = LINVFS_GET_IP(vp); + struct inode *ip = vn_to_inode(vp); size_t length; void *value; char *name; @@ -257,46 +257,46 @@ linvfs_init_security( * XXX(hch): nfsd is broken, better fix it instead. */ STATIC inline int -has_fs_struct(struct task_struct *task) +xfs_has_fs_struct(struct task_struct *task) { return (task->fs != init_task.fs); } STATIC inline void -cleanup_inode( +xfs_cleanup_inode( vnode_t *dvp, vnode_t *vp, - struct dentry *dentry, + struct dentry *dentry, int mode) { struct dentry teardown = {}; - int err2; + int error; /* Oh, the horror. - * If we can't add the ACL or we fail in - * linvfs_init_security we must back out. + * If we can't add the ACL or we fail in + * xfs_init_security we must back out. * ENOSPC can hit here, among other things. */ - teardown.d_inode = LINVFS_GET_IP(vp); + teardown.d_inode = vn_to_inode(vp); teardown.d_name = dentry->d_name; if (S_ISDIR(mode)) - VOP_RMDIR(dvp, &teardown, NULL, err2); + VOP_RMDIR(dvp, &teardown, NULL, error); else - VOP_REMOVE(dvp, &teardown, NULL, err2); + VOP_REMOVE(dvp, &teardown, NULL, error); VN_RELE(vp); } STATIC int -linvfs_mknod( +xfs_vn_mknod( struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode *ip; - vattr_t va; - vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); + vattr_t vattr = { 0 }; + vnode_t *vp = NULL, *dvp = vn_from_inode(dir); xfs_acl_t *default_acl = NULL; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; int error; @@ -305,99 +305,98 @@ linvfs_mknod( * Irix uses Missed'em'V split, but doesn't want to see * the upper 5 bits of (14bit) major. */ - if (!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff) + if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff)) return -EINVAL; - if (test_default_acl && test_default_acl(dvp)) { - if (!_ACL_ALLOC(default_acl)) + if (unlikely(test_default_acl && test_default_acl(dvp))) { + if (!_ACL_ALLOC(default_acl)) { return -ENOMEM; + } if (!_ACL_GET_DEFAULT(dvp, default_acl)) { _ACL_FREE(default_acl); default_acl = NULL; } } - if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current)) + if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current)) mode &= ~current->fs->umask; - memset(&va, 0, sizeof(va)); - va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; - va.va_mode = mode; + vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE; + vattr.va_mode = mode; switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: - va.va_rdev = sysv_encode_dev(rdev); - va.va_mask |= XFS_AT_RDEV; + vattr.va_rdev = sysv_encode_dev(rdev); + vattr.va_mask |= XFS_AT_RDEV; /*FALLTHROUGH*/ case S_IFREG: - VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); + VOP_CREATE(dvp, dentry, &vattr, &vp, NULL, error); break; case S_IFDIR: - VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); + VOP_MKDIR(dvp, dentry, &vattr, &vp, NULL, error); break; default: error = EINVAL; break; } - if (!error) - { - error = linvfs_init_security(vp, dir); + if (unlikely(!error)) { + error = xfs_init_security(vp, dir); if (error) - cleanup_inode(dvp, vp, dentry, mode); + xfs_cleanup_inode(dvp, vp, dentry, mode); } - if (default_acl) { + if (unlikely(default_acl)) { if (!error) { - error = _ACL_INHERIT(vp, &va, default_acl); - if (!error) + error = _ACL_INHERIT(vp, &vattr, default_acl); + if (!error) VMODIFY(vp); else - cleanup_inode(dvp, vp, dentry, mode); + xfs_cleanup_inode(dvp, vp, dentry, mode); } _ACL_FREE(default_acl); } - if (!error) { + if (likely(!error)) { ASSERT(vp); - ip = LINVFS_GET_IP(vp); + ip = vn_to_inode(vp); if (S_ISCHR(mode) || S_ISBLK(mode)) ip->i_rdev = rdev; else if (S_ISDIR(mode)) - validate_fields(ip); + xfs_validate_fields(ip, &vattr); d_instantiate(dentry, ip); - validate_fields(dir); + xfs_validate_fields(dir, &vattr); } return -error; } STATIC int -linvfs_create( +xfs_vn_create( struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { - return linvfs_mknod(dir, dentry, mode, 0); + return xfs_vn_mknod(dir, dentry, mode, 0); } STATIC int -linvfs_mkdir( +xfs_vn_mkdir( struct inode *dir, struct dentry *dentry, int mode) { - return linvfs_mknod(dir, dentry, mode|S_IFDIR, 0); + return xfs_vn_mknod(dir, dentry, mode|S_IFDIR, 0); } STATIC struct dentry * -linvfs_lookup( +xfs_vn_lookup( struct inode *dir, struct dentry *dentry, struct nameidata *nd) { - struct vnode *vp = LINVFS_GET_VP(dir), *cvp; + struct vnode *vp = vn_from_inode(dir), *cvp; int error; if (dentry->d_name.len >= MAXNAMELEN) @@ -411,11 +410,11 @@ linvfs_lookup( return NULL; } - return d_splice_alias(LINVFS_GET_IP(cvp), dentry); + return d_splice_alias(vn_to_inode(cvp), dentry); } STATIC int -linvfs_link( +xfs_vn_link( struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) @@ -423,99 +422,102 @@ linvfs_link( struct inode *ip; /* inode of guy being linked to */ vnode_t *tdvp; /* target directory for new name/link */ vnode_t *vp; /* vp of name being linked */ + vattr_t vattr; int error; ip = old_dentry->d_inode; /* inode being linked to */ if (S_ISDIR(ip->i_mode)) return -EPERM; - tdvp = LINVFS_GET_VP(dir); - vp = LINVFS_GET_VP(ip); + tdvp = vn_from_inode(dir); + vp = vn_from_inode(ip); VOP_LINK(tdvp, vp, dentry, NULL, error); - if (!error) { + if (likely(!error)) { VMODIFY(tdvp); VN_HOLD(vp); - validate_fields(ip); + xfs_validate_fields(ip, &vattr); d_instantiate(dentry, ip); } return -error; } STATIC int -linvfs_unlink( +xfs_vn_unlink( struct inode *dir, struct dentry *dentry) { struct inode *inode; vnode_t *dvp; /* directory containing name to remove */ + vattr_t vattr; int error; inode = dentry->d_inode; - dvp = LINVFS_GET_VP(dir); + dvp = vn_from_inode(dir); VOP_REMOVE(dvp, dentry, NULL, error); - if (!error) { - validate_fields(dir); /* For size only */ - validate_fields(inode); + if (likely(!error)) { + xfs_validate_fields(dir, &vattr); /* size needs update */ + xfs_validate_fields(inode, &vattr); } - return -error; } STATIC int -linvfs_symlink( +xfs_vn_symlink( struct inode *dir, struct dentry *dentry, const char *symname) { struct inode *ip; - vattr_t va; + vattr_t vattr = { 0 }; vnode_t *dvp; /* directory containing name of symlink */ vnode_t *cvp; /* used to lookup symlink to put in dentry */ int error; - dvp = LINVFS_GET_VP(dir); + dvp = vn_from_inode(dir); cvp = NULL; - memset(&va, 0, sizeof(va)); - va.va_mode = S_IFLNK | + vattr.va_mode = S_IFLNK | (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); - va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; + vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE; error = 0; - VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error); + VOP_SYMLINK(dvp, dentry, &vattr, (char *)symname, &cvp, NULL, error); if (likely(!error && cvp)) { - error = linvfs_init_security(cvp, dir); + error = xfs_init_security(cvp, dir); if (likely(!error)) { - ip = LINVFS_GET_IP(cvp); + ip = vn_to_inode(cvp); d_instantiate(dentry, ip); - validate_fields(dir); - validate_fields(ip); + xfs_validate_fields(dir, &vattr); + xfs_validate_fields(ip, &vattr); + } else { + xfs_cleanup_inode(dvp, cvp, dentry, 0); } } return -error; } STATIC int -linvfs_rmdir( +xfs_vn_rmdir( struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; - vnode_t *dvp = LINVFS_GET_VP(dir); + vnode_t *dvp = vn_from_inode(dir); + vattr_t vattr; int error; VOP_RMDIR(dvp, dentry, NULL, error); - if (!error) { - validate_fields(inode); - validate_fields(dir); + if (likely(!error)) { + xfs_validate_fields(inode, &vattr); + xfs_validate_fields(dir, &vattr); } return -error; } STATIC int -linvfs_rename( +xfs_vn_rename( struct inode *odir, struct dentry *odentry, struct inode *ndir, @@ -524,22 +526,21 @@ linvfs_rename( struct inode *new_inode = ndentry->d_inode; vnode_t *fvp; /* from directory */ vnode_t *tvp; /* target directory */ + vattr_t vattr; int error; - fvp = LINVFS_GET_VP(odir); - tvp = LINVFS_GET_VP(ndir); + fvp = vn_from_inode(odir); + tvp = vn_from_inode(ndir); VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); - if (error) - return -error; - - if (new_inode) - validate_fields(new_inode); - - validate_fields(odir); - if (ndir != odir) - validate_fields(ndir); - return 0; + if (likely(!error)) { + if (new_inode) + xfs_validate_fields(new_inode, &vattr); + xfs_validate_fields(odir, &vattr); + if (ndir != odir) + xfs_validate_fields(ndir, &vattr); + } + return -error; } /* @@ -548,7 +549,7 @@ linvfs_rename( * uio is kmalloced for this reason... */ STATIC void * -linvfs_follow_link( +xfs_vn_follow_link( struct dentry *dentry, struct nameidata *nd) { @@ -574,7 +575,7 @@ linvfs_follow_link( return NULL; } - vp = LINVFS_GET_VP(dentry->d_inode); + vp = vn_from_inode(dentry->d_inode); iov.iov_base = link; iov.iov_len = MAXPATHLEN; @@ -599,7 +600,7 @@ linvfs_follow_link( } STATIC void -linvfs_put_link( +xfs_vn_put_link( struct dentry *dentry, struct nameidata *nd, void *p) @@ -612,12 +613,12 @@ linvfs_put_link( #ifdef CONFIG_XFS_POSIX_ACL STATIC int -linvfs_permission( +xfs_vn_permission( struct inode *inode, int mode, struct nameidata *nd) { - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error; mode <<= 6; /* convert from linux to vnode access bits */ @@ -625,17 +626,17 @@ linvfs_permission( return -error; } #else -#define linvfs_permission NULL +#define xfs_vn_permission NULL #endif STATIC int -linvfs_getattr( +xfs_vn_getattr( struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct inode *inode = dentry->d_inode; - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error = 0; if (unlikely(vp->v_flag & VMODIFIED)) @@ -646,18 +647,17 @@ linvfs_getattr( } STATIC int -linvfs_setattr( +xfs_vn_setattr( struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; - vnode_t *vp = LINVFS_GET_VP(inode); - vattr_t vattr; + vnode_t *vp = vn_from_inode(inode); + vattr_t vattr = { 0 }; int flags = 0; int error; - memset(&vattr, 0, sizeof(vattr_t)); if (ia_valid & ATTR_UID) { vattr.va_mask |= XFS_AT_UID; vattr.va_uid = attr->ia_uid; @@ -699,28 +699,27 @@ linvfs_setattr( #endif VOP_SETATTR(vp, &vattr, flags, NULL, error); - if (error) - return -error; - vn_revalidate(vp); - return error; + if (likely(!error)) + __vn_revalidate(vp, &vattr); + return -error; } STATIC void -linvfs_truncate( +xfs_vn_truncate( struct inode *inode) { - block_truncate_page(inode->i_mapping, inode->i_size, linvfs_get_block); + block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_block); } STATIC int -linvfs_setxattr( +xfs_vn_setxattr( struct dentry *dentry, const char *name, const void *data, size_t size, int flags) { - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); + vnode_t *vp = vn_from_inode(dentry->d_inode); char *attr = (char *)name; attrnames_t *namesp; int xflags = 0; @@ -744,13 +743,13 @@ linvfs_setxattr( } STATIC ssize_t -linvfs_getxattr( +xfs_vn_getxattr( struct dentry *dentry, const char *name, void *data, size_t size) { - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); + vnode_t *vp = vn_from_inode(dentry->d_inode); char *attr = (char *)name; attrnames_t *namesp; int xflags = 0; @@ -774,12 +773,12 @@ linvfs_getxattr( } STATIC ssize_t -linvfs_listxattr( +xfs_vn_listxattr( struct dentry *dentry, char *data, size_t size) { - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); + vnode_t *vp = vn_from_inode(dentry->d_inode); int error, xflags = ATTR_KERNAMELS; ssize_t result; @@ -794,11 +793,11 @@ linvfs_listxattr( } STATIC int -linvfs_removexattr( +xfs_vn_removexattr( struct dentry *dentry, const char *name) { - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); + vnode_t *vp = vn_from_inode(dentry->d_inode); char *attr = (char *)name; attrnames_t *namesp; int xflags = 0; @@ -816,45 +815,45 @@ linvfs_removexattr( } -struct inode_operations linvfs_file_inode_operations = { - .permission = linvfs_permission, - .truncate = linvfs_truncate, - .getattr = linvfs_getattr, - .setattr = linvfs_setattr, - .setxattr = linvfs_setxattr, - .getxattr = linvfs_getxattr, - .listxattr = linvfs_listxattr, - .removexattr = linvfs_removexattr, +struct inode_operations xfs_inode_operations = { + .permission = xfs_vn_permission, + .truncate = xfs_vn_truncate, + .getattr = xfs_vn_getattr, + .setattr = xfs_vn_setattr, + .setxattr = xfs_vn_setxattr, + .getxattr = xfs_vn_getxattr, + .listxattr = xfs_vn_listxattr, + .removexattr = xfs_vn_removexattr, }; -struct inode_operations linvfs_dir_inode_operations = { - .create = linvfs_create, - .lookup = linvfs_lookup, - .link = linvfs_link, - .unlink = linvfs_unlink, - .symlink = linvfs_symlink, - .mkdir = linvfs_mkdir, - .rmdir = linvfs_rmdir, - .mknod = linvfs_mknod, - .rename = linvfs_rename, - .permission = linvfs_permission, - .getattr = linvfs_getattr, - .setattr = linvfs_setattr, - .setxattr = linvfs_setxattr, - .getxattr = linvfs_getxattr, - .listxattr = linvfs_listxattr, - .removexattr = linvfs_removexattr, +struct inode_operations xfs_dir_inode_operations = { + .create = xfs_vn_create, + .lookup = xfs_vn_lookup, + .link = xfs_vn_link, + .unlink = xfs_vn_unlink, + .symlink = xfs_vn_symlink, + .mkdir = xfs_vn_mkdir, + .rmdir = xfs_vn_rmdir, + .mknod = xfs_vn_mknod, + .rename = xfs_vn_rename, + .permission = xfs_vn_permission, + .getattr = xfs_vn_getattr, + .setattr = xfs_vn_setattr, + .setxattr = xfs_vn_setxattr, + .getxattr = xfs_vn_getxattr, + .listxattr = xfs_vn_listxattr, + .removexattr = xfs_vn_removexattr, }; -struct inode_operations linvfs_symlink_inode_operations = { +struct inode_operations xfs_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = linvfs_follow_link, - .put_link = linvfs_put_link, - .permission = linvfs_permission, - .getattr = linvfs_getattr, - .setattr = linvfs_setattr, - .setxattr = linvfs_setxattr, - .getxattr = linvfs_getxattr, - .listxattr = linvfs_listxattr, - .removexattr = linvfs_removexattr, + .follow_link = xfs_vn_follow_link, + .put_link = xfs_vn_put_link, + .permission = xfs_vn_permission, + .getattr = xfs_vn_getattr, + .setattr = xfs_vn_setattr, + .setxattr = xfs_vn_setxattr, + .getxattr = xfs_vn_getxattr, + .listxattr = xfs_vn_listxattr, + .removexattr = xfs_vn_removexattr, }; diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index 6899a6b4a50a..a8417d7af5f9 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h @@ -18,13 +18,13 @@ #ifndef __XFS_IOPS_H__ #define __XFS_IOPS_H__ -extern struct inode_operations linvfs_file_inode_operations; -extern struct inode_operations linvfs_dir_inode_operations; -extern struct inode_operations linvfs_symlink_inode_operations; +extern struct inode_operations xfs_inode_operations; +extern struct inode_operations xfs_dir_inode_operations; +extern struct inode_operations xfs_symlink_inode_operations; -extern struct file_operations linvfs_file_operations; -extern struct file_operations linvfs_invis_file_operations; -extern struct file_operations linvfs_dir_operations; +extern struct file_operations xfs_file_operations; +extern struct file_operations xfs_dir_file_operations; +extern struct file_operations xfs_invis_file_operations; extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, int, unsigned int, void __user *); diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 67389b745526..1fe09f2d6519 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -73,6 +73,9 @@ #include <linux/list.h> #include <linux/proc_fs.h> #include <linux/sort.h> +#include <linux/cpu.h> +#include <linux/notifier.h> +#include <linux/delay.h> #include <asm/page.h> #include <asm/div64.h> @@ -100,6 +103,11 @@ */ #undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */ #define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */ +#ifdef CONFIG_SMP +#define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ +#else +#undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ +#endif /* * State flag for unwritten extent buffers. @@ -226,7 +234,7 @@ BUFFER_FNS(PrivateStart, unwritten); #define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL) #define xfs_stack_trace() dump_stack() #define xfs_itruncate_data(ip, off) \ - (-vmtruncate(LINVFS_GET_IP(XFS_ITOV(ip)), (off))) + (-vmtruncate(vn_to_inode(XFS_ITOV(ip)), (off))) #define xfs_statvfs_fsid(statp, mp) \ ({ u64 id = huge_encode_dev((mp)->m_ddev_targp->bt_dev); \ __kernel_fsid_t *fsid = &(statp)->f_fsid; \ diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index e0ab45fbfebd..0169360475c4 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -83,7 +83,7 @@ xfs_rw_enter_trace( (void *)((unsigned long)ioflags), (void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)), (void *)((unsigned long)(io->io_new_size & 0xffffffff)), - (void *)NULL, + (void *)((unsigned long)current_pid()), (void *)NULL, (void *)NULL, (void *)NULL, @@ -113,7 +113,7 @@ xfs_inval_cached_trace( (void *)((unsigned long)(first & 0xffffffff)), (void *)((unsigned long)((last >> 32) & 0xffffffff)), (void *)((unsigned long)(last & 0xffffffff)), - (void *)NULL, + (void *)((unsigned long)current_pid()), (void *)NULL, (void *)NULL, (void *)NULL, @@ -249,9 +249,8 @@ xfs_read( if (n < size) size = n; - if (XFS_FORCED_SHUTDOWN(mp)) { + if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; - } if (unlikely(ioflags & IO_ISDIRECT)) mutex_lock(&inode->i_mutex); @@ -267,10 +266,14 @@ xfs_read( dmflags, &locktype); if (ret) { xfs_iunlock(ip, XFS_IOLOCK_SHARED); - goto unlock_isem; + goto unlock_mutex; } } + if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp))) + VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(*offset)), + -1, FI_REMAPF_LOCKED); + xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, (void *)iovp, segs, *offset, ioflags); ret = __generic_file_aio_read(iocb, iovp, segs, offset); @@ -281,7 +284,7 @@ xfs_read( xfs_iunlock(ip, XFS_IOLOCK_SHARED); -unlock_isem: +unlock_mutex: if (unlikely(ioflags & IO_ISDIRECT)) mutex_unlock(&inode->i_mutex); return ret; @@ -432,7 +435,7 @@ xfs_zero_eof( xfs_fsize_t isize, /* current inode size */ xfs_fsize_t end_size) /* terminal inode size */ { - struct inode *ip = LINVFS_GET_IP(vp); + struct inode *ip = vn_to_inode(vp); xfs_fileoff_t start_zero_fsb; xfs_fileoff_t end_zero_fsb; xfs_fileoff_t zero_count_fsb; @@ -573,7 +576,7 @@ xfs_write( vrwlock_t locktype; size_t ocount = 0, count; loff_t pos; - int need_isem = 1, need_flush = 0; + int need_i_mutex = 1, need_flush = 0; XFS_STATS_INC(xs_write_calls); @@ -622,14 +625,14 @@ xfs_write( return XFS_ERROR(-EINVAL); if (!VN_CACHED(vp) && pos < i_size_read(inode)) - need_isem = 0; + need_i_mutex = 0; if (VN_CACHED(vp)) need_flush = 1; } relock: - if (need_isem) { + if (need_i_mutex) { iolock = XFS_IOLOCK_EXCL; locktype = VRWLOCK_WRITE; @@ -651,7 +654,7 @@ start: S_ISBLK(inode->i_mode)); if (error) { xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); - goto out_unlock_isem; + goto out_unlock_mutex; } new_size = pos + count; @@ -663,7 +666,7 @@ start: loff_t savedsize = pos; int dmflags = FILP_DELAY_FLAG(file); - if (need_isem) + if (need_i_mutex) dmflags |= DM_FLAGS_IMUX; xfs_iunlock(xip, XFS_ILOCK_EXCL); @@ -672,7 +675,7 @@ start: dmflags, &locktype); if (error) { xfs_iunlock(xip, iolock); - goto out_unlock_isem; + goto out_unlock_mutex; } xfs_ilock(xip, XFS_ILOCK_EXCL); eventsent = 1; @@ -710,7 +713,7 @@ start: isize, pos + count); if (error) { xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); - goto out_unlock_isem; + goto out_unlock_mutex; } } xfs_iunlock(xip, XFS_ILOCK_EXCL); @@ -731,7 +734,7 @@ start: error = -remove_suid(file->f_dentry); if (unlikely(error)) { xfs_iunlock(xip, iolock); - goto out_unlock_isem; + goto out_unlock_mutex; } } @@ -747,14 +750,14 @@ retry: -1, FI_REMAPF_LOCKED); } - if (need_isem) { + if (need_i_mutex) { /* demote the lock now the cached pages are gone */ XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL); mutex_unlock(&inode->i_mutex); iolock = XFS_IOLOCK_SHARED; locktype = VRWLOCK_WRITE_DIRECT; - need_isem = 0; + need_i_mutex = 0; } xfs_rw_enter_trace(XFS_DIOWR_ENTER, io, (void *)iovp, segs, @@ -772,7 +775,7 @@ retry: pos += ret; count -= ret; - need_isem = 1; + need_i_mutex = 1; ioflags &= ~IO_ISDIRECT; xfs_iunlock(xip, iolock); goto relock; @@ -794,14 +797,14 @@ retry: !(ioflags & IO_INVIS)) { xfs_rwunlock(bdp, locktype); - if (need_isem) + if (need_i_mutex) mutex_unlock(&inode->i_mutex); error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp, DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL, 0, 0, 0); /* Delay flag intentionally unused */ if (error) goto out_nounlocks; - if (need_isem) + if (need_i_mutex) mutex_lock(&inode->i_mutex); xfs_rwlock(bdp, locktype); pos = xip->i_d.di_size; @@ -905,9 +908,9 @@ retry: if (error) goto out_unlock_internal; } - + xfs_rwunlock(bdp, locktype); - if (need_isem) + if (need_i_mutex) mutex_unlock(&inode->i_mutex); error = sync_page_range(inode, mapping, pos, ret); @@ -918,8 +921,8 @@ retry: out_unlock_internal: xfs_rwunlock(bdp, locktype); - out_unlock_isem: - if (need_isem) + out_unlock_mutex: + if (need_i_mutex) mutex_unlock(&inode->i_mutex); out_nounlocks: return -error; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index f22e426d9e42..8355faf8ffde 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -59,8 +59,8 @@ #include <linux/writeback.h> #include <linux/kthread.h> -STATIC struct quotactl_ops linvfs_qops; -STATIC struct super_operations linvfs_sops; +STATIC struct quotactl_ops xfs_quotactl_operations; +STATIC struct super_operations xfs_super_operations; STATIC kmem_zone_t *xfs_vnode_zone; STATIC kmem_zone_t *xfs_ioend_zone; mempool_t *xfs_ioend_pool; @@ -76,8 +76,6 @@ xfs_args_allocate( strncpy(args->fsname, sb->s_id, MAXNAMELEN); /* Copy the already-parsed mount(2) flags we're interested in */ - if (sb->s_flags & MS_NOATIME) - args->flags |= XFSMNT_NOATIME; if (sb->s_flags & MS_DIRSYNC) args->flags |= XFSMNT_DIRSYNC; if (sb->s_flags & MS_SYNCHRONOUS) @@ -129,21 +127,21 @@ xfs_set_inodeops( { switch (inode->i_mode & S_IFMT) { case S_IFREG: - inode->i_op = &linvfs_file_inode_operations; - inode->i_fop = &linvfs_file_operations; - inode->i_mapping->a_ops = &linvfs_aops; + inode->i_op = &xfs_inode_operations; + inode->i_fop = &xfs_file_operations; + inode->i_mapping->a_ops = &xfs_address_space_operations; break; case S_IFDIR: - inode->i_op = &linvfs_dir_inode_operations; - inode->i_fop = &linvfs_dir_operations; + inode->i_op = &xfs_dir_inode_operations; + inode->i_fop = &xfs_dir_file_operations; break; case S_IFLNK: - inode->i_op = &linvfs_symlink_inode_operations; + inode->i_op = &xfs_symlink_inode_operations; if (inode->i_blocks) - inode->i_mapping->a_ops = &linvfs_aops; + inode->i_mapping->a_ops = &xfs_address_space_operations; break; default: - inode->i_op = &linvfs_file_inode_operations; + inode->i_op = &xfs_inode_operations; init_special_inode(inode, inode->i_mode, inode->i_rdev); break; } @@ -155,7 +153,7 @@ xfs_revalidate_inode( vnode_t *vp, xfs_inode_t *ip) { - struct inode *inode = LINVFS_GET_IP(vp); + struct inode *inode = vn_to_inode(vp); inode->i_mode = ip->i_d.di_mode; inode->i_nlink = ip->i_d.di_nlink; @@ -212,7 +210,7 @@ xfs_initialize_vnode( int unlock) { xfs_inode_t *ip = XFS_BHVTOI(inode_bhv); - struct inode *inode = LINVFS_GET_IP(vp); + struct inode *inode = vn_to_inode(vp); if (!inode_bhv->bd_vobj) { vp->v_vfsp = bhvtovfs(bdp); @@ -230,7 +228,7 @@ xfs_initialize_vnode( if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) { xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); xfs_set_inodeops(inode); - + ip->i_flags &= ~XFS_INEW; barrier(); @@ -334,43 +332,42 @@ xfs_blkdev_issue_flush( } STATIC struct inode * -linvfs_alloc_inode( +xfs_fs_alloc_inode( struct super_block *sb) { vnode_t *vp; - vp = kmem_cache_alloc(xfs_vnode_zone, kmem_flags_convert(KM_SLEEP)); - if (!vp) + vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); + if (unlikely(!vp)) return NULL; - return LINVFS_GET_IP(vp); + return vn_to_inode(vp); } STATIC void -linvfs_destroy_inode( +xfs_fs_destroy_inode( struct inode *inode) { - kmem_zone_free(xfs_vnode_zone, LINVFS_GET_VP(inode)); + kmem_zone_free(xfs_vnode_zone, vn_from_inode(inode)); } STATIC void -linvfs_inode_init_once( - void *data, - kmem_cache_t *cachep, +xfs_fs_inode_init_once( + void *vnode, + kmem_zone_t *zonep, unsigned long flags) { - vnode_t *vp = (vnode_t *)data; - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == - SLAB_CTOR_CONSTRUCTOR) - inode_init_once(LINVFS_GET_IP(vp)); + SLAB_CTOR_CONSTRUCTOR) + inode_init_once(vn_to_inode((vnode_t *)vnode)); } STATIC int -linvfs_init_zones(void) +xfs_init_zones(void) { - xfs_vnode_zone = kmem_cache_create("xfs_vnode", - sizeof(vnode_t), 0, SLAB_RECLAIM_ACCOUNT, - linvfs_inode_init_once, NULL); + xfs_vnode_zone = kmem_zone_init_flags(sizeof(vnode_t), "xfs_vnode_t", + KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | + KM_ZONE_SPREAD, + xfs_fs_inode_init_once); if (!xfs_vnode_zone) goto out; @@ -379,14 +376,12 @@ linvfs_init_zones(void) goto out_destroy_vnode_zone; xfs_ioend_pool = mempool_create(4 * MAX_BUF_PER_PAGE, - mempool_alloc_slab, mempool_free_slab, - xfs_ioend_zone); + mempool_alloc_slab, mempool_free_slab, + xfs_ioend_zone); if (!xfs_ioend_pool) goto out_free_ioend_zone; - return 0; - out_free_ioend_zone: kmem_zone_destroy(xfs_ioend_zone); out_destroy_vnode_zone: @@ -396,7 +391,7 @@ linvfs_init_zones(void) } STATIC void -linvfs_destroy_zones(void) +xfs_destroy_zones(void) { mempool_destroy(xfs_ioend_pool); kmem_zone_destroy(xfs_vnode_zone); @@ -407,14 +402,14 @@ linvfs_destroy_zones(void) * Attempt to flush the inode, this will actually fail * if the inode is pinned, but we dirty the inode again * at the point when it is unpinned after a log write, - * since this is when the inode itself becomes flushable. + * since this is when the inode itself becomes flushable. */ STATIC int -linvfs_write_inode( +xfs_fs_write_inode( struct inode *inode, int sync) { - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error = 0, flags = FLUSH_INODE; if (vp) { @@ -434,13 +429,13 @@ linvfs_write_inode( } STATIC void -linvfs_clear_inode( +xfs_fs_clear_inode( struct inode *inode) { - vnode_t *vp = LINVFS_GET_VP(inode); + vnode_t *vp = vn_from_inode(inode); int error, cache; - vn_trace_entry(vp, "clear_inode", (inst_t *)__return_address); + vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); XFS_STATS_INC(vn_rele); XFS_STATS_INC(vn_remove); @@ -516,7 +511,7 @@ void xfs_flush_inode( xfs_inode_t *ip) { - struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); + struct inode *inode = vn_to_inode(XFS_ITOV(ip)); struct vfs *vfs = XFS_MTOVFS(ip->i_mount); igrab(inode); @@ -541,7 +536,7 @@ void xfs_flush_device( xfs_inode_t *ip) { - struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); + struct inode *inode = vn_to_inode(XFS_ITOV(ip)); struct vfs *vfs = XFS_MTOVFS(ip->i_mount); igrab(inode); @@ -550,7 +545,7 @@ xfs_flush_device( xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); } -#define SYNCD_FLAGS (SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR) +#define SYNCD_FLAGS (SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR|SYNC_REFCACHE) STATIC void vfs_sync_worker( vfs_t *vfsp, @@ -613,7 +608,7 @@ xfssyncd( } STATIC int -linvfs_start_syncd( +xfs_fs_start_syncd( vfs_t *vfsp) { vfsp->vfs_sync_work.w_syncer = vfs_sync_worker; @@ -625,20 +620,20 @@ linvfs_start_syncd( } STATIC void -linvfs_stop_syncd( +xfs_fs_stop_syncd( vfs_t *vfsp) { kthread_stop(vfsp->vfs_sync_task); } STATIC void -linvfs_put_super( +xfs_fs_put_super( struct super_block *sb) { - vfs_t *vfsp = LINVFS_GET_VFS(sb); + vfs_t *vfsp = vfs_from_sb(sb); int error; - linvfs_stop_syncd(vfsp); + xfs_fs_stop_syncd(vfsp); VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error); if (!error) VFS_UNMOUNT(vfsp, 0, NULL, error); @@ -652,10 +647,10 @@ linvfs_put_super( } STATIC void -linvfs_write_super( +xfs_fs_write_super( struct super_block *sb) { - vfs_t *vfsp = LINVFS_GET_VFS(sb); + vfs_t *vfsp = vfs_from_sb(sb); int error; if (sb->s_flags & MS_RDONLY) { @@ -668,11 +663,11 @@ linvfs_write_super( } STATIC int -linvfs_sync_super( +xfs_fs_sync_super( struct super_block *sb, int wait) { - vfs_t *vfsp = LINVFS_GET_VFS(sb); + vfs_t *vfsp = vfs_from_sb(sb); int error; int flags = SYNC_FSDATA; @@ -707,11 +702,11 @@ linvfs_sync_super( } STATIC int -linvfs_statfs( +xfs_fs_statfs( struct super_block *sb, struct kstatfs *statp) { - vfs_t *vfsp = LINVFS_GET_VFS(sb); + vfs_t *vfsp = vfs_from_sb(sb); int error; VFS_STATVFS(vfsp, statp, NULL, error); @@ -719,12 +714,12 @@ linvfs_statfs( } STATIC int -linvfs_remount( +xfs_fs_remount( struct super_block *sb, int *flags, char *options) { - vfs_t *vfsp = LINVFS_GET_VFS(sb); + vfs_t *vfsp = vfs_from_sb(sb); struct xfs_mount_args *args = xfs_args_allocate(sb); int error; @@ -736,18 +731,18 @@ linvfs_remount( } STATIC void -linvfs_freeze_fs( +xfs_fs_lockfs( struct super_block *sb) { - VFS_FREEZE(LINVFS_GET_VFS(sb)); + VFS_FREEZE(vfs_from_sb(sb)); } STATIC int -linvfs_show_options( +xfs_fs_show_options( struct seq_file *m, struct vfsmount *mnt) { - struct vfs *vfsp = LINVFS_GET_VFS(mnt->mnt_sb); + struct vfs *vfsp = vfs_from_sb(mnt->mnt_sb); int error; VFS_SHOWARGS(vfsp, m, error); @@ -755,11 +750,11 @@ linvfs_show_options( } STATIC int -linvfs_quotasync( +xfs_fs_quotasync( struct super_block *sb, int type) { - struct vfs *vfsp = LINVFS_GET_VFS(sb); + struct vfs *vfsp = vfs_from_sb(sb); int error; VFS_QUOTACTL(vfsp, Q_XQUOTASYNC, 0, (caddr_t)NULL, error); @@ -767,11 +762,11 @@ linvfs_quotasync( } STATIC int -linvfs_getxstate( +xfs_fs_getxstate( struct super_block *sb, struct fs_quota_stat *fqs) { - struct vfs *vfsp = LINVFS_GET_VFS(sb); + struct vfs *vfsp = vfs_from_sb(sb); int error; VFS_QUOTACTL(vfsp, Q_XGETQSTAT, 0, (caddr_t)fqs, error); @@ -779,12 +774,12 @@ linvfs_getxstate( } STATIC int -linvfs_setxstate( +xfs_fs_setxstate( struct super_block *sb, unsigned int flags, int op) { - struct vfs *vfsp = LINVFS_GET_VFS(sb); + struct vfs *vfsp = vfs_from_sb(sb); int error; VFS_QUOTACTL(vfsp, op, 0, (caddr_t)&flags, error); @@ -792,13 +787,13 @@ linvfs_setxstate( } STATIC int -linvfs_getxquota( +xfs_fs_getxquota( struct super_block *sb, int type, qid_t id, struct fs_disk_quota *fdq) { - struct vfs *vfsp = LINVFS_GET_VFS(sb); + struct vfs *vfsp = vfs_from_sb(sb); int error, getmode; getmode = (type == USRQUOTA) ? Q_XGETQUOTA : @@ -808,13 +803,13 @@ linvfs_getxquota( } STATIC int -linvfs_setxquota( +xfs_fs_setxquota( struct super_block *sb, int type, qid_t id, struct fs_disk_quota *fdq) { - struct vfs *vfsp = LINVFS_GET_VFS(sb); + struct vfs *vfsp = vfs_from_sb(sb); int error, setmode; setmode = (type == USRQUOTA) ? Q_XSETQLIM : @@ -824,21 +819,17 @@ linvfs_setxquota( } STATIC int -linvfs_fill_super( +xfs_fs_fill_super( struct super_block *sb, void *data, int silent) { vnode_t *rootvp; - struct vfs *vfsp = vfs_allocate(); + struct vfs *vfsp = vfs_allocate(sb); struct xfs_mount_args *args = xfs_args_allocate(sb); struct kstatfs statvfs; int error, error2; - vfsp->vfs_super = sb; - LINVFS_SET_VFS(sb, vfsp); - if (sb->s_flags & MS_RDONLY) - vfsp->vfs_flag |= VFS_RDONLY; bhv_insert_all_vfsops(vfsp); VFS_PARSEARGS(vfsp, (char *)data, args, 0, error); @@ -849,10 +840,10 @@ linvfs_fill_super( sb_min_blocksize(sb, BBSIZE); #ifdef CONFIG_XFS_EXPORT - sb->s_export_op = &linvfs_export_ops; + sb->s_export_op = &xfs_export_operations; #endif - sb->s_qcop = &linvfs_qops; - sb->s_op = &linvfs_sops; + sb->s_qcop = &xfs_quotactl_operations; + sb->s_op = &xfs_super_operations; VFS_MOUNT(vfsp, args, NULL, error); if (error) { @@ -876,7 +867,7 @@ linvfs_fill_super( if (error) goto fail_unmount; - sb->s_root = d_alloc_root(LINVFS_GET_IP(rootvp)); + sb->s_root = d_alloc_root(vn_to_inode(rootvp)); if (!sb->s_root) { error = ENOMEM; goto fail_vnrele; @@ -885,7 +876,7 @@ linvfs_fill_super( error = EINVAL; goto fail_vnrele; } - if ((error = linvfs_start_syncd(vfsp))) + if ((error = xfs_fs_start_syncd(vfsp))) goto fail_vnrele; vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address); @@ -910,41 +901,41 @@ fail_vfsop: } STATIC struct super_block * -linvfs_get_sb( +xfs_fs_get_sb( struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return get_sb_bdev(fs_type, flags, dev_name, data, linvfs_fill_super); -} - -STATIC struct super_operations linvfs_sops = { - .alloc_inode = linvfs_alloc_inode, - .destroy_inode = linvfs_destroy_inode, - .write_inode = linvfs_write_inode, - .clear_inode = linvfs_clear_inode, - .put_super = linvfs_put_super, - .write_super = linvfs_write_super, - .sync_fs = linvfs_sync_super, - .write_super_lockfs = linvfs_freeze_fs, - .statfs = linvfs_statfs, - .remount_fs = linvfs_remount, - .show_options = linvfs_show_options, + return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super); +} + +STATIC struct super_operations xfs_super_operations = { + .alloc_inode = xfs_fs_alloc_inode, + .destroy_inode = xfs_fs_destroy_inode, + .write_inode = xfs_fs_write_inode, + .clear_inode = xfs_fs_clear_inode, + .put_super = xfs_fs_put_super, + .write_super = xfs_fs_write_super, + .sync_fs = xfs_fs_sync_super, + .write_super_lockfs = xfs_fs_lockfs, + .statfs = xfs_fs_statfs, + .remount_fs = xfs_fs_remount, + .show_options = xfs_fs_show_options, }; -STATIC struct quotactl_ops linvfs_qops = { - .quota_sync = linvfs_quotasync, - .get_xstate = linvfs_getxstate, - .set_xstate = linvfs_setxstate, - .get_xquota = linvfs_getxquota, - .set_xquota = linvfs_setxquota, +STATIC struct quotactl_ops xfs_quotactl_operations = { + .quota_sync = xfs_fs_quotasync, + .get_xstate = xfs_fs_getxstate, + .set_xstate = xfs_fs_setxstate, + .get_xquota = xfs_fs_getxquota, + .set_xquota = xfs_fs_setxquota, }; STATIC struct file_system_type xfs_fs_type = { .owner = THIS_MODULE, .name = "xfs", - .get_sb = linvfs_get_sb, + .get_sb = xfs_fs_get_sb, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; @@ -965,7 +956,7 @@ init_xfs_fs( void ) ktrace_init(64); - error = linvfs_init_zones(); + error = xfs_init_zones(); if (error < 0) goto undo_zones; @@ -981,14 +972,13 @@ init_xfs_fs( void ) error = register_filesystem(&xfs_fs_type); if (error) goto undo_register; - XFS_DM_INIT(&xfs_fs_type); return 0; undo_register: xfs_buf_terminate(); undo_buffers: - linvfs_destroy_zones(); + xfs_destroy_zones(); undo_zones: return error; @@ -998,11 +988,10 @@ STATIC void __exit exit_xfs_fs( void ) { vfs_exitquota(); - XFS_DM_EXIT(&xfs_fs_type); unregister_filesystem(&xfs_fs_type); xfs_cleanup(); xfs_buf_terminate(); - linvfs_destroy_zones(); + xfs_destroy_zones(); ktrace_uninit(); } diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index df59408dca06..376b96cb513a 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h @@ -98,11 +98,6 @@ extern void xfs_qm_exit(void); XFS_DMAPI_STRING \ XFS_DBG_STRING /* DBG must be last */ -#define LINVFS_GET_VFS(s) \ - (vfs_t *)((s)->s_fs_info) -#define LINVFS_SET_VFS(s, vfsp) \ - ((s)->s_fs_info = vfsp) - struct xfs_inode; struct xfs_mount; struct xfs_buftarg; @@ -120,6 +115,6 @@ extern int xfs_blkdev_get(struct xfs_mount *, const char *, extern void xfs_blkdev_put(struct block_device *); extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); -extern struct export_operations linvfs_export_ops; +extern struct export_operations xfs_export_operations; #endif /* __XFS_SUPER_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c index c855d62e5344..6f7c9f7a8624 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.c +++ b/fs/xfs/linux-2.6/xfs_vfs.c @@ -227,7 +227,8 @@ vfs_freeze( } vfs_t * -vfs_allocate( void ) +vfs_allocate( + struct super_block *sb) { struct vfs *vfsp; @@ -236,9 +237,23 @@ vfs_allocate( void ) INIT_LIST_HEAD(&vfsp->vfs_sync_list); spin_lock_init(&vfsp->vfs_sync_lock); init_waitqueue_head(&vfsp->vfs_wait_single_sync_task); + + vfsp->vfs_super = sb; + sb->s_fs_info = vfsp; + + if (sb->s_flags & MS_RDONLY) + vfsp->vfs_flag |= VFS_RDONLY; + return vfsp; } +vfs_t * +vfs_from_sb( + struct super_block *sb) +{ + return (vfs_t *)sb->s_fs_info; +} + void vfs_deallocate( struct vfs *vfsp) @@ -295,7 +310,7 @@ bhv_remove_all_vfsops( bhv_remove_vfsops(vfsp, VFS_POSITION_DM); if (!freebase) return; - mp = XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfsp), &xfs_vfsops)); + mp = XFS_VFSTOM(vfsp); VFS_REMOVEBHV(vfsp, &mp->m_bhv); xfs_mount_free(mp, 0); } diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index 57caf9eddee0..8fed356db055 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h @@ -193,7 +193,8 @@ typedef struct bhv_vfsops { #define vfs_bhv_set_custom(b,o) ( (b)->bhv_custom = (void *)(o)) #define vfs_bhv_clr_custom(b) ( (b)->bhv_custom = NULL ) -extern vfs_t *vfs_allocate(void); +extern vfs_t *vfs_allocate(struct super_block *); +extern vfs_t *vfs_from_sb(struct super_block *); extern void vfs_deallocate(vfs_t *); extern void vfs_insertops(vfs_t *, bhv_vfsops_t *); extern void vfs_insertbhv(vfs_t *, bhv_desc_t *, vfsops_t *, void *); diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 260dd8415dd7..d27c25b27ccd 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -58,7 +58,7 @@ struct vnode * vn_initialize( struct inode *inode) { - struct vnode *vp = LINVFS_GET_VP(inode); + struct vnode *vp = vn_from_inode(inode); XFS_STATS_INC(vn_active); XFS_STATS_INC(vn_alloc); @@ -83,7 +83,7 @@ vn_initialize( vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); #endif /* XFS_VNODE_TRACE */ - vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address); + vn_trace_exit(vp, __FUNCTION__, (inst_t *)__return_address); return vp; } @@ -97,7 +97,7 @@ vn_revalidate_core( struct vnode *vp, vattr_t *vap) { - struct inode *inode = LINVFS_GET_IP(vp); + struct inode *inode = vn_to_inode(vp); inode->i_mode = vap->va_mode; inode->i_nlink = vap->va_nlink; @@ -129,24 +129,31 @@ vn_revalidate_core( * Revalidate the Linux inode from the vnode. */ int -vn_revalidate( - struct vnode *vp) +__vn_revalidate( + struct vnode *vp, + struct vattr *vattr) { - vattr_t va; int error; - vn_trace_entry(vp, "vn_revalidate", (inst_t *)__return_address); - ASSERT(vp->v_fbhv != NULL); - - va.va_mask = XFS_AT_STAT|XFS_AT_XFLAGS; - VOP_GETATTR(vp, &va, 0, NULL, error); - if (!error) { - vn_revalidate_core(vp, &va); + vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); + vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS; + VOP_GETATTR(vp, vattr, 0, NULL, error); + if (likely(!error)) { + vn_revalidate_core(vp, vattr); VUNMODIFY(vp); } return -error; } +int +vn_revalidate( + struct vnode *vp) +{ + vattr_t vattr; + + return __vn_revalidate(vp, &vattr); +} + /* * Add a reference to a referenced vnode. */ @@ -159,7 +166,7 @@ vn_hold( XFS_STATS_INC(vn_hold); VN_LOCK(vp); - inode = igrab(LINVFS_GET_IP(vp)); + inode = igrab(vn_to_inode(vp)); ASSERT(inode); VN_UNLOCK(vp, 0); diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 0fe2419461d6..06f5845e9568 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -116,8 +116,14 @@ typedef enum { /* * Vnode to Linux inode mapping. */ -#define LINVFS_GET_VP(inode) ((vnode_t *)list_entry(inode, vnode_t, v_inode)) -#define LINVFS_GET_IP(vp) (&(vp)->v_inode) +static inline struct vnode *vn_from_inode(struct inode *inode) +{ + return (vnode_t *)list_entry(inode, vnode_t, v_inode); +} +static inline struct inode *vn_to_inode(struct vnode *vnode) +{ + return &vnode->v_inode; +} /* * Vnode flags. @@ -490,6 +496,7 @@ typedef struct vnode_map { (vmap).v_ino = (vp)->v_inode.i_ino; } extern int vn_revalidate(struct vnode *); +extern int __vn_revalidate(struct vnode *, vattr_t *); extern void vn_revalidate_core(struct vnode *, vattr_t *); extern void vn_iowait(struct vnode *vp); @@ -497,7 +504,7 @@ extern void vn_iowake(struct vnode *vp); static inline int vn_count(struct vnode *vp) { - return atomic_read(&LINVFS_GET_IP(vp)->i_count); + return atomic_read(&vn_to_inode(vp)->i_count); } /* @@ -511,16 +518,16 @@ extern vnode_t *vn_hold(struct vnode *); vn_trace_hold(vp, __FILE__, __LINE__, (inst_t *)__return_address)) #define VN_RELE(vp) \ (vn_trace_rele(vp, __FILE__, __LINE__, (inst_t *)__return_address), \ - iput(LINVFS_GET_IP(vp))) + iput(vn_to_inode(vp))) #else #define VN_HOLD(vp) ((void)vn_hold(vp)) -#define VN_RELE(vp) (iput(LINVFS_GET_IP(vp))) +#define VN_RELE(vp) (iput(vn_to_inode(vp))) #endif static inline struct vnode *vn_grab(struct vnode *vp) { - struct inode *inode = igrab(LINVFS_GET_IP(vp)); - return inode ? LINVFS_GET_VP(inode) : NULL; + struct inode *inode = igrab(vn_to_inode(vp)); + return inode ? vn_from_inode(inode) : NULL; } /* @@ -528,7 +535,7 @@ static inline struct vnode *vn_grab(struct vnode *vp) */ #define VNAME(dentry) ((char *) (dentry)->d_name.name) #define VNAMELEN(dentry) ((dentry)->d_name.len) -#define VNAME_TO_VNODE(dentry) (LINVFS_GET_VP((dentry)->d_inode)) +#define VNAME_TO_VNODE(dentry) (vn_from_inode((dentry)->d_inode)) /* * Vnode spinlock manipulation. @@ -557,12 +564,12 @@ static __inline__ void vn_flagclr(struct vnode *vp, uint flag) */ static inline void vn_mark_bad(struct vnode *vp) { - make_bad_inode(LINVFS_GET_IP(vp)); + make_bad_inode(vn_to_inode(vp)); } static inline int VN_BAD(struct vnode *vp) { - return is_bad_inode(LINVFS_GET_IP(vp)); + return is_bad_inode(vn_to_inode(vp)); } /* @@ -587,9 +594,9 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) /* * Some useful predicates. */ -#define VN_MAPPED(vp) mapping_mapped(LINVFS_GET_IP(vp)->i_mapping) -#define VN_CACHED(vp) (LINVFS_GET_IP(vp)->i_mapping->nrpages) -#define VN_DIRTY(vp) mapping_tagged(LINVFS_GET_IP(vp)->i_mapping, \ +#define VN_MAPPED(vp) mapping_mapped(vn_to_inode(vp)->i_mapping) +#define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages) +#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \ PAGECACHE_TAG_DIRTY) #define VMODIFY(vp) VN_FLAGSET(vp, VMODIFIED) #define VUNMODIFY(vp) VN_FLAGCLR(vp, VMODIFIED) diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 2ec6b441849c..e4e5f05b841b 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -79,9 +79,11 @@ xfs_qm_dquot_logitem_format( logvec->i_addr = (xfs_caddr_t)&logitem->qli_format; logvec->i_len = sizeof(xfs_dq_logformat_t); + XLOG_VEC_SET_TYPE(logvec, XLOG_REG_TYPE_QFORMAT); logvec++; logvec->i_addr = (xfs_caddr_t)&logitem->qli_dquot->q_core; logvec->i_len = sizeof(xfs_disk_dquot_t); + XLOG_VEC_SET_TYPE(logvec, XLOG_REG_TYPE_DQUOT); ASSERT(2 == logitem->qli_item.li_desc->lid_size); logitem->qli_format.qlf_size = 2; diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 7c0e39dc6189..1fb757ef3f41 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1704,9 +1704,9 @@ xfs_qm_get_rtblks( xfs_qcnt_t *O_rtblks) { xfs_filblks_t rtblks; /* total rt blks */ + xfs_extnum_t idx; /* extent record index */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_extnum_t nextents; /* number of extent entries */ - xfs_bmbt_rec_t *base; /* base of extent array */ xfs_bmbt_rec_t *ep; /* pointer to an extent entry */ int error; @@ -1717,10 +1717,11 @@ xfs_qm_get_rtblks( return error; } rtblks = 0; - nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); - base = &ifp->if_u1.if_extents[0]; - for (ep = base; ep < &base[nextents]; ep++) + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + for (idx = 0; idx < nextents; idx++) { + ep = xfs_iext_get_ext(ifp, idx); rtblks += xfs_bmbt_get_blockcount(ep); + } *O_rtblks = (xfs_qcnt_t)rtblks; return 0; } @@ -2788,9 +2789,7 @@ xfs_qm_freelist_destroy(xfs_frlist_t *ql) xfs_qm_dqdestroy(dqp); dqp = nextdqp; } - /* - * Don't bother about unlocking. - */ + mutex_unlock(&ql->qh_lock); mutex_destroy(&ql->qh_lock); ASSERT(ql->qh_nelems == 0); diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 90402a1c3983..6838b36d95a9 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -374,7 +374,7 @@ xfs_qm_exit(void) vfs_bhv_clr_custom(&xfs_qmops); xfs_qm_cleanup_procfs(); if (qm_dqzone) - kmem_cache_destroy(qm_dqzone); + kmem_zone_destroy(qm_dqzone); if (qm_dqtrxzone) - kmem_cache_destroy(qm_dqtrxzone); + kmem_zone_destroy(qm_dqtrxzone); } diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c index 841aa4c15b8a..addf5a7ea06c 100644 --- a/fs/xfs/support/ktrace.c +++ b/fs/xfs/support/ktrace.c @@ -39,8 +39,8 @@ ktrace_init(int zentries) void ktrace_uninit(void) { - kmem_cache_destroy(ktrace_hdr_zone); - kmem_cache_destroy(ktrace_ent_zone); + kmem_zone_destroy(ktrace_hdr_zone); + kmem_zone_destroy(ktrace_ent_zone); } /* diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c index a3d565a67734..e157015c70ff 100644 --- a/fs/xfs/support/uuid.c +++ b/fs/xfs/support/uuid.c @@ -21,13 +21,6 @@ static mutex_t uuid_monitor; static int uuid_table_size; static uuid_t *uuid_table; -void -uuid_init(void) -{ - mutex_init(&uuid_monitor); -} - - /* IRIX interpretation of an uuid_t */ typedef struct { __be32 uu_timelow; @@ -50,7 +43,7 @@ uuid_getnodeuniq(uuid_t *uuid, int fsid [2]) fsid[0] = (be16_to_cpu(uup->uu_clockseq) << 16) | be16_to_cpu(uup->uu_timemid); - fsid[1] = be16_to_cpu(uup->uu_timelow); + fsid[1] = be32_to_cpu(uup->uu_timelow); } void @@ -139,3 +132,9 @@ uuid_table_remove(uuid_t *uuid) ASSERT(i < uuid_table_size); mutex_unlock(&uuid_monitor); } + +void +uuid_init(void) +{ + mutex_init(&uuid_monitor); +} diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index f9315bc960cb..538d0d65b04c 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -55,8 +55,8 @@ struct xfs_inode; extern struct kmem_zone *xfs_acl_zone; #define xfs_acl_zone_init(zone, name) \ - (zone) = kmem_zone_init(sizeof(xfs_acl_t), name) -#define xfs_acl_zone_destroy(zone) kmem_cache_destroy(zone) + (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) +#define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *); extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index e5e91e9c7e89..093fac476bda 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -1127,8 +1127,7 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context) return(error); ASSERT(bp != NULL); leaf = bp->data; - if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - != XFS_ATTR_LEAF_MAGIC)) { + if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) { XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW, context->dp->i_mount, leaf); xfs_da_brelse(NULL, bp); @@ -1541,8 +1540,8 @@ xfs_attr_node_removename(xfs_da_args_t *args) XFS_ATTR_FORK); if (error) goto out; - ASSERT(INT_GET(((xfs_attr_leafblock_t *) - bp->data)->hdr.info.magic, ARCH_CONVERT) + ASSERT(be16_to_cpu(((xfs_attr_leafblock_t *) + bp->data)->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { @@ -1763,7 +1762,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) return(error); if (bp) { node = bp->data; - switch (INT_GET(node->hdr.info.magic, ARCH_CONVERT)) { + switch (be16_to_cpu(node->hdr.info.magic)) { case XFS_DA_NODE_MAGIC: xfs_attr_trace_l_cn("wrong blk", context, node); xfs_da_brelse(NULL, bp); @@ -1771,18 +1770,14 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) break; case XFS_ATTR_LEAF_MAGIC: leaf = bp->data; - if (cursor->hashval > - INT_GET(leaf->entries[ - INT_GET(leaf->hdr.count, - ARCH_CONVERT)-1].hashval, - ARCH_CONVERT)) { + if (cursor->hashval > be32_to_cpu(leaf->entries[ + be16_to_cpu(leaf->hdr.count)-1].hashval)) { xfs_attr_trace_l_cl("wrong blk", context, leaf); xfs_da_brelse(NULL, bp); bp = NULL; } else if (cursor->hashval <= - INT_GET(leaf->entries[0].hashval, - ARCH_CONVERT)) { + be32_to_cpu(leaf->entries[0].hashval)) { xfs_attr_trace_l_cl("maybe wrong blk", context, leaf); xfs_da_brelse(NULL, bp); @@ -1817,10 +1812,10 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) return(XFS_ERROR(EFSCORRUPTED)); } node = bp->data; - if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) + if (be16_to_cpu(node->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC) break; - if (unlikely(INT_GET(node->hdr.info.magic, ARCH_CONVERT) + if (unlikely(be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC)) { XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)", XFS_ERRLEVEL_LOW, @@ -1830,19 +1825,17 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) return(XFS_ERROR(EFSCORRUPTED)); } btree = node->btree; - for (i = 0; - i < INT_GET(node->hdr.count, ARCH_CONVERT); + for (i = 0; i < be16_to_cpu(node->hdr.count); btree++, i++) { if (cursor->hashval - <= INT_GET(btree->hashval, - ARCH_CONVERT)) { - cursor->blkno = INT_GET(btree->before, ARCH_CONVERT); + <= be32_to_cpu(btree->hashval)) { + cursor->blkno = be32_to_cpu(btree->before); xfs_attr_trace_l_cb("descending", context, btree); break; } } - if (i == INT_GET(node->hdr.count, ARCH_CONVERT)) { + if (i == be16_to_cpu(node->hdr.count)) { xfs_da_brelse(NULL, bp); return(0); } @@ -1858,7 +1851,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) */ for (;;) { leaf = bp->data; - if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) + if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) { XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)", XFS_ERRLEVEL_LOW, @@ -1869,7 +1862,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) error = xfs_attr_leaf_list_int(bp, context); if (error || !leaf->hdr.info.forw) break; /* not really an error, buffer full or EOF */ - cursor->blkno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT); + cursor->blkno = be32_to_cpu(leaf->hdr.info.forw); xfs_da_brelse(NULL, bp); error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1, &bp, XFS_ATTR_FORK); @@ -2232,9 +2225,10 @@ xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context, : 0, (__psunsigned_t)context->dupcnt, (__psunsigned_t)context->flags, - (__psunsigned_t)INT_GET(node->hdr.count, ARCH_CONVERT), - (__psunsigned_t)INT_GET(node->btree[0].hashval, ARCH_CONVERT), - (__psunsigned_t)INT_GET(node->btree[INT_GET(node->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); + (__psunsigned_t)be16_to_cpu(node->hdr.count), + (__psunsigned_t)be32_to_cpu(node->btree[0].hashval), + (__psunsigned_t)be32_to_cpu(node->btree[ + be16_to_cpu(node->hdr.count)-1].hashval)); } /* @@ -2261,8 +2255,8 @@ xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context, : 0, (__psunsigned_t)context->dupcnt, (__psunsigned_t)context->flags, - (__psunsigned_t)INT_GET(btree->hashval, ARCH_CONVERT), - (__psunsigned_t)INT_GET(btree->before, ARCH_CONVERT), + (__psunsigned_t)be32_to_cpu(btree->hashval), + (__psunsigned_t)be32_to_cpu(btree->before), (__psunsigned_t)NULL); } @@ -2290,9 +2284,10 @@ xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, : 0, (__psunsigned_t)context->dupcnt, (__psunsigned_t)context->flags, - (__psunsigned_t)INT_GET(leaf->hdr.count, ARCH_CONVERT), - (__psunsigned_t)INT_GET(leaf->entries[0].hashval, ARCH_CONVERT), - (__psunsigned_t)INT_GET(leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); + (__psunsigned_t)be16_to_cpu(leaf->hdr.count), + (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval), + (__psunsigned_t)be32_to_cpu(leaf->entries[ + be16_to_cpu(leaf->hdr.count)-1].hashval)); } /* @@ -2522,7 +2517,7 @@ attr_user_capable( struct vnode *vp, cred_t *cred) { - struct inode *inode = LINVFS_GET_IP(vp); + struct inode *inode = vn_to_inode(vp); if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) return -EPERM; @@ -2540,7 +2535,7 @@ attr_trusted_capable( struct vnode *vp, cred_t *cred) { - struct inode *inode = LINVFS_GET_IP(vp); + struct inode *inode = vn_to_inode(vp); if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) return -EPERM; diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index fe91eac4e2a7..717682747bd2 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -194,7 +194,7 @@ xfs_attr_shortform_create(xfs_da_args_t *args) xfs_idata_realloc(dp, sizeof(*hdr), XFS_ATTR_FORK); hdr = (xfs_attr_sf_hdr_t *)ifp->if_u1.if_data; hdr->count = 0; - INT_SET(hdr->totsize, ARCH_CONVERT, sizeof(*hdr)); + hdr->totsize = cpu_to_be16(sizeof(*hdr)); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); } @@ -224,8 +224,7 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) ASSERT(ifp->if_flags & XFS_IFINLINE); sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; sfe = &sf->list[0]; - for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); - sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { + for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { #ifdef DEBUG if (sfe->namelen != args->namelen) continue; @@ -248,13 +247,13 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) sfe = (xfs_attr_sf_entry_t *)((char *)sf + offset); sfe->namelen = args->namelen; - INT_SET(sfe->valuelen, ARCH_CONVERT, args->valuelen); + sfe->valuelen = args->valuelen; sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE : ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0); memcpy(sfe->nameval, args->name, args->namelen); memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); - INT_MOD(sf->hdr.count, ARCH_CONVERT, 1); - INT_MOD(sf->hdr.totsize, ARCH_CONVERT, size); + sf->hdr.count++; + be16_add(&sf->hdr.totsize, size); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); xfs_sbversion_add_attr2(mp, args->trans); @@ -277,7 +276,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) base = sizeof(xfs_attr_sf_hdr_t); sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; sfe = &sf->list[0]; - end = INT_GET(sf->hdr.count, ARCH_CONVERT); + end = sf->hdr.count; for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), base += size, i++) { size = XFS_ATTR_SF_ENTSIZE(sfe); @@ -300,11 +299,11 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) * Fix up the attribute fork data, covering the hole */ end = base + size; - totsize = INT_GET(sf->hdr.totsize, ARCH_CONVERT); + totsize = be16_to_cpu(sf->hdr.totsize); if (end != totsize) memmove(&((char *)sf)[base], &((char *)sf)[end], totsize - end); - INT_MOD(sf->hdr.count, ARCH_CONVERT, -1); - INT_MOD(sf->hdr.totsize, ARCH_CONVERT, -size); + sf->hdr.count--; + be16_add(&sf->hdr.totsize, -size); /* * Fix up the start offset of the attribute fork @@ -360,7 +359,7 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args) ASSERT(ifp->if_flags & XFS_IFINLINE); sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; sfe = &sf->list[0]; - for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); + for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { if (sfe->namelen != args->namelen) continue; @@ -391,7 +390,7 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args) ASSERT(args->dp->i_d.di_aformat == XFS_IFINLINE); sf = (xfs_attr_shortform_t *)args->dp->i_afp->if_u1.if_data; sfe = &sf->list[0]; - for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); + for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { if (sfe->namelen != args->namelen) continue; @@ -404,14 +403,14 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args) ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; if (args->flags & ATTR_KERNOVAL) { - args->valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT); + args->valuelen = sfe->valuelen; return(XFS_ERROR(EEXIST)); } - if (args->valuelen < INT_GET(sfe->valuelen, ARCH_CONVERT)) { - args->valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT); + if (args->valuelen < sfe->valuelen) { + args->valuelen = sfe->valuelen; return(XFS_ERROR(ERANGE)); } - args->valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT); + args->valuelen = sfe->valuelen; memcpy(args->value, &sfe->nameval[args->namelen], args->valuelen); return(XFS_ERROR(EEXIST)); @@ -438,7 +437,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) dp = args->dp; ifp = dp->i_afp; sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; - size = INT_GET(sf->hdr.totsize, ARCH_CONVERT); + size = be16_to_cpu(sf->hdr.totsize); tmpbuffer = kmem_alloc(size, KM_SLEEP); ASSERT(tmpbuffer != NULL); memcpy(tmpbuffer, ifp->if_u1.if_data, size); @@ -481,11 +480,11 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) nargs.oknoent = 1; sfe = &sf->list[0]; - for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { + for (i = 0; i < sf->hdr.count; i++) { nargs.name = (char *)sfe->nameval; nargs.namelen = sfe->namelen; nargs.value = (char *)&sfe->nameval[nargs.namelen]; - nargs.valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT); + nargs.valuelen = sfe->valuelen; nargs.hashval = xfs_da_hashname((char *)sfe->nameval, sfe->namelen); nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : @@ -514,11 +513,9 @@ xfs_attr_shortform_compare(const void *a, const void *b) sa = (xfs_attr_sf_sort_t *)a; sb = (xfs_attr_sf_sort_t *)b; - if (INT_GET(sa->hash, ARCH_CONVERT) - < INT_GET(sb->hash, ARCH_CONVERT)) { + if (sa->hash < sb->hash) { return(-1); - } else if (INT_GET(sa->hash, ARCH_CONVERT) - > INT_GET(sb->hash, ARCH_CONVERT)) { + } else if (sa->hash > sb->hash) { return(1); } else { return(sa->entno - sb->entno); @@ -560,10 +557,8 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) * If the buffer is large enough, do not bother with sorting. * Note the generous fudge factor of 16 overhead bytes per entry. */ - if ((dp->i_afp->if_bytes + INT_GET(sf->hdr.count, ARCH_CONVERT) * 16) - < context->bufsize) { - for (i = 0, sfe = &sf->list[0]; - i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { + if ((dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize) { + for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { attrnames_t *namesp; if (((context->flags & ATTR_SECURE) != 0) != @@ -584,14 +579,13 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) if (context->flags & ATTR_KERNOVAL) { ASSERT(context->flags & ATTR_KERNAMELS); context->count += namesp->attr_namelen + - INT_GET(sfe->namelen, ARCH_CONVERT) + 1; + sfe->namelen + 1; } else { if (xfs_attr_put_listent(context, namesp, (char *)sfe->nameval, (int)sfe->namelen, - (int)INT_GET(sfe->valuelen, - ARCH_CONVERT))) + (int)sfe->valuelen)) break; } sfe = XFS_ATTR_SF_NEXTENTRY(sfe); @@ -603,7 +597,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) /* * It didn't all fit, so we have to sort everything on hashval. */ - sbsize = INT_GET(sf->hdr.count, ARCH_CONVERT) * sizeof(*sbuf); + sbsize = sf->hdr.count * sizeof(*sbuf); sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP); /* @@ -611,8 +605,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) * the relevant info from only those that match into a buffer. */ nsbuf = 0; - for (i = 0, sfe = &sf->list[0]; - i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { + for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { if (unlikely( ((char *)sfe < (char *)sf) || ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) { @@ -636,8 +629,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) continue; } sbp->entno = i; - INT_SET(sbp->hash, ARCH_CONVERT, - xfs_da_hashname((char *)sfe->nameval, sfe->namelen)); + sbp->hash = xfs_da_hashname((char *)sfe->nameval, sfe->namelen); sbp->name = (char *)sfe->nameval; sbp->namelen = sfe->namelen; /* These are bytes, and both on-disk, don't endian-flip */ @@ -660,12 +652,12 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) cursor->initted = 1; cursor->blkno = 0; for (sbp = sbuf, i = 0; i < nsbuf; i++, sbp++) { - if (INT_GET(sbp->hash, ARCH_CONVERT) == cursor->hashval) { + if (sbp->hash == cursor->hashval) { if (cursor->offset == count) { break; } count++; - } else if (INT_GET(sbp->hash, ARCH_CONVERT) > cursor->hashval) { + } else if (sbp->hash > cursor->hashval) { break; } } @@ -685,8 +677,8 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) ((sbp->flags & XFS_ATTR_ROOT) ? &attr_trusted : &attr_user); - if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) { - cursor->hashval = INT_GET(sbp->hash, ARCH_CONVERT); + if (cursor->hashval != sbp->hash) { + cursor->hashval = sbp->hash; cursor->offset = 0; } if (context->flags & ATTR_KERNOVAL) { @@ -696,7 +688,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) } else { if (xfs_attr_put_listent(context, namesp, sbp->name, sbp->namelen, - INT_GET(sbp->valuelen, ARCH_CONVERT))) + sbp->valuelen)) break; } cursor->offset++; @@ -720,12 +712,11 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) int bytes, i; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); entry = &leaf->entries[0]; bytes = sizeof(struct xfs_attr_sf_hdr); - for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); entry++, i++) { + for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { if (entry->flags & XFS_ATTR_INCOMPLETE) continue; /* don't copy partial entries */ if (!(entry->flags & XFS_ATTR_LOCAL)) @@ -733,11 +724,11 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i); if (name_loc->namelen >= XFS_ATTR_SF_ENTSIZE_MAX) return(0); - if (INT_GET(name_loc->valuelen, ARCH_CONVERT) >= XFS_ATTR_SF_ENTSIZE_MAX) + if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX) return(0); bytes += sizeof(struct xfs_attr_sf_entry)-1 + name_loc->namelen - + INT_GET(name_loc->valuelen, ARCH_CONVERT); + + be16_to_cpu(name_loc->valuelen); } if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && (bytes == sizeof(struct xfs_attr_sf_hdr))) @@ -766,8 +757,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) ASSERT(bp != NULL); memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount)); leaf = (xfs_attr_leafblock_t *)tmpbuffer; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); memset(bp->data, 0, XFS_LBSIZE(dp->i_mount)); /* @@ -810,7 +800,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) nargs.trans = args->trans; nargs.oknoent = 1; entry = &leaf->entries[0]; - for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); entry++, i++) { + for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { if (entry->flags & XFS_ATTR_INCOMPLETE) continue; /* don't copy partial entries */ if (!entry->nameidx) @@ -820,8 +810,8 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) nargs.name = (char *)name_loc->nameval; nargs.namelen = name_loc->namelen; nargs.value = (char *)&name_loc->nameval[nargs.namelen]; - nargs.valuelen = INT_GET(name_loc->valuelen, ARCH_CONVERT); - nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); + nargs.valuelen = be16_to_cpu(name_loc->valuelen); + nargs.hashval = be32_to_cpu(entry->hashval); nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); xfs_attr_shortform_add(&nargs, forkoff); @@ -875,13 +865,12 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args) goto out; node = bp1->data; leaf = bp2->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); /* both on-disk, don't endian-flip twice */ node->btree[0].hashval = - leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval; - INT_SET(node->btree[0].before, ARCH_CONVERT, blkno); - INT_SET(node->hdr.count, ARCH_CONVERT, 1); + leaf->entries[be16_to_cpu(leaf->hdr.count)-1 ].hashval; + node->btree[0].before = cpu_to_be32(blkno); + node->hdr.count = cpu_to_be16(1); xfs_da_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1); error = 0; out: @@ -920,19 +909,16 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) leaf = bp->data; memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); hdr = &leaf->hdr; - INT_SET(hdr->info.magic, ARCH_CONVERT, XFS_ATTR_LEAF_MAGIC); - INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount)); + hdr->info.magic = cpu_to_be16(XFS_ATTR_LEAF_MAGIC); + hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount)); if (!hdr->firstused) { - INT_SET(hdr->firstused, ARCH_CONVERT, + hdr->firstused = cpu_to_be16( XFS_LBSIZE(dp->i_mount) - XFS_ATTR_LEAF_NAME_ALIGN); } - INT_SET(hdr->freemap[0].base, ARCH_CONVERT, - sizeof(xfs_attr_leaf_hdr_t)); - INT_SET(hdr->freemap[0].size, ARCH_CONVERT, - INT_GET(hdr->firstused, ARCH_CONVERT) - - INT_GET(hdr->freemap[0].base, - ARCH_CONVERT)); + hdr->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); + hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) - + sizeof(xfs_attr_leaf_hdr_t)); xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); @@ -1004,10 +990,9 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args) int tablesize, entsize, sum, tmp, i; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); ASSERT((args->index >= 0) - && (args->index <= INT_GET(leaf->hdr.count, ARCH_CONVERT))); + && (args->index <= be16_to_cpu(leaf->hdr.count))); hdr = &leaf->hdr; entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen, args->trans->t_mountp->m_sb.sb_blocksize, NULL); @@ -1016,26 +1001,25 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args) * Search through freemap for first-fit on new name length. * (may need to figure in size of entry struct too) */ - tablesize = (INT_GET(hdr->count, ARCH_CONVERT) + 1) + tablesize = (be16_to_cpu(hdr->count) + 1) * sizeof(xfs_attr_leaf_entry_t) + sizeof(xfs_attr_leaf_hdr_t); map = &hdr->freemap[XFS_ATTR_LEAF_MAPSIZE-1]; for (sum = 0, i = XFS_ATTR_LEAF_MAPSIZE-1; i >= 0; map--, i--) { - if (tablesize > INT_GET(hdr->firstused, ARCH_CONVERT)) { - sum += INT_GET(map->size, ARCH_CONVERT); + if (tablesize > be16_to_cpu(hdr->firstused)) { + sum += be16_to_cpu(map->size); continue; } if (!map->size) continue; /* no space in this map */ tmp = entsize; - if (INT_GET(map->base, ARCH_CONVERT) - < INT_GET(hdr->firstused, ARCH_CONVERT)) + if (be16_to_cpu(map->base) < be16_to_cpu(hdr->firstused)) tmp += sizeof(xfs_attr_leaf_entry_t); - if (INT_GET(map->size, ARCH_CONVERT) >= tmp) { + if (be16_to_cpu(map->size) >= tmp) { tmp = xfs_attr_leaf_add_work(bp, args, i); return(tmp); } - sum += INT_GET(map->size, ARCH_CONVERT); + sum += be16_to_cpu(map->size); } /* @@ -1056,7 +1040,7 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args) * After compaction, the block is guaranteed to have only one * free region, in freemap[0]. If it is not big enough, give up. */ - if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) + if (be16_to_cpu(hdr->freemap[0].size) < (entsize + sizeof(xfs_attr_leaf_entry_t))) return(XFS_ERROR(ENOSPC)); @@ -1079,45 +1063,42 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) int tmp, i; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); hdr = &leaf->hdr; ASSERT((mapindex >= 0) && (mapindex < XFS_ATTR_LEAF_MAPSIZE)); - ASSERT((args->index >= 0) - && (args->index <= INT_GET(hdr->count, ARCH_CONVERT))); + ASSERT((args->index >= 0) && (args->index <= be16_to_cpu(hdr->count))); /* * Force open some space in the entry array and fill it in. */ entry = &leaf->entries[args->index]; - if (args->index < INT_GET(hdr->count, ARCH_CONVERT)) { - tmp = INT_GET(hdr->count, ARCH_CONVERT) - args->index; + if (args->index < be16_to_cpu(hdr->count)) { + tmp = be16_to_cpu(hdr->count) - args->index; tmp *= sizeof(xfs_attr_leaf_entry_t); memmove((char *)(entry+1), (char *)entry, tmp); xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); } - INT_MOD(hdr->count, ARCH_CONVERT, 1); + be16_add(&hdr->count, 1); /* * Allocate space for the new string (at the end of the run). */ map = &hdr->freemap[mapindex]; mp = args->trans->t_mountp; - ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); - ASSERT((INT_GET(map->base, ARCH_CONVERT) & 0x3) == 0); - ASSERT(INT_GET(map->size, ARCH_CONVERT) >= + ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); + ASSERT((be16_to_cpu(map->base) & 0x3) == 0); + ASSERT(be16_to_cpu(map->size) >= xfs_attr_leaf_newentsize(args->namelen, args->valuelen, mp->m_sb.sb_blocksize, NULL)); - ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); - ASSERT((INT_GET(map->size, ARCH_CONVERT) & 0x3) == 0); - INT_MOD(map->size, ARCH_CONVERT, + ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); + ASSERT((be16_to_cpu(map->size) & 0x3) == 0); + be16_add(&map->size, -xfs_attr_leaf_newentsize(args->namelen, args->valuelen, mp->m_sb.sb_blocksize, &tmp)); - INT_SET(entry->nameidx, ARCH_CONVERT, - INT_GET(map->base, ARCH_CONVERT) - + INT_GET(map->size, ARCH_CONVERT)); - INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); + entry->nameidx = cpu_to_be16(be16_to_cpu(map->base) + + be16_to_cpu(map->size)); + entry->hashval = cpu_to_be32(args->hashval); entry->flags = tmp ? XFS_ATTR_LOCAL : 0; entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE : ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0); @@ -1130,12 +1111,10 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) } xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); - ASSERT((args->index == 0) || (INT_GET(entry->hashval, ARCH_CONVERT) - >= INT_GET((entry-1)->hashval, - ARCH_CONVERT))); - ASSERT((args->index == INT_GET(hdr->count, ARCH_CONVERT)-1) || - (INT_GET(entry->hashval, ARCH_CONVERT) - <= (INT_GET((entry+1)->hashval, ARCH_CONVERT)))); + ASSERT((args->index == 0) || + (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval))); + ASSERT((args->index == be16_to_cpu(hdr->count)-1) || + (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval))); /* * Copy the attribute name and value into the new space. @@ -1149,10 +1128,10 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) if (entry->flags & XFS_ATTR_LOCAL) { name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, args->index); name_loc->namelen = args->namelen; - INT_SET(name_loc->valuelen, ARCH_CONVERT, args->valuelen); + name_loc->valuelen = cpu_to_be16(args->valuelen); memcpy((char *)name_loc->nameval, args->name, args->namelen); memcpy((char *)&name_loc->nameval[args->namelen], args->value, - INT_GET(name_loc->valuelen, ARCH_CONVERT)); + be16_to_cpu(name_loc->valuelen)); } else { name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index); name_rmt->namelen = args->namelen; @@ -1171,28 +1150,23 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) /* * Update the control info for this leaf node */ - if (INT_GET(entry->nameidx, ARCH_CONVERT) - < INT_GET(hdr->firstused, ARCH_CONVERT)) { + if (be16_to_cpu(entry->nameidx) < be16_to_cpu(hdr->firstused)) { /* both on-disk, don't endian-flip twice */ hdr->firstused = entry->nameidx; } - ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) - >= ((INT_GET(hdr->count, ARCH_CONVERT) - * sizeof(*entry))+sizeof(*hdr))); - tmp = (INT_GET(hdr->count, ARCH_CONVERT)-1) - * sizeof(xfs_attr_leaf_entry_t) + ASSERT(be16_to_cpu(hdr->firstused) >= + ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr))); + tmp = (be16_to_cpu(hdr->count)-1) * sizeof(xfs_attr_leaf_entry_t) + sizeof(xfs_attr_leaf_hdr_t); map = &hdr->freemap[0]; for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) { - if (INT_GET(map->base, ARCH_CONVERT) == tmp) { - INT_MOD(map->base, ARCH_CONVERT, - sizeof(xfs_attr_leaf_entry_t)); - INT_MOD(map->size, ARCH_CONVERT, - -sizeof(xfs_attr_leaf_entry_t)); + if (be16_to_cpu(map->base) == tmp) { + be16_add(&map->base, sizeof(xfs_attr_leaf_entry_t)); + be16_add(&map->size, + -((int)sizeof(xfs_attr_leaf_entry_t))); } } - INT_MOD(hdr->usedbytes, ARCH_CONVERT, - xfs_attr_leaf_entsize(leaf, args->index)); + be16_add(&hdr->usedbytes, xfs_attr_leaf_entsize(leaf, args->index)); xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); return(0); @@ -1223,28 +1197,25 @@ xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp) hdr_s = &leaf_s->hdr; hdr_d = &leaf_d->hdr; hdr_d->info = hdr_s->info; /* struct copy */ - INT_SET(hdr_d->firstused, ARCH_CONVERT, XFS_LBSIZE(mp)); + hdr_d->firstused = cpu_to_be16(XFS_LBSIZE(mp)); /* handle truncation gracefully */ if (!hdr_d->firstused) { - INT_SET(hdr_d->firstused, ARCH_CONVERT, + hdr_d->firstused = cpu_to_be16( XFS_LBSIZE(mp) - XFS_ATTR_LEAF_NAME_ALIGN); } hdr_d->usedbytes = 0; hdr_d->count = 0; hdr_d->holes = 0; - INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, - sizeof(xfs_attr_leaf_hdr_t)); - INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, - INT_GET(hdr_d->firstused, ARCH_CONVERT) - - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT)); + hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); + hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) - + sizeof(xfs_attr_leaf_hdr_t)); /* * Copy all entry's in the same (sorted) order, * but allocate name/value pairs packed and in sequence. */ xfs_attr_leaf_moveents(leaf_s, 0, leaf_d, 0, - (int)INT_GET(hdr_s->count, ARCH_CONVERT), mp); - + be16_to_cpu(hdr_s->count), mp); xfs_da_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1); kmem_free(tmpbuffer, XFS_LBSIZE(mp)); @@ -1279,10 +1250,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC); leaf1 = blk1->bp->data; leaf2 = blk2->bp->data; - ASSERT(INT_GET(leaf1->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); args = state->args; /* @@ -1319,22 +1288,21 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Move any entries required from leaf to leaf: */ - if (count < INT_GET(hdr1->count, ARCH_CONVERT)) { + if (count < be16_to_cpu(hdr1->count)) { /* * Figure the total bytes to be added to the destination leaf. */ /* number entries being moved */ - count = INT_GET(hdr1->count, ARCH_CONVERT) - count; - space = INT_GET(hdr1->usedbytes, ARCH_CONVERT) - totallen; + count = be16_to_cpu(hdr1->count) - count; + space = be16_to_cpu(hdr1->usedbytes) - totallen; space += count * sizeof(xfs_attr_leaf_entry_t); /* * leaf2 is the destination, compact it if it looks tight. */ - max = INT_GET(hdr2->firstused, ARCH_CONVERT) + max = be16_to_cpu(hdr2->firstused) - sizeof(xfs_attr_leaf_hdr_t); - max -= INT_GET(hdr2->count, ARCH_CONVERT) - * sizeof(xfs_attr_leaf_entry_t); + max -= be16_to_cpu(hdr2->count) * sizeof(xfs_attr_leaf_entry_t); if (space > max) { xfs_attr_leaf_compact(args->trans, blk2->bp); } @@ -1342,13 +1310,12 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Move high entries from leaf1 to low end of leaf2. */ - xfs_attr_leaf_moveents(leaf1, - INT_GET(hdr1->count, ARCH_CONVERT)-count, + xfs_attr_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count, leaf2, 0, count, state->mp); xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); - } else if (count > INT_GET(hdr1->count, ARCH_CONVERT)) { + } else if (count > be16_to_cpu(hdr1->count)) { /* * I assert that since all callers pass in an empty * second buffer, this code should never execute. @@ -1358,17 +1325,16 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * Figure the total bytes to be added to the destination leaf. */ /* number entries being moved */ - count -= INT_GET(hdr1->count, ARCH_CONVERT); - space = totallen - INT_GET(hdr1->usedbytes, ARCH_CONVERT); + count -= be16_to_cpu(hdr1->count); + space = totallen - be16_to_cpu(hdr1->usedbytes); space += count * sizeof(xfs_attr_leaf_entry_t); /* * leaf1 is the destination, compact it if it looks tight. */ - max = INT_GET(hdr1->firstused, ARCH_CONVERT) + max = be16_to_cpu(hdr1->firstused) - sizeof(xfs_attr_leaf_hdr_t); - max -= INT_GET(hdr1->count, ARCH_CONVERT) - * sizeof(xfs_attr_leaf_entry_t); + max -= be16_to_cpu(hdr1->count) * sizeof(xfs_attr_leaf_entry_t); if (space > max) { xfs_attr_leaf_compact(args->trans, blk1->bp); } @@ -1377,8 +1343,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * Move low entries from leaf2 to high end of leaf1. */ xfs_attr_leaf_moveents(leaf2, 0, leaf1, - (int)INT_GET(hdr1->count, ARCH_CONVERT), count, - state->mp); + be16_to_cpu(hdr1->count), count, state->mp); xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); @@ -1387,12 +1352,10 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Copy out last hashval in each block for B-tree code. */ - blk1->hashval = - INT_GET(leaf1->entries[INT_GET(leaf1->hdr.count, - ARCH_CONVERT)-1].hashval, ARCH_CONVERT); - blk2->hashval = - INT_GET(leaf2->entries[INT_GET(leaf2->hdr.count, - ARCH_CONVERT)-1].hashval, ARCH_CONVERT); + blk1->hashval = be32_to_cpu( + leaf1->entries[be16_to_cpu(leaf1->hdr.count)-1].hashval); + blk2->hashval = be32_to_cpu( + leaf2->entries[be16_to_cpu(leaf2->hdr.count)-1].hashval); /* * Adjust the expected index for insertion. @@ -1406,13 +1369,12 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * inserting. The index/blkno fields refer to the "old" entry, * while the index2/blkno2 fields refer to the "new" entry. */ - if (blk1->index > INT_GET(leaf1->hdr.count, ARCH_CONVERT)) { + if (blk1->index > be16_to_cpu(leaf1->hdr.count)) { ASSERT(state->inleaf == 0); - blk2->index = blk1->index - - INT_GET(leaf1->hdr.count, ARCH_CONVERT); + blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); args->index = args->index2 = blk2->index; args->blkno = args->blkno2 = blk2->blkno; - } else if (blk1->index == INT_GET(leaf1->hdr.count, ARCH_CONVERT)) { + } else if (blk1->index == be16_to_cpu(leaf1->hdr.count)) { if (state->inleaf) { args->index = blk1->index; args->blkno = blk1->blkno; @@ -1420,7 +1382,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, args->blkno2 = blk2->blkno; } else { blk2->index = blk1->index - - INT_GET(leaf1->hdr.count, ARCH_CONVERT); + - be16_to_cpu(leaf1->hdr.count); args->index = args->index2 = blk2->index; args->blkno = args->blkno2 = blk2->blkno; } @@ -1464,15 +1426,14 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, * Examine entries until we reduce the absolute difference in * byte usage between the two blocks to a minimum. */ - max = INT_GET(hdr1->count, ARCH_CONVERT) - + INT_GET(hdr2->count, ARCH_CONVERT); + max = be16_to_cpu(hdr1->count) + be16_to_cpu(hdr2->count); half = (max+1) * sizeof(*entry); - half += INT_GET(hdr1->usedbytes, ARCH_CONVERT) - + INT_GET(hdr2->usedbytes, ARCH_CONVERT) - + xfs_attr_leaf_newentsize( - state->args->namelen, - state->args->valuelen, - state->blocksize, NULL); + half += be16_to_cpu(hdr1->usedbytes) + + be16_to_cpu(hdr2->usedbytes) + + xfs_attr_leaf_newentsize( + state->args->namelen, + state->args->valuelen, + state->blocksize, NULL); half /= 2; lastdelta = state->blocksize; entry = &leaf1->entries[0]; @@ -1498,7 +1459,7 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, /* * Wrap around into the second block if necessary. */ - if (count == INT_GET(hdr1->count, ARCH_CONVERT)) { + if (count == be16_to_cpu(hdr1->count)) { leaf1 = leaf2; entry = &leaf1->entries[0]; index = 0; @@ -1566,12 +1527,12 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) */ blk = &state->path.blk[ state->path.active-1 ]; info = blk->bp->data; - ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC); leaf = (xfs_attr_leafblock_t *)info; - count = INT_GET(leaf->hdr.count, ARCH_CONVERT); + count = be16_to_cpu(leaf->hdr.count); bytes = sizeof(xfs_attr_leaf_hdr_t) + count * sizeof(xfs_attr_leaf_entry_t) + - INT_GET(leaf->hdr.usedbytes, ARCH_CONVERT); + be16_to_cpu(leaf->hdr.usedbytes); if (bytes > (state->blocksize >> 1)) { *action = 0; /* blk over 50%, don't try to join */ return(0); @@ -1588,7 +1549,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) * Make altpath point to the block we want to keep and * path point to the block we want to drop (this one). */ - forward = info->forw; + forward = (info->forw != 0); memcpy(&state->altpath, &state->path, sizeof(state->path)); error = xfs_da_path_shift(state, &state->altpath, forward, 0, &retval); @@ -1610,13 +1571,12 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) * to shrink an attribute list over time. */ /* start with smaller blk num */ - forward = (INT_GET(info->forw, ARCH_CONVERT) - < INT_GET(info->back, ARCH_CONVERT)); + forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); for (i = 0; i < 2; forward = !forward, i++) { if (forward) - blkno = INT_GET(info->forw, ARCH_CONVERT); + blkno = be32_to_cpu(info->forw); else - blkno = INT_GET(info->back, ARCH_CONVERT); + blkno = be32_to_cpu(info->back); if (blkno == 0) continue; error = xfs_da_read_buf(state->args->trans, state->args->dp, @@ -1626,14 +1586,13 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) ASSERT(bp != NULL); leaf = (xfs_attr_leafblock_t *)info; - count = INT_GET(leaf->hdr.count, ARCH_CONVERT); + count = be16_to_cpu(leaf->hdr.count); bytes = state->blocksize - (state->blocksize>>2); - bytes -= INT_GET(leaf->hdr.usedbytes, ARCH_CONVERT); + bytes -= be16_to_cpu(leaf->hdr.usedbytes); leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - count += INT_GET(leaf->hdr.count, ARCH_CONVERT); - bytes -= INT_GET(leaf->hdr.usedbytes, ARCH_CONVERT); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + count += be16_to_cpu(leaf->hdr.count); + bytes -= be16_to_cpu(leaf->hdr.usedbytes); bytes -= count * sizeof(xfs_attr_leaf_entry_t); bytes -= sizeof(xfs_attr_leaf_hdr_t); xfs_da_brelse(state->args->trans, bp); @@ -1685,21 +1644,18 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) xfs_mount_t *mp; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); hdr = &leaf->hdr; mp = args->trans->t_mountp; - ASSERT((INT_GET(hdr->count, ARCH_CONVERT) > 0) - && (INT_GET(hdr->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); + ASSERT((be16_to_cpu(hdr->count) > 0) + && (be16_to_cpu(hdr->count) < (XFS_LBSIZE(mp)/8))); ASSERT((args->index >= 0) - && (args->index < INT_GET(hdr->count, ARCH_CONVERT))); - ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) - >= ((INT_GET(hdr->count, ARCH_CONVERT) - * sizeof(*entry))+sizeof(*hdr))); + && (args->index < be16_to_cpu(hdr->count))); + ASSERT(be16_to_cpu(hdr->firstused) >= + ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr))); entry = &leaf->entries[args->index]; - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) - >= INT_GET(hdr->firstused, ARCH_CONVERT)); - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); + ASSERT(be16_to_cpu(entry->nameidx) >= be16_to_cpu(hdr->firstused)); + ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); /* * Scan through free region table: @@ -1707,33 +1663,30 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) * find smallest free region in case we need to replace it, * adjust any map that borders the entry table, */ - tablesize = INT_GET(hdr->count, ARCH_CONVERT) - * sizeof(xfs_attr_leaf_entry_t) + tablesize = be16_to_cpu(hdr->count) * sizeof(xfs_attr_leaf_entry_t) + sizeof(xfs_attr_leaf_hdr_t); map = &hdr->freemap[0]; - tmp = INT_GET(map->size, ARCH_CONVERT); + tmp = be16_to_cpu(map->size); before = after = -1; smallest = XFS_ATTR_LEAF_MAPSIZE - 1; entsize = xfs_attr_leaf_entsize(leaf, args->index); for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) { - ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); - ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); - if (INT_GET(map->base, ARCH_CONVERT) == tablesize) { - INT_MOD(map->base, ARCH_CONVERT, - -sizeof(xfs_attr_leaf_entry_t)); - INT_MOD(map->size, ARCH_CONVERT, - sizeof(xfs_attr_leaf_entry_t)); + ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); + ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); + if (be16_to_cpu(map->base) == tablesize) { + be16_add(&map->base, + -((int)sizeof(xfs_attr_leaf_entry_t))); + be16_add(&map->size, sizeof(xfs_attr_leaf_entry_t)); } - if ((INT_GET(map->base, ARCH_CONVERT) - + INT_GET(map->size, ARCH_CONVERT)) - == INT_GET(entry->nameidx, ARCH_CONVERT)) { + if ((be16_to_cpu(map->base) + be16_to_cpu(map->size)) + == be16_to_cpu(entry->nameidx)) { before = i; - } else if (INT_GET(map->base, ARCH_CONVERT) - == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) { + } else if (be16_to_cpu(map->base) + == (be16_to_cpu(entry->nameidx) + entsize)) { after = i; - } else if (INT_GET(map->size, ARCH_CONVERT) < tmp) { - tmp = INT_GET(map->size, ARCH_CONVERT); + } else if (be16_to_cpu(map->size) < tmp) { + tmp = be16_to_cpu(map->size); smallest = i; } } @@ -1745,38 +1698,35 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) if ((before >= 0) || (after >= 0)) { if ((before >= 0) && (after >= 0)) { map = &hdr->freemap[before]; - INT_MOD(map->size, ARCH_CONVERT, entsize); - INT_MOD(map->size, ARCH_CONVERT, - INT_GET(hdr->freemap[after].size, - ARCH_CONVERT)); + be16_add(&map->size, entsize); + be16_add(&map->size, + be16_to_cpu(hdr->freemap[after].size)); hdr->freemap[after].base = 0; hdr->freemap[after].size = 0; } else if (before >= 0) { map = &hdr->freemap[before]; - INT_MOD(map->size, ARCH_CONVERT, entsize); + be16_add(&map->size, entsize); } else { map = &hdr->freemap[after]; /* both on-disk, don't endian flip twice */ map->base = entry->nameidx; - INT_MOD(map->size, ARCH_CONVERT, entsize); + be16_add(&map->size, entsize); } } else { /* * Replace smallest region (if it is smaller than free'd entry) */ map = &hdr->freemap[smallest]; - if (INT_GET(map->size, ARCH_CONVERT) < entsize) { - INT_SET(map->base, ARCH_CONVERT, - INT_GET(entry->nameidx, ARCH_CONVERT)); - INT_SET(map->size, ARCH_CONVERT, entsize); + if (be16_to_cpu(map->size) < entsize) { + map->base = cpu_to_be16(be16_to_cpu(entry->nameidx)); + map->size = cpu_to_be16(entsize); } } /* * Did we remove the first entry? */ - if (INT_GET(entry->nameidx, ARCH_CONVERT) - == INT_GET(hdr->firstused, ARCH_CONVERT)) + if (be16_to_cpu(entry->nameidx) == be16_to_cpu(hdr->firstused)) smallest = 1; else smallest = 0; @@ -1785,18 +1735,18 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) * Compress the remaining entries and zero out the removed stuff. */ memset(XFS_ATTR_LEAF_NAME(leaf, args->index), 0, entsize); - INT_MOD(hdr->usedbytes, ARCH_CONVERT, -entsize); + be16_add(&hdr->usedbytes, -entsize); xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, XFS_ATTR_LEAF_NAME(leaf, args->index), entsize)); - tmp = (INT_GET(hdr->count, ARCH_CONVERT) - args->index) + tmp = (be16_to_cpu(hdr->count) - args->index) * sizeof(xfs_attr_leaf_entry_t); memmove((char *)entry, (char *)(entry+1), tmp); - INT_MOD(hdr->count, ARCH_CONVERT, -1); + be16_add(&hdr->count, -1); xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); - entry = &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)]; + entry = &leaf->entries[be16_to_cpu(hdr->count)]; memset((char *)entry, 0, sizeof(xfs_attr_leaf_entry_t)); /* @@ -1808,18 +1758,17 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) if (smallest) { tmp = XFS_LBSIZE(mp); entry = &leaf->entries[0]; - for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; - i >= 0; entry++, i--) { - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) - >= INT_GET(hdr->firstused, ARCH_CONVERT)); - ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) - < XFS_LBSIZE(mp)); - if (INT_GET(entry->nameidx, ARCH_CONVERT) < tmp) - tmp = INT_GET(entry->nameidx, ARCH_CONVERT); + for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { + ASSERT(be16_to_cpu(entry->nameidx) >= + be16_to_cpu(hdr->firstused)); + ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); + + if (be16_to_cpu(entry->nameidx) < tmp) + tmp = be16_to_cpu(entry->nameidx); } - INT_SET(hdr->firstused, ARCH_CONVERT, tmp); + hdr->firstused = cpu_to_be16(tmp); if (!hdr->firstused) { - INT_SET(hdr->firstused, ARCH_CONVERT, + hdr->firstused = cpu_to_be16( tmp - XFS_ATTR_LEAF_NAME_ALIGN); } } else { @@ -1833,9 +1782,8 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) * "join" the leaf with a sibling if so. */ tmp = sizeof(xfs_attr_leaf_hdr_t); - tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) - * sizeof(xfs_attr_leaf_entry_t); - tmp += INT_GET(leaf->hdr.usedbytes, ARCH_CONVERT); + tmp += be16_to_cpu(leaf->hdr.count) * sizeof(xfs_attr_leaf_entry_t); + tmp += be16_to_cpu(leaf->hdr.usedbytes); return(tmp < mp->m_attr_magicpct); /* leaf is < 37% full */ } @@ -1859,20 +1807,16 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, ASSERT(save_blk->magic == XFS_ATTR_LEAF_MAGIC); drop_leaf = drop_blk->bp->data; save_leaf = save_blk->bp->data; - ASSERT(INT_GET(drop_leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(INT_GET(save_leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); drop_hdr = &drop_leaf->hdr; save_hdr = &save_leaf->hdr; /* * Save last hashval from dying block for later Btree fixup. */ - drop_blk->hashval = - INT_GET(drop_leaf->entries[INT_GET(drop_leaf->hdr.count, - ARCH_CONVERT)-1].hashval, - ARCH_CONVERT); + drop_blk->hashval = be32_to_cpu( + drop_leaf->entries[be16_to_cpu(drop_leaf->hdr.count)-1].hashval); /* * Check if we need a temp buffer, or can we do it in place. @@ -1886,12 +1830,11 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, */ if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) { xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf, 0, - (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); + be16_to_cpu(drop_hdr->count), mp); } else { xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf, - INT_GET(save_hdr->count, ARCH_CONVERT), - (int)INT_GET(drop_hdr->count, ARCH_CONVERT), - mp); + be16_to_cpu(save_hdr->count), + be16_to_cpu(drop_hdr->count), mp); } } else { /* @@ -1905,28 +1848,24 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, tmp_hdr = &tmp_leaf->hdr; tmp_hdr->info = save_hdr->info; /* struct copy */ tmp_hdr->count = 0; - INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize); + tmp_hdr->firstused = cpu_to_be16(state->blocksize); if (!tmp_hdr->firstused) { - INT_SET(tmp_hdr->firstused, ARCH_CONVERT, + tmp_hdr->firstused = cpu_to_be16( state->blocksize - XFS_ATTR_LEAF_NAME_ALIGN); } tmp_hdr->usedbytes = 0; if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) { xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, 0, - (int)INT_GET(drop_hdr->count, ARCH_CONVERT), - mp); + be16_to_cpu(drop_hdr->count), mp); xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf, - INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT), - (int)INT_GET(save_hdr->count, ARCH_CONVERT), - mp); + be16_to_cpu(tmp_leaf->hdr.count), + be16_to_cpu(save_hdr->count), mp); } else { xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf, 0, - (int)INT_GET(save_hdr->count, ARCH_CONVERT), - mp); + be16_to_cpu(save_hdr->count), mp); xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, - INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT), - (int)INT_GET(drop_hdr->count, ARCH_CONVERT), - mp); + be16_to_cpu(tmp_leaf->hdr.count), + be16_to_cpu(drop_hdr->count), mp); } memcpy((char *)save_leaf, (char *)tmp_leaf, state->blocksize); kmem_free(tmpbuffer, state->blocksize); @@ -1938,10 +1877,8 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, /* * Copy out last hashval in each block for B-tree code. */ - save_blk->hashval = - INT_GET(save_leaf->entries[INT_GET(save_leaf->hdr.count, - ARCH_CONVERT)-1].hashval, - ARCH_CONVERT); + save_blk->hashval = be32_to_cpu( + save_leaf->entries[be16_to_cpu(save_leaf->hdr.count)-1].hashval); } /*======================================================================== @@ -1972,48 +1909,45 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) xfs_dahash_t hashval; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.count) < (XFS_LBSIZE(args->dp->i_mount)/8)); /* * Binary search. (note: small blocks will skip this loop) */ hashval = args->hashval; - probe = span = INT_GET(leaf->hdr.count, ARCH_CONVERT) / 2; + probe = span = be16_to_cpu(leaf->hdr.count) / 2; for (entry = &leaf->entries[probe]; span > 4; entry = &leaf->entries[probe]) { span /= 2; - if (INT_GET(entry->hashval, ARCH_CONVERT) < hashval) + if (be32_to_cpu(entry->hashval) < hashval) probe += span; - else if (INT_GET(entry->hashval, ARCH_CONVERT) > hashval) + else if (be32_to_cpu(entry->hashval) > hashval) probe -= span; else break; } ASSERT((probe >= 0) && (!leaf->hdr.count - || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)))); - ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) - == hashval)); + || (probe < be16_to_cpu(leaf->hdr.count)))); + ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval)); /* * Since we may have duplicate hashval's, find the first matching * hashval in the leaf. */ - while ((probe > 0) && (INT_GET(entry->hashval, ARCH_CONVERT) - >= hashval)) { + while ((probe > 0) && (be32_to_cpu(entry->hashval) >= hashval)) { entry--; probe--; } - while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) - && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) { + while ((probe < be16_to_cpu(leaf->hdr.count)) && + (be32_to_cpu(entry->hashval) < hashval)) { entry++; probe++; } - if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) - || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) { + if ((probe == be16_to_cpu(leaf->hdr.count)) || + (be32_to_cpu(entry->hashval) != hashval)) { args->index = probe; return(XFS_ERROR(ENOATTR)); } @@ -2021,8 +1955,8 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) /* * Duplicate keys may be present, so search all of them for a match. */ - for ( ; (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) - && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval); + for ( ; (probe < be16_to_cpu(leaf->hdr.count)) && + (be32_to_cpu(entry->hashval) == hashval); entry++, probe++) { /* * GROT: Add code to remove incomplete entries. @@ -2064,11 +1998,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) ((entry->flags & XFS_ATTR_ROOT) != 0)) continue; args->index = probe; - args->rmtblkno - = INT_GET(name_rmt->valueblk, ARCH_CONVERT); + args->rmtblkno = be32_to_cpu(name_rmt->valueblk); args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, - INT_GET(name_rmt->valuelen, - ARCH_CONVERT)); + be32_to_cpu(name_rmt->valuelen)); return(XFS_ERROR(EEXIST)); } } @@ -2090,18 +2022,17 @@ xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args) xfs_attr_leaf_name_remote_t *name_rmt; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.count) < (XFS_LBSIZE(args->dp->i_mount)/8)); - ASSERT(args->index < ((int)INT_GET(leaf->hdr.count, ARCH_CONVERT))); + ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); entry = &leaf->entries[args->index]; if (entry->flags & XFS_ATTR_LOCAL) { name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, args->index); ASSERT(name_loc->namelen == args->namelen); ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0); - valuelen = INT_GET(name_loc->valuelen, ARCH_CONVERT); + valuelen = be16_to_cpu(name_loc->valuelen); if (args->flags & ATTR_KERNOVAL) { args->valuelen = valuelen; return(0); @@ -2116,8 +2047,8 @@ xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args) name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index); ASSERT(name_rmt->namelen == args->namelen); ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); - valuelen = INT_GET(name_rmt->valuelen, ARCH_CONVERT); - args->rmtblkno = INT_GET(name_rmt->valueblk, ARCH_CONVERT); + valuelen = be32_to_cpu(name_rmt->valuelen); + args->rmtblkno = be32_to_cpu(name_rmt->valueblk); args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, valuelen); if (args->flags & ATTR_KERNOVAL) { args->valuelen = valuelen; @@ -2159,32 +2090,29 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, /* * Set up environment. */ - ASSERT(INT_GET(leaf_s->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(INT_GET(leaf_d->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); hdr_s = &leaf_s->hdr; hdr_d = &leaf_d->hdr; - ASSERT((INT_GET(hdr_s->count, ARCH_CONVERT) > 0) - && (INT_GET(hdr_s->count, ARCH_CONVERT) - < (XFS_LBSIZE(mp)/8))); - ASSERT(INT_GET(hdr_s->firstused, ARCH_CONVERT) >= - ((INT_GET(hdr_s->count, ARCH_CONVERT) + ASSERT((be16_to_cpu(hdr_s->count) > 0) && + (be16_to_cpu(hdr_s->count) < (XFS_LBSIZE(mp)/8))); + ASSERT(be16_to_cpu(hdr_s->firstused) >= + ((be16_to_cpu(hdr_s->count) * sizeof(*entry_s))+sizeof(*hdr_s))); - ASSERT(INT_GET(hdr_d->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)); - ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= - ((INT_GET(hdr_d->count, ARCH_CONVERT) + ASSERT(be16_to_cpu(hdr_d->count) < (XFS_LBSIZE(mp)/8)); + ASSERT(be16_to_cpu(hdr_d->firstused) >= + ((be16_to_cpu(hdr_d->count) * sizeof(*entry_d))+sizeof(*hdr_d))); - ASSERT(start_s < INT_GET(hdr_s->count, ARCH_CONVERT)); - ASSERT(start_d <= INT_GET(hdr_d->count, ARCH_CONVERT)); - ASSERT(count <= INT_GET(hdr_s->count, ARCH_CONVERT)); + ASSERT(start_s < be16_to_cpu(hdr_s->count)); + ASSERT(start_d <= be16_to_cpu(hdr_d->count)); + ASSERT(count <= be16_to_cpu(hdr_s->count)); /* * Move the entries in the destination leaf up to make a hole? */ - if (start_d < INT_GET(hdr_d->count, ARCH_CONVERT)) { - tmp = INT_GET(hdr_d->count, ARCH_CONVERT) - start_d; + if (start_d < be16_to_cpu(hdr_d->count)) { + tmp = be16_to_cpu(hdr_d->count) - start_d; tmp *= sizeof(xfs_attr_leaf_entry_t); entry_s = &leaf_d->entries[start_d]; entry_d = &leaf_d->entries[start_d + count]; @@ -2199,8 +2127,8 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, entry_d = &leaf_d->entries[start_d]; desti = start_d; for (i = 0; i < count; entry_s++, entry_d++, desti++, i++) { - ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) - >= INT_GET(hdr_s->firstused, ARCH_CONVERT)); + ASSERT(be16_to_cpu(entry_s->nameidx) + >= be16_to_cpu(hdr_s->firstused)); tmp = xfs_attr_leaf_entsize(leaf_s, start_s + i); #ifdef GROT /* @@ -2210,35 +2138,35 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, */ if (entry_s->flags & XFS_ATTR_INCOMPLETE) { /* skip partials? */ memset(XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), 0, tmp); - INT_MOD(hdr_s->usedbytes, ARCH_CONVERT, -tmp); - INT_MOD(hdr_s->count, ARCH_CONVERT, -1); + be16_add(&hdr_s->usedbytes, -tmp); + be16_add(&hdr_s->count, -1); entry_d--; /* to compensate for ++ in loop hdr */ desti--; if ((start_s + i) < offset) result++; /* insertion index adjustment */ } else { #endif /* GROT */ - INT_MOD(hdr_d->firstused, ARCH_CONVERT, -tmp); + be16_add(&hdr_d->firstused, -tmp); /* both on-disk, don't endian flip twice */ entry_d->hashval = entry_s->hashval; /* both on-disk, don't endian flip twice */ entry_d->nameidx = hdr_d->firstused; entry_d->flags = entry_s->flags; - ASSERT(INT_GET(entry_d->nameidx, ARCH_CONVERT) + tmp + ASSERT(be16_to_cpu(entry_d->nameidx) + tmp <= XFS_LBSIZE(mp)); memmove(XFS_ATTR_LEAF_NAME(leaf_d, desti), XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), tmp); - ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) + tmp + ASSERT(be16_to_cpu(entry_s->nameidx) + tmp <= XFS_LBSIZE(mp)); memset(XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), 0, tmp); - INT_MOD(hdr_s->usedbytes, ARCH_CONVERT, -tmp); - INT_MOD(hdr_d->usedbytes, ARCH_CONVERT, tmp); - INT_MOD(hdr_s->count, ARCH_CONVERT, -1); - INT_MOD(hdr_d->count, ARCH_CONVERT, 1); - tmp = INT_GET(hdr_d->count, ARCH_CONVERT) + be16_add(&hdr_s->usedbytes, -tmp); + be16_add(&hdr_d->usedbytes, tmp); + be16_add(&hdr_s->count, -1); + be16_add(&hdr_d->count, 1); + tmp = be16_to_cpu(hdr_d->count) * sizeof(xfs_attr_leaf_entry_t) + sizeof(xfs_attr_leaf_hdr_t); - ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= tmp); + ASSERT(be16_to_cpu(hdr_d->firstused) >= tmp); #ifdef GROT } #endif /* GROT */ @@ -2247,7 +2175,7 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, /* * Zero out the entries we just copied. */ - if (start_s == INT_GET(hdr_s->count, ARCH_CONVERT)) { + if (start_s == be16_to_cpu(hdr_s->count)) { tmp = count * sizeof(xfs_attr_leaf_entry_t); entry_s = &leaf_s->entries[start_s]; ASSERT(((char *)entry_s + tmp) <= @@ -2258,15 +2186,14 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, * Move the remaining entries down to fill the hole, * then zero the entries at the top. */ - tmp = INT_GET(hdr_s->count, ARCH_CONVERT) - count; + tmp = be16_to_cpu(hdr_s->count) - count; tmp *= sizeof(xfs_attr_leaf_entry_t); entry_s = &leaf_s->entries[start_s + count]; entry_d = &leaf_s->entries[start_s]; memmove((char *)entry_d, (char *)entry_s, tmp); tmp = count * sizeof(xfs_attr_leaf_entry_t); - entry_s = &leaf_s->entries[INT_GET(hdr_s->count, - ARCH_CONVERT)]; + entry_s = &leaf_s->entries[be16_to_cpu(hdr_s->count)]; ASSERT(((char *)entry_s + tmp) <= ((char *)leaf_s + XFS_LBSIZE(mp))); memset((char *)entry_s, 0, tmp); @@ -2275,14 +2202,11 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, /* * Fill in the freemap information */ - INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, - sizeof(xfs_attr_leaf_hdr_t)); - INT_MOD(hdr_d->freemap[0].base, ARCH_CONVERT, - INT_GET(hdr_d->count, ARCH_CONVERT) - * sizeof(xfs_attr_leaf_entry_t)); - INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, - INT_GET(hdr_d->firstused, ARCH_CONVERT) - - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT)); + hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); + be16_add(&hdr_d->freemap[0].base, be16_to_cpu(hdr_d->count) * + sizeof(xfs_attr_leaf_entry_t)); + hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) + - be16_to_cpu(hdr_d->freemap[0].base)); hdr_d->freemap[1].base = 0; hdr_d->freemap[2].base = 0; hdr_d->freemap[1].size = 0; @@ -2301,18 +2225,16 @@ xfs_attr_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) leaf1 = leaf1_bp->data; leaf2 = leaf2_bp->data; - ASSERT((INT_GET(leaf1->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC) && - (INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC)); - if ( (INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0) - && (INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0) - && ( (INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) < - INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) - || (INT_GET(leaf2->entries[INT_GET(leaf2->hdr.count, - ARCH_CONVERT)-1].hashval, ARCH_CONVERT) < - INT_GET(leaf1->entries[INT_GET(leaf1->hdr.count, - ARCH_CONVERT)-1].hashval, ARCH_CONVERT))) ) { + ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC) && + (be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC)); + if ((be16_to_cpu(leaf1->hdr.count) > 0) && + (be16_to_cpu(leaf2->hdr.count) > 0) && + ((be32_to_cpu(leaf2->entries[0].hashval) < + be32_to_cpu(leaf1->entries[0].hashval)) || + (be32_to_cpu(leaf2->entries[ + be16_to_cpu(leaf2->hdr.count)-1].hashval) < + be32_to_cpu(leaf1->entries[ + be16_to_cpu(leaf1->hdr.count)-1].hashval)))) { return(1); } return(0); @@ -2327,14 +2249,12 @@ xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count) xfs_attr_leafblock_t *leaf; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); if (count) - *count = INT_GET(leaf->hdr.count, ARCH_CONVERT); + *count = be16_to_cpu(leaf->hdr.count); if (!leaf->hdr.count) return(0); - return(INT_GET(leaf->entries[INT_GET(leaf->hdr.count, - ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); + return be32_to_cpu(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval); } /* @@ -2348,13 +2268,11 @@ xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index) xfs_attr_leaf_name_remote_t *name_rmt; int size; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); if (leaf->entries[index].flags & XFS_ATTR_LOCAL) { name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, index); size = XFS_ATTR_LEAF_ENTSIZE_LOCAL(name_loc->namelen, - INT_GET(name_loc->valuelen, - ARCH_CONVERT)); + be16_to_cpu(name_loc->valuelen)); } else { name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, index); size = XFS_ATTR_LEAF_ENTSIZE_REMOTE(name_rmt->namelen); @@ -2412,22 +2330,20 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) */ if (context->resynch) { entry = &leaf->entries[0]; - for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); - entry++, i++) { - if (INT_GET(entry->hashval, ARCH_CONVERT) - == cursor->hashval) { + for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { + if (be32_to_cpu(entry->hashval) == cursor->hashval) { if (cursor->offset == context->dupcnt) { context->dupcnt = 0; break; } context->dupcnt++; - } else if (INT_GET(entry->hashval, ARCH_CONVERT) - > cursor->hashval) { + } else if (be32_to_cpu(entry->hashval) > + cursor->hashval) { context->dupcnt = 0; break; } } - if (i == INT_GET(leaf->hdr.count, ARCH_CONVERT)) { + if (i == be16_to_cpu(leaf->hdr.count)) { xfs_attr_trace_l_c("not found", context); return(0); } @@ -2441,12 +2357,12 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) * We have found our place, start copying out the new attributes. */ retval = 0; - for ( ; (i < INT_GET(leaf->hdr.count, ARCH_CONVERT)) + for ( ; (i < be16_to_cpu(leaf->hdr.count)) && (retval == 0); entry++, i++) { attrnames_t *namesp; - if (INT_GET(entry->hashval, ARCH_CONVERT) != cursor->hashval) { - cursor->hashval = INT_GET(entry->hashval, ARCH_CONVERT); + if (be32_to_cpu(entry->hashval) != cursor->hashval) { + cursor->hashval = be32_to_cpu(entry->hashval); cursor->offset = 0; } @@ -2475,8 +2391,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) retval = xfs_attr_put_listent(context, namesp, (char *)name_loc->nameval, (int)name_loc->namelen, - (int)INT_GET(name_loc->valuelen, - ARCH_CONVERT)); + be16_to_cpu(name_loc->valuelen)); } } else { name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i); @@ -2488,8 +2403,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) retval = xfs_attr_put_listent(context, namesp, (char *)name_rmt->name, (int)name_rmt->namelen, - (int)INT_GET(name_rmt->valuelen, - ARCH_CONVERT)); + be32_to_cpu(name_rmt->valuelen)); } } if (retval == 0) { @@ -2596,9 +2510,8 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) ASSERT(bp != NULL); leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(args->index < INT_GET(leaf->hdr.count, ARCH_CONVERT)); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); ASSERT(args->index >= 0); entry = &leaf->entries[ args->index ]; ASSERT(entry->flags & XFS_ATTR_INCOMPLETE); @@ -2613,7 +2526,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) namelen = name_rmt->namelen; name = (char *)name_rmt->name; } - ASSERT(INT_GET(entry->hashval, ARCH_CONVERT) == args->hashval); + ASSERT(be32_to_cpu(entry->hashval) == args->hashval); ASSERT(namelen == args->namelen); ASSERT(memcmp(name, args->name, namelen) == 0); #endif /* DEBUG */ @@ -2625,8 +2538,8 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) if (args->rmtblkno) { ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0); name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index); - INT_SET(name_rmt->valueblk, ARCH_CONVERT, args->rmtblkno); - INT_SET(name_rmt->valuelen, ARCH_CONVERT, args->valuelen); + name_rmt->valueblk = cpu_to_be32(args->rmtblkno); + name_rmt->valuelen = cpu_to_be32(args->valuelen); xfs_da_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); } @@ -2663,9 +2576,8 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args) ASSERT(bp != NULL); leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(args->index < INT_GET(leaf->hdr.count, ARCH_CONVERT)); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); ASSERT(args->index >= 0); entry = &leaf->entries[ args->index ]; @@ -2736,16 +2648,14 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) } leaf1 = bp1->data; - ASSERT(INT_GET(leaf1->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(args->index < INT_GET(leaf1->hdr.count, ARCH_CONVERT)); + ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(args->index < be16_to_cpu(leaf1->hdr.count)); ASSERT(args->index >= 0); entry1 = &leaf1->entries[ args->index ]; leaf2 = bp2->data; - ASSERT(INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); - ASSERT(args->index2 < INT_GET(leaf2->hdr.count, ARCH_CONVERT)); + ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); + ASSERT(args->index2 < be16_to_cpu(leaf2->hdr.count)); ASSERT(args->index2 >= 0); entry2 = &leaf2->entries[ args->index2 ]; @@ -2768,7 +2678,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) namelen2 = name_rmt->namelen; name2 = (char *)name_rmt->name; } - ASSERT(INT_GET(entry1->hashval, ARCH_CONVERT) == INT_GET(entry2->hashval, ARCH_CONVERT)); + ASSERT(be32_to_cpu(entry1->hashval) == be32_to_cpu(entry2->hashval)); ASSERT(namelen1 == namelen2); ASSERT(memcmp(name1, name2, namelen1) == 0); #endif /* DEBUG */ @@ -2782,8 +2692,8 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) if (args->rmtblkno) { ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0); name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf1, args->index); - INT_SET(name_rmt->valueblk, ARCH_CONVERT, args->rmtblkno); - INT_SET(name_rmt->valuelen, ARCH_CONVERT, args->valuelen); + name_rmt->valueblk = cpu_to_be32(args->rmtblkno); + name_rmt->valuelen = cpu_to_be32(args->valuelen); xfs_da_log_buf(args->trans, bp1, XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt))); } @@ -2842,9 +2752,9 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) * This is a depth-first traversal! */ info = bp->data; - if (INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) { + if (be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC) { error = xfs_attr_node_inactive(trans, dp, bp, 1); - } else if (INT_GET(info->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC) { + } else if (be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC) { error = xfs_attr_leaf_inactive(trans, dp, bp); } else { error = XFS_ERROR(EIO); @@ -2892,15 +2802,14 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, } node = bp->data; - ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) - == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); parent_blkno = xfs_da_blkno(bp); /* save for re-read later */ - count = INT_GET(node->hdr.count, ARCH_CONVERT); + count = be16_to_cpu(node->hdr.count); if (!count) { xfs_da_brelse(*trans, bp); return(0); } - child_fsb = INT_GET(node->btree[0].before, ARCH_CONVERT); + child_fsb = be32_to_cpu(node->btree[0].before); xfs_da_brelse(*trans, bp); /* no locks for later trans */ /* @@ -2927,12 +2836,10 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, * Invalidate the subtree, however we have to. */ info = child_bp->data; - if (INT_GET(info->magic, ARCH_CONVERT) - == XFS_DA_NODE_MAGIC) { + if (be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC) { error = xfs_attr_node_inactive(trans, dp, child_bp, level+1); - } else if (INT_GET(info->magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC) { + } else if (be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC) { error = xfs_attr_leaf_inactive(trans, dp, child_bp); } else { @@ -2962,7 +2869,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, &bp, XFS_ATTR_FORK); if (error) return(error); - child_fsb = INT_GET(node->btree[i+1].before, ARCH_CONVERT); + child_fsb = be32_to_cpu(node->btree[i+1].before); xfs_da_brelse(*trans, bp); } /* @@ -2991,17 +2898,16 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) int error, count, size, tmp, i; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC); /* * Count the number of "remote" value extents. */ count = 0; entry = &leaf->entries[0]; - for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); entry++, i++) { - if ( INT_GET(entry->nameidx, ARCH_CONVERT) - && ((entry->flags & XFS_ATTR_LOCAL) == 0)) { + for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { + if (be16_to_cpu(entry->nameidx) && + ((entry->flags & XFS_ATTR_LOCAL) == 0)) { name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i); if (name_rmt->valueblk) count++; @@ -3027,17 +2933,14 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) */ lp = list; entry = &leaf->entries[0]; - for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); entry++, i++) { - if ( INT_GET(entry->nameidx, ARCH_CONVERT) - && ((entry->flags & XFS_ATTR_LOCAL) == 0)) { + for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { + if (be16_to_cpu(entry->nameidx) && + ((entry->flags & XFS_ATTR_LOCAL) == 0)) { name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i); if (name_rmt->valueblk) { - /* both on-disk, don't endian flip twice */ - lp->valueblk = name_rmt->valueblk; - INT_SET(lp->valuelen, ARCH_CONVERT, - XFS_B_TO_FSB(dp->i_mount, - INT_GET(name_rmt->valuelen, - ARCH_CONVERT))); + lp->valueblk = be32_to_cpu(name_rmt->valueblk); + lp->valuelen = XFS_B_TO_FSB(dp->i_mount, + be32_to_cpu(name_rmt->valuelen)); lp++; } } @@ -3050,10 +2953,8 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) error = 0; for (lp = list, i = 0; i < count; i++, lp++) { tmp = xfs_attr_leaf_freextent(trans, dp, - INT_GET(lp->valueblk, - ARCH_CONVERT), - INT_GET(lp->valuelen, - ARCH_CONVERT)); + lp->valueblk, lp->valuelen); + if (error == 0) error = tmp; /* save only the 1st errno */ } diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index 541e34109bb9..51c3ee156b2f 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h @@ -73,39 +73,39 @@ struct xfs_trans; #define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */ typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */ - __uint16_t base; /* base of free region */ - __uint16_t size; /* length of free region */ + __be16 base; /* base of free region */ + __be16 size; /* length of free region */ } xfs_attr_leaf_map_t; typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */ xfs_da_blkinfo_t info; /* block type, links, etc. */ - __uint16_t count; /* count of active leaf_entry's */ - __uint16_t usedbytes; /* num bytes of names/values stored */ - __uint16_t firstused; /* first used byte in name area */ - __uint8_t holes; /* != 0 if blk needs compaction */ - __uint8_t pad1; + __be16 count; /* count of active leaf_entry's */ + __be16 usedbytes; /* num bytes of names/values stored */ + __be16 firstused; /* first used byte in name area */ + __u8 holes; /* != 0 if blk needs compaction */ + __u8 pad1; xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE]; /* N largest free regions */ } xfs_attr_leaf_hdr_t; typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */ - xfs_dahash_t hashval; /* hash value of name */ - __uint16_t nameidx; /* index into buffer of name/value */ - __uint8_t flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ - __uint8_t pad2; /* unused pad byte */ + __be32 hashval; /* hash value of name */ + __be16 nameidx; /* index into buffer of name/value */ + __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ + __u8 pad2; /* unused pad byte */ } xfs_attr_leaf_entry_t; typedef struct xfs_attr_leaf_name_local { - __uint16_t valuelen; /* number of bytes in value */ - __uint8_t namelen; /* length of name bytes */ - __uint8_t nameval[1]; /* name/value bytes */ + __be16 valuelen; /* number of bytes in value */ + __u8 namelen; /* length of name bytes */ + __u8 nameval[1]; /* name/value bytes */ } xfs_attr_leaf_name_local_t; typedef struct xfs_attr_leaf_name_remote { - xfs_dablk_t valueblk; /* block number of value bytes */ - __uint32_t valuelen; /* number of bytes in value */ - __uint8_t namelen; /* length of name bytes */ - __uint8_t name[1]; /* name bytes */ + __be32 valueblk; /* block number of value bytes */ + __be32 valuelen; /* number of bytes in value */ + __u8 namelen; /* length of name bytes */ + __u8 name[1]; /* name bytes */ } xfs_attr_leaf_name_remote_t; typedef struct xfs_attr_leafblock { @@ -143,8 +143,8 @@ typedef struct xfs_attr_leafblock { static inline xfs_attr_leaf_name_remote_t * xfs_attr_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx) { - return (xfs_attr_leaf_name_remote_t *) &((char *) - (leafp))[INT_GET((leafp)->entries[idx].nameidx, ARCH_CONVERT)]; + return (xfs_attr_leaf_name_remote_t *) + &((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)]; } #define XFS_ATTR_LEAF_NAME_LOCAL(leafp,idx) \ @@ -152,16 +152,15 @@ xfs_attr_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx) static inline xfs_attr_leaf_name_local_t * xfs_attr_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx) { - return (xfs_attr_leaf_name_local_t *) &((char *) - (leafp))[INT_GET((leafp)->entries[idx].nameidx, ARCH_CONVERT)]; + return (xfs_attr_leaf_name_local_t *) + &((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)]; } #define XFS_ATTR_LEAF_NAME(leafp,idx) \ xfs_attr_leaf_name(leafp,idx) static inline char *xfs_attr_leaf_name(xfs_attr_leafblock_t *leafp, int idx) { - return (&((char *) - (leafp))[INT_GET((leafp)->entries[idx].nameidx, ARCH_CONVERT)]); + return &((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)]; } /* diff --git a/fs/xfs/xfs_attr_sf.h b/fs/xfs/xfs_attr_sf.h index ffed6ca81a52..f67f917803b1 100644 --- a/fs/xfs/xfs_attr_sf.h +++ b/fs/xfs/xfs_attr_sf.h @@ -32,8 +32,8 @@ struct xfs_inode; */ typedef struct xfs_attr_shortform { struct xfs_attr_sf_hdr { /* constant-structure header block */ - __uint16_t totsize; /* total bytes in shortform list */ - __uint8_t count; /* count of active entries */ + __be16 totsize; /* total bytes in shortform list */ + __u8 count; /* count of active entries */ } hdr; struct xfs_attr_sf_entry { __uint8_t namelen; /* actual length of name (no NULL) */ @@ -66,8 +66,8 @@ typedef struct xfs_attr_sf_sort { #define XFS_ATTR_SF_NEXTENTRY(sfep) /* next entry in struct */ \ ((xfs_attr_sf_entry_t *)((char *)(sfep) + XFS_ATTR_SF_ENTSIZE(sfep))) #define XFS_ATTR_SF_TOTSIZE(dp) /* total space in use */ \ - (INT_GET(((xfs_attr_shortform_t *) \ - ((dp)->i_afp->if_u1.if_data))->hdr.totsize, ARCH_CONVERT)) + (be16_to_cpu(((xfs_attr_shortform_t *) \ + ((dp)->i_afp->if_u1.if_data))->hdr.totsize)) #if defined(XFS_ATTR_TRACE) /* diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 70625e577c70..2d702e4a74a3 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -89,7 +89,7 @@ xfs_bmap_add_attrfork_local( int *flags); /* inode logging flags */ /* - * Called by xfs_bmapi to update extent list structure and the btree + * Called by xfs_bmapi to update file extent records and the btree * after allocating space (or doing a delayed allocation). */ STATIC int /* error */ @@ -97,7 +97,7 @@ xfs_bmap_add_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ @@ -113,7 +113,7 @@ xfs_bmap_add_extent_delay_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ @@ -129,7 +129,7 @@ xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t *cur, /* if null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp,/* inode logging flags */ int rsvd); /* OK to allocate reserved blocks */ @@ -142,7 +142,7 @@ xfs_bmap_add_extent_hole_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t *cur, /* if null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ int whichfork); /* data or attr fork */ @@ -155,7 +155,7 @@ xfs_bmap_add_extent_unwritten_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp); /* inode logging flags */ /* @@ -169,7 +169,7 @@ xfs_bmap_alloc( /* * Transform a btree format file with only one leaf node, where the * extents list will fit in the inode, into an extents format file. - * Since the extent list is already in-core, all we have to do is + * Since the file extents are already in-core, all we have to do is * give up the space for the btree root and pitch the leaf block. */ STATIC int /* error */ @@ -191,7 +191,7 @@ xfs_bmap_check_extents( #endif /* - * Called by xfs_bmapi to update extent list structure and the btree + * Called by xfs_bmapi to update file extent records and the btree * after removing space (or undoing a delayed allocation). */ STATIC int /* error */ @@ -201,7 +201,7 @@ xfs_bmap_del_extent( xfs_extnum_t idx, /* extent number to update/insert */ xfs_bmap_free_t *flist, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp,/* inode logging flags */ int whichfork, /* data or attr fork */ int rsvd); /* OK to allocate reserved blocks */ @@ -217,18 +217,6 @@ xfs_bmap_del_free( xfs_bmap_free_item_t *free); /* list item to be freed */ /* - * Remove count entries from the extents array for inode "ip", starting - * at index "idx". Copies the remaining items down over the deleted ones, - * and gives back the excess memory. - */ -STATIC void -xfs_bmap_delete_exlist( - xfs_inode_t *ip, /* incode inode pointer */ - xfs_extnum_t idx, /* starting delete index */ - xfs_extnum_t count, /* count of items to delete */ - int whichfork); /* data or attr fork */ - -/* * Convert an extents-format file into a btree-format file. * The new file will have a root block (in the inode) and a single child block. */ @@ -244,18 +232,6 @@ xfs_bmap_extents_to_btree( int whichfork); /* data or attr fork */ /* - * Insert new item(s) in the extent list for inode "ip". - * Count new items are inserted at offset idx. - */ -STATIC void -xfs_bmap_insert_exlist( - xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t idx, /* starting index of new items */ - xfs_extnum_t count, /* number of inserted items */ - xfs_bmbt_irec_t *new, /* items to insert */ - int whichfork); /* data or attr fork */ - -/* * Convert a local file to an extents file. * This code is sort of bogus, since the file data needs to get * logged so it won't be lost. The bmap-level manipulations are ok, though. @@ -316,7 +292,7 @@ xfs_bmap_trace_addentry( int whichfork); /* data or attr fork */ /* - * Add bmap trace entry prior to a call to xfs_bmap_delete_exlist. + * Add bmap trace entry prior to a call to xfs_iext_remove. */ STATIC void xfs_bmap_trace_delete( @@ -328,7 +304,7 @@ xfs_bmap_trace_delete( int whichfork); /* data or attr fork */ /* - * Add bmap trace entry prior to a call to xfs_bmap_insert_exlist, or + * Add bmap trace entry prior to a call to xfs_iext_insert, or * reading in the extents list from the disk (in the btree). */ STATIC void @@ -343,7 +319,7 @@ xfs_bmap_trace_insert( int whichfork); /* data or attr fork */ /* - * Add bmap trace entry after updating an extent list entry in place. + * Add bmap trace entry after updating an extent record in place. */ STATIC void xfs_bmap_trace_post_update( @@ -354,7 +330,7 @@ xfs_bmap_trace_post_update( int whichfork); /* data or attr fork */ /* - * Add bmap trace entry prior to updating an extent list entry in place. + * Add bmap trace entry prior to updating an extent record in place. */ STATIC void xfs_bmap_trace_pre_update( @@ -413,19 +389,24 @@ STATIC int xfs_bmap_count_tree( xfs_mount_t *mp, xfs_trans_t *tp, + xfs_ifork_t *ifp, xfs_fsblock_t blockno, int levelin, int *count); STATIC int xfs_bmap_count_leaves( - xfs_bmbt_rec_t *frp, + xfs_ifork_t *ifp, + xfs_extnum_t idx, int numrecs, int *count); STATIC int xfs_bmap_disk_count_leaves( - xfs_bmbt_rec_t *frp, + xfs_ifork_t *ifp, + xfs_mount_t *mp, + xfs_extnum_t idx, + xfs_bmbt_block_t *block, int numrecs, int *count); @@ -537,7 +518,7 @@ xfs_bmap_add_attrfork_local( } /* - * Called by xfs_bmapi to update extent list structure and the btree + * Called by xfs_bmapi to update file extent records and the btree * after allocating space (or doing a delayed allocation). */ STATIC int /* error */ @@ -545,7 +526,7 @@ xfs_bmap_add_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ @@ -578,7 +559,7 @@ xfs_bmap_add_extent( if (nextents == 0) { xfs_bmap_trace_insert(fname, "insert empty", ip, 0, 1, new, NULL, whichfork); - xfs_bmap_insert_exlist(ip, 0, 1, new, whichfork); + xfs_iext_insert(ifp, 0, 1, new); ASSERT(cur == NULL); ifp->if_lastex = 0; if (!ISNULLSTARTBLOCK(new->br_startblock)) { @@ -614,7 +595,7 @@ xfs_bmap_add_extent( /* * Get the record referred to by idx. */ - xfs_bmbt_get_all(&ifp->if_u1.if_extents[idx], &prev); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &prev); /* * If it's a real allocation record, and the new allocation ends * after the start of the referred to record, then we're filling @@ -714,14 +695,13 @@ xfs_bmap_add_extent_delay_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ int rsvd) /* OK to use reserved data block allocation */ { - xfs_bmbt_rec_t *base; /* base of extent entry list */ xfs_btree_cur_t *cur; /* btree cursor */ int diff; /* temp value */ xfs_bmbt_rec_t *ep; /* extent entry for idx */ @@ -730,6 +710,7 @@ xfs_bmap_add_extent_delay_real( static char fname[] = "xfs_bmap_add_extent_delay_real"; #endif int i; /* temp state */ + xfs_ifork_t *ifp; /* inode fork pointer */ xfs_fileoff_t new_endoff; /* end offset of new entry */ xfs_bmbt_irec_t r[3]; /* neighbor extent entries */ /* left is 0, right is 1, prev is 2 */ @@ -763,8 +744,8 @@ xfs_bmap_add_extent_delay_real( * Set up a bunch of variables to make the tests simpler. */ cur = *curp; - base = ip->i_df.if_u1.if_extents; - ep = &base[idx]; + ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_get_all(ep, &PREV); new_endoff = new->br_startoff + new->br_blockcount; ASSERT(PREV.br_startoff <= new->br_startoff); @@ -781,7 +762,7 @@ xfs_bmap_add_extent_delay_real( * Don't set contiguous if the combined extent would be too large. */ if (STATE_SET_TEST(LEFT_VALID, idx > 0)) { - xfs_bmbt_get_all(ep - 1, &LEFT); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT); STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock)); } STATE_SET(LEFT_CONTIG, @@ -798,7 +779,7 @@ xfs_bmap_add_extent_delay_real( if (STATE_SET_TEST(RIGHT_VALID, idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) { - xfs_bmbt_get_all(ep + 1, &RIGHT); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT); STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock)); } STATE_SET(RIGHT_CONTIG, @@ -825,14 +806,14 @@ xfs_bmap_add_extent_delay_real( */ xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1, XFS_DATA_FORK); - xfs_bmbt_set_blockcount(ep - 1, + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount); xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1, XFS_DATA_FORK); xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK); - xfs_bmap_delete_exlist(ip, idx, 2, XFS_DATA_FORK); + xfs_iext_remove(ifp, idx, 2); ip->i_df.if_lastex = idx - 1; ip->i_d.di_nextents--; if (cur == NULL) @@ -867,14 +848,14 @@ xfs_bmap_add_extent_delay_real( */ xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1, XFS_DATA_FORK); - xfs_bmbt_set_blockcount(ep - 1, + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount); xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1, XFS_DATA_FORK); ip->i_df.if_lastex = idx - 1; xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1, XFS_DATA_FORK); - xfs_bmap_delete_exlist(ip, idx, 1, XFS_DATA_FORK); + xfs_iext_remove(ifp, idx, 1); if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -908,7 +889,7 @@ xfs_bmap_add_extent_delay_real( ip->i_df.if_lastex = idx; xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK); - xfs_bmap_delete_exlist(ip, idx + 1, 1, XFS_DATA_FORK); + xfs_iext_remove(ifp, idx + 1, 1); if (cur == NULL) rval = XFS_ILOG_DEXT; else { @@ -964,7 +945,7 @@ xfs_bmap_add_extent_delay_real( */ xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1, XFS_DATA_FORK); - xfs_bmbt_set_blockcount(ep - 1, + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + new->br_blockcount); xfs_bmbt_set_startoff(ep, PREV.br_startoff + new->br_blockcount); @@ -1010,7 +991,7 @@ xfs_bmap_add_extent_delay_real( xfs_bmbt_set_blockcount(ep, temp); xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL, XFS_DATA_FORK); - xfs_bmap_insert_exlist(ip, idx, 1, new, XFS_DATA_FORK); + xfs_iext_insert(ifp, idx, 1, new); ip->i_df.if_lastex = idx; ip->i_d.di_nextents++; if (cur == NULL) @@ -1039,8 +1020,7 @@ xfs_bmap_add_extent_delay_real( temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), STARTBLOCKVAL(PREV.br_startblock) - (cur ? cur->bc_private.b.allocated : 0)); - base = ip->i_df.if_u1.if_extents; - ep = &base[idx + 1]; + ep = xfs_iext_get_ext(ifp, idx + 1); xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp)); xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1, XFS_DATA_FORK); @@ -1058,7 +1038,8 @@ xfs_bmap_add_extent_delay_real( xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1, XFS_DATA_FORK); xfs_bmbt_set_blockcount(ep, temp); - xfs_bmbt_set_allf(ep + 1, new->br_startoff, new->br_startblock, + xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1), + new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, RIGHT.br_state); xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1, @@ -1098,7 +1079,7 @@ xfs_bmap_add_extent_delay_real( xfs_bmbt_set_blockcount(ep, temp); xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1, new, NULL, XFS_DATA_FORK); - xfs_bmap_insert_exlist(ip, idx + 1, 1, new, XFS_DATA_FORK); + xfs_iext_insert(ifp, idx + 1, 1, new); ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents++; if (cur == NULL) @@ -1127,8 +1108,7 @@ xfs_bmap_add_extent_delay_real( temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), STARTBLOCKVAL(PREV.br_startblock) - (cur ? cur->bc_private.b.allocated : 0)); - base = ip->i_df.if_u1.if_extents; - ep = &base[idx]; + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp)); xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK); *dnew = temp; @@ -1149,7 +1129,7 @@ xfs_bmap_add_extent_delay_real( r[1].br_blockcount = temp2; xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1], XFS_DATA_FORK); - xfs_bmap_insert_exlist(ip, idx + 1, 2, &r[0], XFS_DATA_FORK); + xfs_iext_insert(ifp, idx + 1, 2, &r[0]); ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents++; if (cur == NULL) @@ -1204,13 +1184,13 @@ xfs_bmap_add_extent_delay_real( } } } - base = ip->i_df.if_u1.if_extents; - ep = &base[idx]; + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp)); xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK); xfs_bmap_trace_pre_update(fname, "0", ip, idx + 2, XFS_DATA_FORK); - xfs_bmbt_set_startblock(ep + 2, NULLSTARTBLOCK((int)temp2)); + xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2), + NULLSTARTBLOCK((int)temp2)); xfs_bmap_trace_post_update(fname, "0", ip, idx + 2, XFS_DATA_FORK); *dnew = temp + temp2; @@ -1254,10 +1234,9 @@ xfs_bmap_add_extent_unwritten_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp) /* inode logging flags */ { - xfs_bmbt_rec_t *base; /* base of extent entry list */ xfs_btree_cur_t *cur; /* btree cursor */ xfs_bmbt_rec_t *ep; /* extent entry for idx */ int error; /* error return value */ @@ -1265,6 +1244,7 @@ xfs_bmap_add_extent_unwritten_real( static char fname[] = "xfs_bmap_add_extent_unwritten_real"; #endif int i; /* temp state */ + xfs_ifork_t *ifp; /* inode fork pointer */ xfs_fileoff_t new_endoff; /* end offset of new entry */ xfs_exntst_t newext; /* new extent state */ xfs_exntst_t oldext; /* old extent state */ @@ -1298,8 +1278,8 @@ xfs_bmap_add_extent_unwritten_real( */ error = 0; cur = *curp; - base = ip->i_df.if_u1.if_extents; - ep = &base[idx]; + ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_get_all(ep, &PREV); newext = new->br_state; oldext = (newext == XFS_EXT_UNWRITTEN) ? @@ -1320,7 +1300,7 @@ xfs_bmap_add_extent_unwritten_real( * Don't set contiguous if the combined extent would be too large. */ if (STATE_SET_TEST(LEFT_VALID, idx > 0)) { - xfs_bmbt_get_all(ep - 1, &LEFT); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT); STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock)); } STATE_SET(LEFT_CONTIG, @@ -1337,7 +1317,7 @@ xfs_bmap_add_extent_unwritten_real( if (STATE_SET_TEST(RIGHT_VALID, idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) { - xfs_bmbt_get_all(ep + 1, &RIGHT); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT); STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock)); } STATE_SET(RIGHT_CONTIG, @@ -1363,14 +1343,14 @@ xfs_bmap_add_extent_unwritten_real( */ xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1, XFS_DATA_FORK); - xfs_bmbt_set_blockcount(ep - 1, + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount + RIGHT.br_blockcount); xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1, XFS_DATA_FORK); xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK); - xfs_bmap_delete_exlist(ip, idx, 2, XFS_DATA_FORK); + xfs_iext_remove(ifp, idx, 2); ip->i_df.if_lastex = idx - 1; ip->i_d.di_nextents -= 2; if (cur == NULL) @@ -1409,14 +1389,14 @@ xfs_bmap_add_extent_unwritten_real( */ xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1, XFS_DATA_FORK); - xfs_bmbt_set_blockcount(ep - 1, + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + PREV.br_blockcount); xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1, XFS_DATA_FORK); ip->i_df.if_lastex = idx - 1; xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1, XFS_DATA_FORK); - xfs_bmap_delete_exlist(ip, idx, 1, XFS_DATA_FORK); + xfs_iext_remove(ifp, idx, 1); ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1456,7 +1436,7 @@ xfs_bmap_add_extent_unwritten_real( ip->i_df.if_lastex = idx; xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK); - xfs_bmap_delete_exlist(ip, idx + 1, 1, XFS_DATA_FORK); + xfs_iext_remove(ifp, idx + 1, 1); ip->i_d.di_nextents--; if (cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1516,7 +1496,7 @@ xfs_bmap_add_extent_unwritten_real( */ xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1, XFS_DATA_FORK); - xfs_bmbt_set_blockcount(ep - 1, + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), LEFT.br_blockcount + new->br_blockcount); xfs_bmbt_set_startoff(ep, PREV.br_startoff + new->br_blockcount); @@ -1571,7 +1551,7 @@ xfs_bmap_add_extent_unwritten_real( xfs_bmap_trace_post_update(fname, "LF", ip, idx, XFS_DATA_FORK); xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL, XFS_DATA_FORK); - xfs_bmap_insert_exlist(ip, idx, 1, new, XFS_DATA_FORK); + xfs_iext_insert(ifp, idx, 1, new); ip->i_df.if_lastex = idx; ip->i_d.di_nextents++; if (cur == NULL) @@ -1609,7 +1589,8 @@ xfs_bmap_add_extent_unwritten_real( PREV.br_blockcount - new->br_blockcount); xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx, XFS_DATA_FORK); - xfs_bmbt_set_allf(ep + 1, new->br_startoff, new->br_startblock, + xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1), + new->br_startoff, new->br_startblock, new->br_blockcount + RIGHT.br_blockcount, newext); xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1, XFS_DATA_FORK); @@ -1649,7 +1630,7 @@ xfs_bmap_add_extent_unwritten_real( xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK); xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1, new, NULL, XFS_DATA_FORK); - xfs_bmap_insert_exlist(ip, idx + 1, 1, new, XFS_DATA_FORK); + xfs_iext_insert(ifp, idx + 1, 1, new); ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents++; if (cur == NULL) @@ -1696,7 +1677,7 @@ xfs_bmap_add_extent_unwritten_real( r[1].br_state = oldext; xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1], XFS_DATA_FORK); - xfs_bmap_insert_exlist(ip, idx + 1, 2, &r[0], XFS_DATA_FORK); + xfs_iext_insert(ifp, idx + 1, 2, &r[0]); ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents += 2; if (cur == NULL) @@ -1770,15 +1751,15 @@ xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t *cur, /* if null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ int rsvd) /* OK to allocate reserved blocks */ { - xfs_bmbt_rec_t *base; /* base of extent entry list */ - xfs_bmbt_rec_t *ep; /* extent list entry for idx */ + xfs_bmbt_rec_t *ep; /* extent record for idx */ #ifdef XFS_BMAP_TRACE static char fname[] = "xfs_bmap_add_extent_hole_delay"; #endif + xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_irec_t left; /* left neighbor extent entry */ xfs_filblks_t newlen=0; /* new indirect size */ xfs_filblks_t oldlen=0; /* old indirect size */ @@ -1799,15 +1780,15 @@ xfs_bmap_add_extent_hole_delay( ((state &= ~MASK(b)), 0)) #define SWITCH_STATE (state & MASK2(LEFT_CONTIG, RIGHT_CONTIG)) - base = ip->i_df.if_u1.if_extents; - ep = &base[idx]; + ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + ep = xfs_iext_get_ext(ifp, idx); state = 0; ASSERT(ISNULLSTARTBLOCK(new->br_startblock)); /* * Check and set flags if this segment has a left neighbor */ if (STATE_SET_TEST(LEFT_VALID, idx > 0)) { - xfs_bmbt_get_all(ep - 1, &left); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left); STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(left.br_startblock)); } /* @@ -1844,23 +1825,24 @@ xfs_bmap_add_extent_hole_delay( /* * New allocation is contiguous with delayed allocations * on the left and on the right. - * Merge all three into a single extent list entry. + * Merge all three into a single extent record. */ temp = left.br_blockcount + new->br_blockcount + right.br_blockcount; xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1, XFS_DATA_FORK); - xfs_bmbt_set_blockcount(ep - 1, temp); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp); oldlen = STARTBLOCKVAL(left.br_startblock) + STARTBLOCKVAL(new->br_startblock) + STARTBLOCKVAL(right.br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); - xfs_bmbt_set_startblock(ep - 1, NULLSTARTBLOCK((int)newlen)); + xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1), + NULLSTARTBLOCK((int)newlen)); xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1, XFS_DATA_FORK); xfs_bmap_trace_delete(fname, "LC|RC", ip, idx, 1, XFS_DATA_FORK); - xfs_bmap_delete_exlist(ip, idx, 1, XFS_DATA_FORK); + xfs_iext_remove(ifp, idx, 1); ip->i_df.if_lastex = idx - 1; break; @@ -1873,11 +1855,12 @@ xfs_bmap_add_extent_hole_delay( temp = left.br_blockcount + new->br_blockcount; xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1, XFS_DATA_FORK); - xfs_bmbt_set_blockcount(ep - 1, temp); + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp); oldlen = STARTBLOCKVAL(left.br_startblock) + STARTBLOCKVAL(new->br_startblock); newlen = xfs_bmap_worst_indlen(ip, temp); - xfs_bmbt_set_startblock(ep - 1, NULLSTARTBLOCK((int)newlen)); + xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1), + NULLSTARTBLOCK((int)newlen)); xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, XFS_DATA_FORK); ip->i_df.if_lastex = idx - 1; @@ -1909,7 +1892,7 @@ xfs_bmap_add_extent_hole_delay( oldlen = newlen = 0; xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL, XFS_DATA_FORK); - xfs_bmap_insert_exlist(ip, idx, 1, new, XFS_DATA_FORK); + xfs_iext_insert(ifp, idx, 1, new); ip->i_df.if_lastex = idx; break; } @@ -1940,7 +1923,7 @@ xfs_bmap_add_extent_hole_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t *cur, /* if null, not a btree */ - xfs_bmbt_irec_t *new, /* new data to put in extent list */ + xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ int whichfork) /* data or attr fork */ { @@ -1970,13 +1953,13 @@ xfs_bmap_add_extent_hole_real( ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); - ep = &ifp->if_u1.if_extents[idx]; + ep = xfs_iext_get_ext(ifp, idx); state = 0; /* * Check and set flags if this segment has a left neighbor. */ if (STATE_SET_TEST(LEFT_VALID, idx > 0)) { - xfs_bmbt_get_all(ep - 1, &left); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left); STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(left.br_startblock)); } /* @@ -2019,18 +2002,18 @@ xfs_bmap_add_extent_hole_real( /* * New allocation is contiguous with real allocations on the * left and on the right. - * Merge all three into a single extent list entry. + * Merge all three into a single extent record. */ xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1, whichfork); - xfs_bmbt_set_blockcount(ep - 1, + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), left.br_blockcount + new->br_blockcount + right.br_blockcount); xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1, whichfork); xfs_bmap_trace_delete(fname, "LC|RC", ip, idx, 1, whichfork); - xfs_bmap_delete_exlist(ip, idx, 1, whichfork); + xfs_iext_remove(ifp, idx, 1); ifp->if_lastex = idx - 1; XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) - 1); @@ -2062,7 +2045,7 @@ xfs_bmap_add_extent_hole_real( * Merge the new allocation with the left neighbor. */ xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1, whichfork); - xfs_bmbt_set_blockcount(ep - 1, + xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), left.br_blockcount + new->br_blockcount); xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork); ifp->if_lastex = idx - 1; @@ -2116,7 +2099,7 @@ xfs_bmap_add_extent_hole_real( */ xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL, whichfork); - xfs_bmap_insert_exlist(ip, idx, 1, new, whichfork); + xfs_iext_insert(ifp, idx, 1, new); ifp->if_lastex = idx; XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); @@ -2311,25 +2294,15 @@ xfs_bmap_extsize_align( #define XFS_ALLOC_GAP_UNITS 4 -/* - * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. - * It figures out where to ask the underlying allocator to put the new extent. - */ STATIC int -xfs_bmap_alloc( +xfs_bmap_adjacent( xfs_bmalloca_t *ap) /* bmap alloc argument struct */ { xfs_fsblock_t adjust; /* adjustment to block numbers */ - xfs_alloctype_t atype=0; /* type for allocation routines */ - int error; /* error return value */ xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */ xfs_mount_t *mp; /* mount point structure */ int nullfb; /* true if ap->firstblock isn't set */ int rt; /* true if inode is realtime */ - xfs_extlen_t prod = 0; /* product factor for allocators */ - xfs_extlen_t ralen = 0; /* realtime allocation length */ - xfs_extlen_t align; /* minimum allocation alignment */ - xfs_rtblock_t rtx; #define ISVALID(x,y) \ (rt ? \ @@ -2338,75 +2311,10 @@ xfs_bmap_alloc( XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \ XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) - /* - * Set up variables. - */ mp = ap->ip->i_mount; nullfb = ap->firstblock == NULLFSBLOCK; rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); - if (rt) { - align = ap->ip->i_d.di_extsize ? - ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize; - /* Set prod to match the extent size */ - prod = align / mp->m_sb.sb_rextsize; - - error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, - align, rt, ap->eof, 0, - ap->conv, &ap->off, &ap->alen); - if (error) - return error; - ASSERT(ap->alen); - ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0); - - /* - * If the offset & length are not perfectly aligned - * then kill prod, it will just get us in trouble. - */ - if (do_mod(ap->off, align) || ap->alen % align) - prod = 1; - /* - * Set ralen to be the actual requested length in rtextents. - */ - ralen = ap->alen / mp->m_sb.sb_rextsize; - /* - * If the old value was close enough to MAXEXTLEN that - * we rounded up to it, cut it back so it's valid again. - * Note that if it's a really large request (bigger than - * MAXEXTLEN), we don't hear about that number, and can't - * adjust the starting point to match it. - */ - if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN) - ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; - /* - * If it's an allocation to an empty file at offset 0, - * pick an extent that will space things out in the rt area. - */ - if (ap->eof && ap->off == 0) { - error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); - if (error) - return error; - ap->rval = rtx * mp->m_sb.sb_rextsize; - } else - ap->rval = 0; - } else { - align = (ap->userdata && ap->ip->i_d.di_extsize && - (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ? - ap->ip->i_d.di_extsize : 0; - if (unlikely(align)) { - error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, - align, rt, - ap->eof, 0, ap->conv, - &ap->off, &ap->alen); - ASSERT(!error); - ASSERT(ap->alen); - } - if (nullfb) - ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); - else - ap->rval = ap->firstblock; - } - /* * If allocating at eof, and there's a previous real block, * try to use it's last block as our starting point. @@ -2531,287 +2439,384 @@ xfs_bmap_alloc( else if (gotbno != NULLFSBLOCK) ap->rval = gotbno; } +#undef ISVALID + return 0; +} + +STATIC int +xfs_bmap_rtalloc( + xfs_bmalloca_t *ap) /* bmap alloc argument struct */ +{ + xfs_alloctype_t atype = 0; /* type for allocation routines */ + int error; /* error return value */ + xfs_mount_t *mp; /* mount point structure */ + xfs_extlen_t prod = 0; /* product factor for allocators */ + xfs_extlen_t ralen = 0; /* realtime allocation length */ + xfs_extlen_t align; /* minimum allocation alignment */ + xfs_rtblock_t rtx; /* realtime extent number */ + xfs_rtblock_t rtb; + + mp = ap->ip->i_mount; + align = ap->ip->i_d.di_extsize ? + ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize; + prod = align / mp->m_sb.sb_rextsize; + error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, + align, 1, ap->eof, 0, + ap->conv, &ap->off, &ap->alen); + if (error) + return error; + ASSERT(ap->alen); + ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0); + + /* + * If the offset & length are not perfectly aligned + * then kill prod, it will just get us in trouble. + */ + if (do_mod(ap->off, align) || ap->alen % align) + prod = 1; + /* + * Set ralen to be the actual requested length in rtextents. + */ + ralen = ap->alen / mp->m_sb.sb_rextsize; + /* + * If the old value was close enough to MAXEXTLEN that + * we rounded up to it, cut it back so it's valid again. + * Note that if it's a really large request (bigger than + * MAXEXTLEN), we don't hear about that number, and can't + * adjust the starting point to match it. + */ + if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN) + ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; + /* + * If it's an allocation to an empty file at offset 0, + * pick an extent that will space things out in the rt area. + */ + if (ap->eof && ap->off == 0) { + error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); + if (error) + return error; + ap->rval = rtx * mp->m_sb.sb_rextsize; + } else { + ap->rval = 0; + } + + xfs_bmap_adjacent(ap); + + /* + * Realtime allocation, done through xfs_rtallocate_extent. + */ + atype = ap->rval == 0 ? XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO; + do_div(ap->rval, mp->m_sb.sb_rextsize); + rtb = ap->rval; + ap->alen = ralen; + if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen, + &ralen, atype, ap->wasdel, prod, &rtb))) + return error; + if (rtb == NULLFSBLOCK && prod > 1 && + (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, + ap->alen, &ralen, atype, + ap->wasdel, 1, &rtb))) + return error; + ap->rval = rtb; + if (ap->rval != NULLFSBLOCK) { + ap->rval *= mp->m_sb.sb_rextsize; + ralen *= mp->m_sb.sb_rextsize; + ap->alen = ralen; + ap->ip->i_d.di_nblocks += ralen; + xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); + if (ap->wasdel) + ap->ip->i_delayed_blks -= ralen; + /* + * Adjust the disk quota also. This was reserved + * earlier. + */ + XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip, + ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : + XFS_TRANS_DQ_RTBCOUNT, (long) ralen); + } else { + ap->alen = 0; + } + return 0; +} + +STATIC int +xfs_bmap_btalloc( + xfs_bmalloca_t *ap) /* bmap alloc argument struct */ +{ + xfs_mount_t *mp; /* mount point structure */ + xfs_alloctype_t atype = 0; /* type for allocation routines */ + xfs_extlen_t align; /* minimum allocation alignment */ + xfs_agnumber_t ag; + xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */ + xfs_agnumber_t startag; + xfs_alloc_arg_t args; + xfs_extlen_t blen; + xfs_extlen_t delta; + xfs_extlen_t longest; + xfs_extlen_t need; + xfs_extlen_t nextminlen = 0; + xfs_perag_t *pag; + int nullfb; /* true if ap->firstblock isn't set */ + int isaligned; + int notinit; + int tryagain; + int error; + + mp = ap->ip->i_mount; + align = (ap->userdata && ap->ip->i_d.di_extsize && + (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ? + ap->ip->i_d.di_extsize : 0; + if (unlikely(align)) { + error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, + align, 0, ap->eof, 0, ap->conv, + &ap->off, &ap->alen); + ASSERT(!error); + ASSERT(ap->alen); + } + nullfb = ap->firstblock == NULLFSBLOCK; + fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); + if (nullfb) + ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); + else + ap->rval = ap->firstblock; + + xfs_bmap_adjacent(ap); + /* * If allowed, use ap->rval; otherwise must use firstblock since * it's in the right allocation group. */ - if (nullfb || rt || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno) + if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno) ; else ap->rval = ap->firstblock; /* - * Realtime allocation, done through xfs_rtallocate_extent. + * Normal allocation, done through xfs_alloc_vextent. */ - if (rt) { -#ifndef __KERNEL__ - ASSERT(0); -#else - xfs_rtblock_t rtb; - - atype = ap->rval == 0 ? - XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO; - do_div(ap->rval, mp->m_sb.sb_rextsize); - rtb = ap->rval; - ap->alen = ralen; - if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen, - &ralen, atype, ap->wasdel, prod, &rtb))) - return error; - if (rtb == NULLFSBLOCK && prod > 1 && - (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, - ap->alen, &ralen, atype, - ap->wasdel, 1, &rtb))) - return error; - ap->rval = rtb; - if (ap->rval != NULLFSBLOCK) { - ap->rval *= mp->m_sb.sb_rextsize; - ralen *= mp->m_sb.sb_rextsize; - ap->alen = ralen; - ap->ip->i_d.di_nblocks += ralen; - xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); - if (ap->wasdel) - ap->ip->i_delayed_blks -= ralen; + tryagain = isaligned = 0; + args.tp = ap->tp; + args.mp = mp; + args.fsbno = ap->rval; + args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); + blen = 0; + if (nullfb) { + args.type = XFS_ALLOCTYPE_START_BNO; + args.total = ap->total; + /* + * Find the longest available space. + * We're going to try for the whole allocation at once. + */ + startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno); + notinit = 0; + down_read(&mp->m_peraglock); + while (blen < ap->alen) { + pag = &mp->m_perag[ag]; + if (!pag->pagf_init && + (error = xfs_alloc_pagf_init(mp, args.tp, + ag, XFS_ALLOC_FLAG_TRYLOCK))) { + up_read(&mp->m_peraglock); + return error; + } /* - * Adjust the disk quota also. This was reserved - * earlier. + * See xfs_alloc_fix_freelist... */ - XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip, - ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : - XFS_TRANS_DQ_RTBCOUNT, - (long) ralen); - } else - ap->alen = 0; -#endif /* __KERNEL__ */ + if (pag->pagf_init) { + need = XFS_MIN_FREELIST_PAG(pag, mp); + delta = need > pag->pagf_flcount ? + need - pag->pagf_flcount : 0; + longest = (pag->pagf_longest > delta) ? + (pag->pagf_longest - delta) : + (pag->pagf_flcount > 0 || + pag->pagf_longest > 0); + if (blen < longest) + blen = longest; + } else + notinit = 1; + if (++ag == mp->m_sb.sb_agcount) + ag = 0; + if (ag == startag) + break; + } + up_read(&mp->m_peraglock); + /* + * Since the above loop did a BUF_TRYLOCK, it is + * possible that there is space for this request. + */ + if (notinit || blen < ap->minlen) + args.minlen = ap->minlen; + /* + * If the best seen length is less than the request + * length, use the best as the minimum. + */ + else if (blen < ap->alen) + args.minlen = blen; + /* + * Otherwise we've seen an extent as big as alen, + * use that as the minimum. + */ + else + args.minlen = ap->alen; + } else if (ap->low) { + args.type = XFS_ALLOCTYPE_FIRST_AG; + args.total = args.minlen = ap->minlen; + } else { + args.type = XFS_ALLOCTYPE_NEAR_BNO; + args.total = ap->total; + args.minlen = ap->minlen; + } + if (unlikely(ap->userdata && ap->ip->i_d.di_extsize && + (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) { + args.prod = ap->ip->i_d.di_extsize; + if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) + args.mod = (xfs_extlen_t)(args.prod - args.mod); + } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) { + args.prod = 1; + args.mod = 0; + } else { + args.prod = NBPP >> mp->m_sb.sb_blocklog; + if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod)))) + args.mod = (xfs_extlen_t)(args.prod - args.mod); } /* - * Normal allocation, done through xfs_alloc_vextent. + * If we are not low on available data blocks, and the + * underlying logical volume manager is a stripe, and + * the file offset is zero then try to allocate data + * blocks on stripe unit boundary. + * NOTE: ap->aeof is only set if the allocation length + * is >= the stripe unit and the allocation offset is + * at the end of file. */ - else { - xfs_agnumber_t ag; - xfs_alloc_arg_t args; - xfs_extlen_t blen; - xfs_extlen_t delta; - int isaligned; - xfs_extlen_t longest; - xfs_extlen_t need; - xfs_extlen_t nextminlen=0; - int notinit; - xfs_perag_t *pag; - xfs_agnumber_t startag; - int tryagain; - - tryagain = isaligned = 0; - args.tp = ap->tp; - args.mp = mp; - args.fsbno = ap->rval; - args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); - blen = 0; - if (nullfb) { - args.type = XFS_ALLOCTYPE_START_BNO; - args.total = ap->total; - /* - * Find the longest available space. - * We're going to try for the whole allocation at once. - */ - startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno); - notinit = 0; - down_read(&mp->m_peraglock); - while (blen < ap->alen) { - pag = &mp->m_perag[ag]; - if (!pag->pagf_init && - (error = xfs_alloc_pagf_init(mp, args.tp, - ag, XFS_ALLOC_FLAG_TRYLOCK))) { - up_read(&mp->m_peraglock); - return error; - } - /* - * See xfs_alloc_fix_freelist... - */ - if (pag->pagf_init) { - need = XFS_MIN_FREELIST_PAG(pag, mp); - delta = need > pag->pagf_flcount ? - need - pag->pagf_flcount : 0; - longest = (pag->pagf_longest > delta) ? - (pag->pagf_longest - delta) : - (pag->pagf_flcount > 0 || - pag->pagf_longest > 0); - if (blen < longest) - blen = longest; - } else - notinit = 1; - if (++ag == mp->m_sb.sb_agcount) - ag = 0; - if (ag == startag) - break; - } - up_read(&mp->m_peraglock); + if (!ap->low && ap->aeof) { + if (!ap->off) { + args.alignment = mp->m_dalign; + atype = args.type; + isaligned = 1; /* - * Since the above loop did a BUF_TRYLOCK, it is - * possible that there is space for this request. + * Adjust for alignment */ - if (notinit || blen < ap->minlen) - args.minlen = ap->minlen; + if (blen > args.alignment && blen <= ap->alen) + args.minlen = blen - args.alignment; + args.minalignslop = 0; + } else { /* - * If the best seen length is less than the request - * length, use the best as the minimum. + * First try an exact bno allocation. + * If it fails then do a near or start bno + * allocation with alignment turned on. */ - else if (blen < ap->alen) - args.minlen = blen; + atype = args.type; + tryagain = 1; + args.type = XFS_ALLOCTYPE_THIS_BNO; + args.alignment = 1; /* - * Otherwise we've seen an extent as big as alen, - * use that as the minimum. + * Compute the minlen+alignment for the + * next case. Set slop so that the value + * of minlen+alignment+slop doesn't go up + * between the calls. */ + if (blen > mp->m_dalign && blen <= ap->alen) + nextminlen = blen - mp->m_dalign; else - args.minlen = ap->alen; - } else if (ap->low) { - args.type = XFS_ALLOCTYPE_FIRST_AG; - args.total = args.minlen = ap->minlen; - } else { - args.type = XFS_ALLOCTYPE_NEAR_BNO; - args.total = ap->total; - args.minlen = ap->minlen; - } - if (unlikely(ap->userdata && ap->ip->i_d.di_extsize && - (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) { - args.prod = ap->ip->i_d.di_extsize; - if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) - args.mod = (xfs_extlen_t)(args.prod - args.mod); - } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) { - args.prod = 1; - args.mod = 0; - } else { - args.prod = NBPP >> mp->m_sb.sb_blocklog; - if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod)))) - args.mod = (xfs_extlen_t)(args.prod - args.mod); + nextminlen = args.minlen; + if (nextminlen + mp->m_dalign > args.minlen + 1) + args.minalignslop = + nextminlen + mp->m_dalign - + args.minlen - 1; + else + args.minalignslop = 0; } + } else { + args.alignment = 1; + args.minalignslop = 0; + } + args.minleft = ap->minleft; + args.wasdel = ap->wasdel; + args.isfl = 0; + args.userdata = ap->userdata; + if ((error = xfs_alloc_vextent(&args))) + return error; + if (tryagain && args.fsbno == NULLFSBLOCK) { /* - * If we are not low on available data blocks, and the - * underlying logical volume manager is a stripe, and - * the file offset is zero then try to allocate data - * blocks on stripe unit boundary. - * NOTE: ap->aeof is only set if the allocation length - * is >= the stripe unit and the allocation offset is - * at the end of file. + * Exact allocation failed. Now try with alignment + * turned on. */ - if (!ap->low && ap->aeof) { - if (!ap->off) { - args.alignment = mp->m_dalign; - atype = args.type; - isaligned = 1; - /* - * Adjust for alignment - */ - if (blen > args.alignment && blen <= ap->alen) - args.minlen = blen - args.alignment; - args.minalignslop = 0; - } else { - /* - * First try an exact bno allocation. - * If it fails then do a near or start bno - * allocation with alignment turned on. - */ - atype = args.type; - tryagain = 1; - args.type = XFS_ALLOCTYPE_THIS_BNO; - args.alignment = 1; - /* - * Compute the minlen+alignment for the - * next case. Set slop so that the value - * of minlen+alignment+slop doesn't go up - * between the calls. - */ - if (blen > mp->m_dalign && blen <= ap->alen) - nextminlen = blen - mp->m_dalign; - else - nextminlen = args.minlen; - if (nextminlen + mp->m_dalign > args.minlen + 1) - args.minalignslop = - nextminlen + mp->m_dalign - - args.minlen - 1; - else - args.minalignslop = 0; - } - } else { - args.alignment = 1; - args.minalignslop = 0; - } - args.minleft = ap->minleft; - args.wasdel = ap->wasdel; - args.isfl = 0; - args.userdata = ap->userdata; + args.type = atype; + args.fsbno = ap->rval; + args.alignment = mp->m_dalign; + args.minlen = nextminlen; + args.minalignslop = 0; + isaligned = 1; + if ((error = xfs_alloc_vextent(&args))) + return error; + } + if (isaligned && args.fsbno == NULLFSBLOCK) { + /* + * allocation failed, so turn off alignment and + * try again. + */ + args.type = atype; + args.fsbno = ap->rval; + args.alignment = 0; + if ((error = xfs_alloc_vextent(&args))) + return error; + } + if (args.fsbno == NULLFSBLOCK && nullfb && + args.minlen > ap->minlen) { + args.minlen = ap->minlen; + args.type = XFS_ALLOCTYPE_START_BNO; + args.fsbno = ap->rval; if ((error = xfs_alloc_vextent(&args))) return error; - if (tryagain && args.fsbno == NULLFSBLOCK) { - /* - * Exact allocation failed. Now try with alignment - * turned on. - */ - args.type = atype; - args.fsbno = ap->rval; - args.alignment = mp->m_dalign; - args.minlen = nextminlen; - args.minalignslop = 0; - isaligned = 1; - if ((error = xfs_alloc_vextent(&args))) - return error; - } - if (isaligned && args.fsbno == NULLFSBLOCK) { - /* - * allocation failed, so turn off alignment and - * try again. - */ - args.type = atype; - args.fsbno = ap->rval; - args.alignment = 0; - if ((error = xfs_alloc_vextent(&args))) - return error; - } - if (args.fsbno == NULLFSBLOCK && nullfb && - args.minlen > ap->minlen) { - args.minlen = ap->minlen; - args.type = XFS_ALLOCTYPE_START_BNO; - args.fsbno = ap->rval; - if ((error = xfs_alloc_vextent(&args))) - return error; - } - if (args.fsbno == NULLFSBLOCK && nullfb) { - args.fsbno = 0; - args.type = XFS_ALLOCTYPE_FIRST_AG; - args.total = ap->minlen; - args.minleft = 0; - if ((error = xfs_alloc_vextent(&args))) - return error; - ap->low = 1; - } - if (args.fsbno != NULLFSBLOCK) { - ap->firstblock = ap->rval = args.fsbno; - ASSERT(nullfb || fb_agno == args.agno || - (ap->low && fb_agno < args.agno)); - ap->alen = args.len; - ap->ip->i_d.di_nblocks += args.len; - xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); - if (ap->wasdel) - ap->ip->i_delayed_blks -= args.len; - /* - * Adjust the disk quota also. This was reserved - * earlier. - */ - XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip, - ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT : - XFS_TRANS_DQ_BCOUNT, - (long) args.len); - } else { - ap->rval = NULLFSBLOCK; - ap->alen = 0; - } + } + if (args.fsbno == NULLFSBLOCK && nullfb) { + args.fsbno = 0; + args.type = XFS_ALLOCTYPE_FIRST_AG; + args.total = ap->minlen; + args.minleft = 0; + if ((error = xfs_alloc_vextent(&args))) + return error; + ap->low = 1; + } + if (args.fsbno != NULLFSBLOCK) { + ap->firstblock = ap->rval = args.fsbno; + ASSERT(nullfb || fb_agno == args.agno || + (ap->low && fb_agno < args.agno)); + ap->alen = args.len; + ap->ip->i_d.di_nblocks += args.len; + xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); + if (ap->wasdel) + ap->ip->i_delayed_blks -= args.len; + /* + * Adjust the disk quota also. This was reserved + * earlier. + */ + XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip, + ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT : + XFS_TRANS_DQ_BCOUNT, + (long) args.len); + } else { + ap->rval = NULLFSBLOCK; + ap->alen = 0; } return 0; -#undef ISVALID +} + +/* + * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. + * It figures out where to ask the underlying allocator to put the new extent. + */ +STATIC int +xfs_bmap_alloc( + xfs_bmalloca_t *ap) /* bmap alloc argument struct */ +{ + if ((ap->ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && ap->userdata) + return xfs_bmap_rtalloc(ap); + return xfs_bmap_btalloc(ap); } /* * Transform a btree format file with only one leaf node, where the * extents list will fit in the inode, into an extents format file. - * Since the extent list is already in-core, all we have to do is + * Since the file extents are already in-core, all we have to do is * give up the space for the btree root and pitch the leaf block. */ STATIC int /* error */ @@ -2868,7 +2873,7 @@ xfs_bmap_btree_to_extents( } /* - * Called by xfs_bmapi to update extent list structure and the btree + * Called by xfs_bmapi to update file extent records and the btree * after removing space (or undoing a delayed allocation). */ STATIC int /* error */ @@ -2878,7 +2883,7 @@ xfs_bmap_del_extent( xfs_extnum_t idx, /* extent number to update/delete */ xfs_bmap_free_t *flist, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ - xfs_bmbt_irec_t *del, /* data to remove from extent list */ + xfs_bmbt_irec_t *del, /* data to remove from extents */ int *logflagsp, /* inode logging flags */ int whichfork, /* data or attr fork */ int rsvd) /* OK to allocate reserved blocks */ @@ -2903,7 +2908,6 @@ xfs_bmap_del_extent( xfs_filblks_t nblks; /* quota/sb block count */ xfs_bmbt_irec_t new; /* new record to be inserted */ /* REFERENCED */ - xfs_extnum_t nextents; /* number of extents in list */ uint qfield; /* quota field to update */ xfs_filblks_t temp; /* for indirect length calculations */ xfs_filblks_t temp2; /* for indirect length calculations */ @@ -2911,10 +2915,10 @@ xfs_bmap_del_extent( XFS_STATS_INC(xs_del_exlist); mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); - nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); - ASSERT(idx >= 0 && idx < nextents); + ASSERT((idx >= 0) && (idx < ifp->if_bytes / + (uint)sizeof(xfs_bmbt_rec_t))); ASSERT(del->br_blockcount > 0); - ep = &ifp->if_u1.if_extents[idx]; + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_get_all(ep, &got); ASSERT(got.br_startoff <= del->br_startoff); del_endoff = del->br_startoff + del->br_blockcount; @@ -2990,7 +2994,7 @@ xfs_bmap_del_extent( * Matches the whole extent. Delete the entry. */ xfs_bmap_trace_delete(fname, "3", ip, idx, 1, whichfork); - xfs_bmap_delete_exlist(ip, idx, 1, whichfork); + xfs_iext_remove(ifp, idx, 1); ifp->if_lastex = idx; if (delay) break; @@ -3160,7 +3164,7 @@ xfs_bmap_del_extent( xfs_bmap_trace_post_update(fname, "0", ip, idx, whichfork); xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 1, &new, NULL, whichfork); - xfs_bmap_insert_exlist(ip, idx + 1, 1, &new, whichfork); + xfs_iext_insert(ifp, idx + 1, 1, &new); ifp->if_lastex = idx + 1; break; } @@ -3213,31 +3217,6 @@ xfs_bmap_del_free( } /* - * Remove count entries from the extents array for inode "ip", starting - * at index "idx". Copies the remaining items down over the deleted ones, - * and gives back the excess memory. - */ -STATIC void -xfs_bmap_delete_exlist( - xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t idx, /* starting delete index */ - xfs_extnum_t count, /* count of items to delete */ - int whichfork) /* data or attr fork */ -{ - xfs_bmbt_rec_t *base; /* base of extent list */ - xfs_ifork_t *ifp; /* inode fork pointer */ - xfs_extnum_t nextents; /* number of extents in list after */ - - ifp = XFS_IFORK_PTR(ip, whichfork); - ASSERT(ifp->if_flags & XFS_IFEXTENTS); - base = ifp->if_u1.if_extents; - nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - count; - memmove(&base[idx], &base[idx + count], - (nextents - idx) * sizeof(*base)); - xfs_iext_realloc(ip, -count, whichfork); -} - -/* * Convert an extents-format file into a btree-format file. * The new file will have a root block (in the inode) and a single child block. */ @@ -3258,13 +3237,13 @@ xfs_bmap_extents_to_btree( xfs_bmbt_rec_t *arp; /* child record pointer */ xfs_bmbt_block_t *block; /* btree root block */ xfs_btree_cur_t *cur; /* bmap btree cursor */ - xfs_bmbt_rec_t *ep; /* extent list pointer */ + xfs_bmbt_rec_t *ep; /* extent record pointer */ int error; /* error return value */ - xfs_extnum_t i, cnt; /* extent list index */ + xfs_extnum_t i, cnt; /* extent record index */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_bmbt_key_t *kp; /* root block key pointer */ xfs_mount_t *mp; /* mount structure */ - xfs_extnum_t nextents; /* extent list size */ + xfs_extnum_t nextents; /* number of file extents */ xfs_bmbt_ptr_t *pp; /* root block address pointer */ ifp = XFS_IFORK_PTR(ip, whichfork); @@ -3343,7 +3322,8 @@ xfs_bmap_extents_to_btree( ablock->bb_rightsib = cpu_to_be64(NULLDFSBNO); arp = XFS_BMAP_REC_IADDR(ablock, 1, cur); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); - for (ep = ifp->if_u1.if_extents, cnt = i = 0; i < nextents; i++, ep++) { + for (cnt = i = 0; i < nextents; i++) { + ep = xfs_iext_get_ext(ifp, i); if (!ISNULLSTARTBLOCK(xfs_bmbt_get_startblock(ep))) { arp->l0 = INT_GET(ep->l0, ARCH_CONVERT); arp->l1 = INT_GET(ep->l1, ARCH_CONVERT); @@ -3373,34 +3353,6 @@ xfs_bmap_extents_to_btree( } /* - * Insert new item(s) in the extent list for inode "ip". - * Count new items are inserted at offset idx. - */ -STATIC void -xfs_bmap_insert_exlist( - xfs_inode_t *ip, /* incore inode pointer */ - xfs_extnum_t idx, /* starting index of new items */ - xfs_extnum_t count, /* number of inserted items */ - xfs_bmbt_irec_t *new, /* items to insert */ - int whichfork) /* data or attr fork */ -{ - xfs_bmbt_rec_t *base; /* extent list base */ - xfs_ifork_t *ifp; /* inode fork pointer */ - xfs_extnum_t nextents; /* extent list size */ - xfs_extnum_t to; /* extent list index */ - - ifp = XFS_IFORK_PTR(ip, whichfork); - ASSERT(ifp->if_flags & XFS_IFEXTENTS); - xfs_iext_realloc(ip, count, whichfork); - base = ifp->if_u1.if_extents; - nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); - memmove(&base[idx + count], &base[idx], - (nextents - (idx + count)) * sizeof(*base)); - for (to = idx; to < idx + count; to++, new++) - xfs_bmbt_set_all(&base[to], new); -} - -/* * Helper routine to reset inode di_forkoff field when switching * attribute fork from local to extent format - we reset it where * possible to make space available for inline data fork extents. @@ -3457,12 +3409,13 @@ xfs_bmap_local_to_extents( error = 0; if (ifp->if_bytes) { xfs_alloc_arg_t args; /* allocation arguments */ - xfs_buf_t *bp; /* buffer for extent list block */ - xfs_bmbt_rec_t *ep; /* extent list pointer */ + xfs_buf_t *bp; /* buffer for extent block */ + xfs_bmbt_rec_t *ep; /* extent record pointer */ args.tp = tp; args.mp = ip->i_mount; - ASSERT(ifp->if_flags & XFS_IFINLINE); + ASSERT((ifp->if_flags & + (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); /* * Allocate a block. We know we need only one, since the * file currently fits in an inode. @@ -3492,8 +3445,8 @@ xfs_bmap_local_to_extents( xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); xfs_bmap_forkoff_reset(args.mp, ip, whichfork); xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); - xfs_iext_realloc(ip, 1, whichfork); - ep = ifp->if_u1.if_extents; + xfs_iext_add(ifp, 0, 1); + ep = xfs_iext_get_ext(ifp, 0); xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM); xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork); XFS_IFORK_NEXT_SET(ip, whichfork, 1); @@ -3518,7 +3471,7 @@ xfs_bmbt_rec_t * /* pointer to found extent entry */ xfs_bmap_do_search_extents( xfs_bmbt_rec_t *base, /* base of extent list */ xfs_extnum_t lastx, /* last extent index used */ - xfs_extnum_t nextents, /* extent list size */ + xfs_extnum_t nextents, /* number of file extents */ xfs_fileoff_t bno, /* block number searched for */ int *eofp, /* out: end of file found */ xfs_extnum_t *lastxp, /* out: last extent index */ @@ -3569,9 +3522,9 @@ xfs_bmap_do_search_extents( got.br_blockcount = xfs_bmbt_get_blockcount(ep); *eofp = 0; } else { - /* binary search the extents array */ low = 0; high = nextents - 1; + /* binary search the extents array */ while (low <= high) { XFS_STATS_INC(xs_cmp_exlist); lastx = (low + high) >> 1; @@ -3622,6 +3575,57 @@ xfs_bmap_do_search_extents( } /* + * Search the extent records for the entry containing block bno. + * If bno lies in a hole, point to the next entry. If bno lies + * past eof, *eofp will be set, and *prevp will contain the last + * entry (null if none). Else, *lastxp will be set to the index + * of the found entry; *gotp will contain the entry. + */ +xfs_bmbt_rec_t * /* pointer to found extent entry */ +xfs_bmap_search_multi_extents( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_fileoff_t bno, /* block number searched for */ + int *eofp, /* out: end of file found */ + xfs_extnum_t *lastxp, /* out: last extent index */ + xfs_bmbt_irec_t *gotp, /* out: extent entry found */ + xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ +{ + xfs_bmbt_rec_t *ep; /* extent record pointer */ + xfs_extnum_t lastx; /* last extent index */ + + /* + * Initialize the extent entry structure to catch access to + * uninitialized br_startblock field. + */ + gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL; + gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL; + gotp->br_state = XFS_EXT_INVALID; +#if XFS_BIG_BLKNOS + gotp->br_startblock = 0xffffa5a5a5a5a5a5LL; +#else + gotp->br_startblock = 0xffffa5a5; +#endif + prevp->br_startoff = NULLFILEOFF; + + ep = xfs_iext_bno_to_ext(ifp, bno, &lastx); + if (lastx > 0) { + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp); + } + if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) { + xfs_bmbt_get_all(ep, gotp); + *eofp = 0; + } else { + if (lastx > 0) { + *gotp = *prevp; + } + *eofp = 1; + ep = NULL; + } + *lastxp = lastx; + return ep; +} + +/* * Search the extents list for the inode, for the extent containing bno. * If bno lies in a hole, point to the next entry. If bno lies past eof, * *eofp will be set, and *prevp will contain the last entry (null if none). @@ -3639,20 +3643,14 @@ xfs_bmap_search_extents( xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ { xfs_ifork_t *ifp; /* inode fork pointer */ - xfs_bmbt_rec_t *base; /* base of extent list */ - xfs_extnum_t lastx; /* last extent index used */ - xfs_extnum_t nextents; /* extent list size */ - xfs_bmbt_rec_t *ep; /* extent list entry pointer */ + xfs_bmbt_rec_t *ep; /* extent record pointer */ int rt; /* realtime flag */ XFS_STATS_INC(xs_look_exlist); ifp = XFS_IFORK_PTR(ip, whichfork); - lastx = ifp->if_lastex; - nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); - base = &ifp->if_u1.if_extents[0]; - ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp, - lastxp, gotp, prevp); + ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp); + rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); if (unlikely(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM))) { cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld " @@ -3732,7 +3730,7 @@ xfs_bmap_trace_addentry( } /* - * Add bmap trace entry prior to a call to xfs_bmap_delete_exlist. + * Add bmap trace entry prior to a call to xfs_iext_remove. */ STATIC void xfs_bmap_trace_delete( @@ -3747,13 +3745,13 @@ xfs_bmap_trace_delete( ifp = XFS_IFORK_PTR(ip, whichfork); xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_DELETE, fname, desc, ip, idx, - cnt, &ifp->if_u1.if_extents[idx], - cnt == 2 ? &ifp->if_u1.if_extents[idx + 1] : NULL, + cnt, xfs_iext_get_ext(ifp, idx), + cnt == 2 ? xfs_iext_get_ext(ifp, idx + 1) : NULL, whichfork); } /* - * Add bmap trace entry prior to a call to xfs_bmap_insert_exlist, or + * Add bmap trace entry prior to a call to xfs_iext_insert, or * reading in the extents list from the disk (in the btree). */ STATIC void @@ -3783,7 +3781,7 @@ xfs_bmap_trace_insert( } /* - * Add bmap trace entry after updating an extent list entry in place. + * Add bmap trace entry after updating an extent record in place. */ STATIC void xfs_bmap_trace_post_update( @@ -3797,11 +3795,11 @@ xfs_bmap_trace_post_update( ifp = XFS_IFORK_PTR(ip, whichfork); xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_POST_UP, fname, desc, ip, idx, - 1, &ifp->if_u1.if_extents[idx], NULL, whichfork); + 1, xfs_iext_get_ext(ifp, idx), NULL, whichfork); } /* - * Add bmap trace entry prior to updating an extent list entry in place. + * Add bmap trace entry prior to updating an extent record in place. */ STATIC void xfs_bmap_trace_pre_update( @@ -3815,7 +3813,7 @@ xfs_bmap_trace_pre_update( ifp = XFS_IFORK_PTR(ip, whichfork); xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_PRE_UP, fname, desc, ip, idx, 1, - &ifp->if_u1.if_extents[idx], NULL, whichfork); + xfs_iext_get_ext(ifp, idx), NULL, whichfork); } #endif /* XFS_BMAP_TRACE */ @@ -3892,7 +3890,7 @@ xfs_bmap_add_attrfork( int rsvd) /* xact may use reserved blks */ { xfs_fsblock_t firstblock; /* 1st block/ag allocated */ - xfs_bmap_free_t flist; /* freed extent list */ + xfs_bmap_free_t flist; /* freed extent records */ xfs_mount_t *mp; /* mount structure */ xfs_trans_t *tp; /* transaction pointer */ unsigned long s; /* spinlock spl value */ @@ -4146,7 +4144,7 @@ xfs_bmap_finish( xfs_efd_log_item_t *efd; /* extent free data */ xfs_efi_log_item_t *efi; /* extent free intention */ int error; /* error return value */ - xfs_bmap_free_item_t *free; /* free extent list item */ + xfs_bmap_free_item_t *free; /* free extent item */ unsigned int logres; /* new log reservation */ unsigned int logcount; /* new log count */ xfs_mount_t *mp; /* filesystem mount structure */ @@ -4242,9 +4240,9 @@ xfs_bmap_first_unused( xfs_fileoff_t *first_unused, /* unused block */ int whichfork) /* data or attr fork */ { - xfs_bmbt_rec_t *base; /* base of extent array */ xfs_bmbt_rec_t *ep; /* pointer to an extent entry */ int error; /* error return value */ + int idx; /* extent record index */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_fileoff_t lastaddr; /* last block number seen */ xfs_fileoff_t lowest; /* lowest useful block */ @@ -4265,10 +4263,8 @@ xfs_bmap_first_unused( return error; lowest = *first_unused; nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); - base = &ifp->if_u1.if_extents[0]; - for (lastaddr = 0, max = lowest, ep = base; - ep < &base[nextents]; - ep++) { + for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) { + ep = xfs_iext_get_ext(ifp, idx); off = xfs_bmbt_get_startoff(ep); /* * See if the hole before this extent will work. @@ -4287,8 +4283,8 @@ xfs_bmap_first_unused( /* * Returns the file-relative block number of the last block + 1 before * last_block (input value) in the file. - * This is not based on i_size, it is based on the extent list. - * Returns 0 for local files, as they do not have an extent list. + * This is not based on i_size, it is based on the extent records. + * Returns 0 for local files, as they do not have extent records. */ int /* error */ xfs_bmap_last_before( @@ -4335,8 +4331,8 @@ xfs_bmap_last_before( /* * Returns the file-relative block number of the first block past eof in - * the file. This is not based on i_size, it is based on the extent list. - * Returns 0 for local files, as they do not have an extent list. + * the file. This is not based on i_size, it is based on the extent records. + * Returns 0 for local files, as they do not have extent records. */ int /* error */ xfs_bmap_last_offset( @@ -4345,7 +4341,6 @@ xfs_bmap_last_offset( xfs_fileoff_t *last_block, /* last block */ int whichfork) /* data or attr fork */ { - xfs_bmbt_rec_t *base; /* base of extent array */ xfs_bmbt_rec_t *ep; /* pointer to last extent */ int error; /* error return value */ xfs_ifork_t *ifp; /* inode fork pointer */ @@ -4368,9 +4363,7 @@ xfs_bmap_last_offset( *last_block = 0; return 0; } - base = &ifp->if_u1.if_extents[0]; - ASSERT(base != NULL); - ep = &base[nextents - 1]; + ep = xfs_iext_get_ext(ifp, nextents - 1); *last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep); return 0; } @@ -4400,7 +4393,7 @@ xfs_bmap_one_block( return 0; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(ifp->if_flags & XFS_IFEXTENTS); - ep = ifp->if_u1.if_extents; + ep = xfs_iext_get_ext(ifp, 0); xfs_bmbt_get_all(ep, &s); rval = s.br_startoff == 0 && s.br_blockcount == 1; if (rval && whichfork == XFS_DATA_FORK) @@ -4435,7 +4428,6 @@ xfs_bmap_read_extents( xfs_bmbt_ptr_t *pp; /* pointer to block address */ /* REFERENCED */ xfs_extnum_t room; /* number of entries there's room for */ - xfs_bmbt_rec_t *trp; /* target record pointer */ bno = NULLFSBLOCK; mp = ip->i_mount; @@ -4478,16 +4470,16 @@ xfs_bmap_read_extents( /* * Here with bp and block set to the leftmost leaf node in the tree. */ - room = ifp->if_bytes / (uint)sizeof(*trp); - trp = ifp->if_u1.if_extents; + room = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); i = 0; /* - * Loop over all leaf nodes. Copy information to the extent list. + * Loop over all leaf nodes. Copy information to the extent records. */ for (;;) { - xfs_bmbt_rec_t *frp, *temp; + xfs_bmbt_rec_t *frp, *trp; xfs_fsblock_t nextbno; xfs_extnum_t num_recs; + xfs_extnum_t start; num_recs = be16_to_cpu(block->bb_numrecs); @@ -4511,12 +4503,13 @@ xfs_bmap_read_extents( if (nextbno != NULLFSBLOCK) xfs_btree_reada_bufl(mp, nextbno, 1); /* - * Copy records into the extent list. + * Copy records into the extent records. */ frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block, 1, mp->m_bmap_dmxr[0]); - temp = trp; - for (j = 0; j < num_recs; j++, frp++, trp++) { + start = i; + for (j = 0; j < num_recs; j++, i++, frp++) { + trp = xfs_iext_get_ext(ifp, i); trp->l0 = INT_GET(frp->l0, ARCH_CONVERT); trp->l1 = INT_GET(frp->l1, ARCH_CONVERT); } @@ -4526,14 +4519,14 @@ xfs_bmap_read_extents( * any "older" data bmap btree records for a * set bit in the "extent flag" position. */ - if (unlikely(xfs_check_nostate_extents(temp, num_recs))) { + if (unlikely(xfs_check_nostate_extents(ifp, + start, num_recs))) { XFS_ERROR_REPORT("xfs_bmap_read_extents(2)", XFS_ERRLEVEL_LOW, ip->i_mount); goto error0; } } - i += num_recs; xfs_trans_brelse(tp, bp); bno = nextbno; /* @@ -4546,7 +4539,7 @@ xfs_bmap_read_extents( return error; block = XFS_BUF_TO_BMBT_BLOCK(bp); } - ASSERT(i == ifp->if_bytes / (uint)sizeof(*trp)); + ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))); ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork)); xfs_bmap_trace_exlist(fname, ip, i, whichfork); return 0; @@ -4557,7 +4550,7 @@ error0: #ifdef XFS_BMAP_TRACE /* - * Add bmap trace insert entries for all the contents of the extent list. + * Add bmap trace insert entries for all the contents of the extent records. */ void xfs_bmap_trace_exlist( @@ -4566,16 +4559,15 @@ xfs_bmap_trace_exlist( xfs_extnum_t cnt, /* count of entries in the list */ int whichfork) /* data or attr fork */ { - xfs_bmbt_rec_t *base; /* base of extent list */ - xfs_bmbt_rec_t *ep; /* current entry in extent list */ - xfs_extnum_t idx; /* extent list entry number */ + xfs_bmbt_rec_t *ep; /* current extent record */ + xfs_extnum_t idx; /* extent record index */ xfs_ifork_t *ifp; /* inode fork pointer */ - xfs_bmbt_irec_t s; /* extent list record */ + xfs_bmbt_irec_t s; /* file extent record */ ifp = XFS_IFORK_PTR(ip, whichfork); - ASSERT(cnt == ifp->if_bytes / (uint)sizeof(*base)); - base = ifp->if_u1.if_extents; - for (idx = 0, ep = base; idx < cnt; idx++, ep++) { + ASSERT(cnt == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))); + for (idx = 0; idx < cnt; idx++) { + ep = xfs_iext_get_ext(ifp, idx); xfs_bmbt_get_all(ep, &s); xfs_bmap_trace_insert(fname, "exlist", ip, idx, 1, &s, NULL, whichfork); @@ -4661,14 +4653,10 @@ xfs_bmapi( xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */ xfs_btree_cur_t *cur; /* bmap btree cursor */ xfs_fileoff_t end; /* end of mapped file region */ - int eof; /* we've hit the end of extent list */ - char contig; /* allocation must be one extent */ - char delay; /* this request is for delayed alloc */ - char exact; /* don't do all of wasdelayed extent */ - char convert; /* unwritten extent I/O completion */ - xfs_bmbt_rec_t *ep; /* extent list entry pointer */ + int eof; /* we've hit the end of extents */ + xfs_bmbt_rec_t *ep; /* extent record pointer */ int error; /* error return */ - xfs_bmbt_irec_t got; /* current extent list record */ + xfs_bmbt_irec_t got; /* current file extent record */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_extlen_t indlen; /* indirect blocks length */ xfs_extnum_t lastx; /* last useful extent number */ @@ -4680,17 +4668,13 @@ xfs_bmapi( int nallocs; /* number of extents alloc\'d */ xfs_extnum_t nextents; /* number of extents in file */ xfs_fileoff_t obno; /* old block number (offset) */ - xfs_bmbt_irec_t prev; /* previous extent list record */ + xfs_bmbt_irec_t prev; /* previous file extent record */ int tmp_logflags; /* temp flags holder */ int whichfork; /* data or attr fork */ char inhole; /* current location is hole in file */ - char stateless; /* ignore state flag set */ - char trim; /* output trimmed to match range */ - char userdata; /* allocating non-metadata */ char wasdelay; /* old extent was delayed */ char wr; /* this is a write request */ char rt; /* this is a realtime file */ - char rsvd; /* OK to allocate reserved blocks */ #ifdef DEBUG xfs_fileoff_t orig_bno; /* original block number value */ int orig_flags; /* original flags arg value */ @@ -4727,15 +4711,8 @@ xfs_bmapi( XFS_STATS_INC(xs_blk_mapw); else XFS_STATS_INC(xs_blk_mapr); - delay = (flags & XFS_BMAPI_DELAY) != 0; - trim = (flags & XFS_BMAPI_ENTIRE) == 0; - userdata = (flags & XFS_BMAPI_METADATA) == 0; - convert = (flags & XFS_BMAPI_CONVERT) != 0; - exact = (flags & XFS_BMAPI_EXACT) != 0; - rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0; - contig = (flags & XFS_BMAPI_CONTIG) != 0; /* - * stateless is used to combine extents which + * IGSTATE flag is used to combine extents which * differ only due to the state of the extents. * This technique is used from xfs_getbmap() * when the caller does not wish to see the @@ -4751,10 +4728,9 @@ xfs_bmapi( * xfs_strat_comp(), where the xfs_bmapi() call * is transactioned, and the extents combined. */ - stateless = (flags & XFS_BMAPI_IGSTATE) != 0; - if (stateless && wr) /* if writing unwritten space, no */ - wr = 0; /* allocations are allowed */ - ASSERT(wr || !delay); + if ((flags & XFS_BMAPI_IGSTATE) && wr) /* if writing unwritten space */ + wr = 0; /* no allocations are allowed */ + ASSERT(wr || !(flags & XFS_BMAPI_DELAY)); logflags = 0; nallocs = 0; cur = NULL; @@ -4789,7 +4765,7 @@ xfs_bmapi( if (eof && !wr) got.br_startoff = end; inhole = eof || got.br_startoff > bno; - wasdelay = wr && !inhole && !delay && + wasdelay = wr && !inhole && !(flags & XFS_BMAPI_DELAY) && ISNULLSTARTBLOCK(got.br_startblock); /* * First, deal with the hole before the allocated space @@ -4801,11 +4777,11 @@ xfs_bmapi( * allocate the stuff asked for in this bmap call * but that wouldn't be as good. */ - if (wasdelay && !exact) { + if (wasdelay && !(flags & XFS_BMAPI_EXACT)) { alen = (xfs_extlen_t)got.br_blockcount; aoff = got.br_startoff; if (lastx != NULLEXTNUM && lastx) { - ep = &ifp->if_u1.if_extents[lastx - 1]; + ep = xfs_iext_get_ext(ifp, lastx - 1); xfs_bmbt_get_all(ep, &prev); } } else if (wasdelay) { @@ -4823,8 +4799,8 @@ xfs_bmapi( got.br_startoff - bno); aoff = bno; } - minlen = contig ? alen : 1; - if (delay) { + minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1; + if (flags & XFS_BMAPI_DELAY) { xfs_extlen_t extsz; /* Figure out the extent size, adjust alen */ @@ -4837,7 +4813,9 @@ xfs_bmapi( if (extsz) { error = xfs_bmap_extsize_align(mp, &got, &prev, extsz, - rt, eof, delay, convert, + rt, eof, + flags&XFS_BMAPI_DELAY, + flags&XFS_BMAPI_CONVERT, &aoff, &alen); ASSERT(!error); } @@ -4875,24 +4853,29 @@ xfs_bmapi( if (rt) { error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, - -(extsz), rsvd); + -(extsz), (flags & + XFS_BMAPI_RSVBLOCKS)); } else { error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, - -(alen), rsvd); + -(alen), (flags & + XFS_BMAPI_RSVBLOCKS)); } if (!error) { error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, - -(indlen), rsvd); + -(indlen), (flags & + XFS_BMAPI_RSVBLOCKS)); if (error && rt) xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, - extsz, rsvd); + extsz, (flags & + XFS_BMAPI_RSVBLOCKS)); else if (error) xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, - alen, rsvd); + alen, (flags & + XFS_BMAPI_RSVBLOCKS)); } if (error) { @@ -4925,7 +4908,7 @@ xfs_bmapi( /* Indicate if this is the first user data * in the file, or just any user data. */ - if (userdata) { + if (!(flags & XFS_BMAPI_METADATA)) { bma.userdata = (aoff == 0) ? XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA; @@ -4937,7 +4920,7 @@ xfs_bmapi( bma.firstblock = *firstblock; bma.alen = alen; bma.off = aoff; - bma.conv = convert; + bma.conv = (flags & XFS_BMAPI_CONVERT); bma.wasdel = wasdelay; bma.minlen = minlen; bma.low = flist->xbf_low; @@ -4948,7 +4931,8 @@ xfs_bmapi( * is larger than a stripe unit. */ if (mp->m_dalign && alen >= mp->m_dalign && - userdata && whichfork == XFS_DATA_FORK) { + (!(flags & XFS_BMAPI_METADATA)) && + (whichfork == XFS_DATA_FORK)) { if ((error = xfs_bmap_isaeof(ip, aoff, whichfork, &bma.aeof))) goto error0; @@ -5011,19 +4995,19 @@ xfs_bmapi( } error = xfs_bmap_add_extent(ip, lastx, &cur, &got, firstblock, flist, &tmp_logflags, whichfork, - rsvd); + (flags & XFS_BMAPI_RSVBLOCKS)); logflags |= tmp_logflags; if (error) goto error0; lastx = ifp->if_lastex; - ep = &ifp->if_u1.if_extents[lastx]; + ep = xfs_iext_get_ext(ifp, lastx); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); xfs_bmbt_get_all(ep, &got); ASSERT(got.br_startoff <= aoff); ASSERT(got.br_startoff + got.br_blockcount >= aoff + alen); #ifdef DEBUG - if (delay) { + if (flags & XFS_BMAPI_DELAY) { ASSERT(ISNULLSTARTBLOCK(got.br_startblock)); ASSERT(STARTBLOCKVAL(got.br_startblock) > 0); } @@ -5052,14 +5036,15 @@ xfs_bmapi( * Then deal with the allocated space we found. */ ASSERT(ep != NULL); - if (trim && (got.br_startoff + got.br_blockcount > obno)) { + if (!(flags & XFS_BMAPI_ENTIRE) && + (got.br_startoff + got.br_blockcount > obno)) { if (obno > bno) bno = obno; ASSERT((bno >= obno) || (n == 0)); ASSERT(bno < end); mval->br_startoff = bno; if (ISNULLSTARTBLOCK(got.br_startblock)) { - ASSERT(!wr || delay); + ASSERT(!wr || (flags & XFS_BMAPI_DELAY)); mval->br_startblock = DELAYSTARTBLOCK; } else mval->br_startblock = @@ -5081,7 +5066,7 @@ xfs_bmapi( } else { *mval = got; if (ISNULLSTARTBLOCK(mval->br_startblock)) { - ASSERT(!wr || delay); + ASSERT(!wr || (flags & XFS_BMAPI_DELAY)); mval->br_startblock = DELAYSTARTBLOCK; } } @@ -5107,12 +5092,12 @@ xfs_bmapi( mval->br_state = XFS_EXT_NORM; error = xfs_bmap_add_extent(ip, lastx, &cur, mval, firstblock, flist, &tmp_logflags, whichfork, - rsvd); + (flags & XFS_BMAPI_RSVBLOCKS)); logflags |= tmp_logflags; if (error) goto error0; lastx = ifp->if_lastex; - ep = &ifp->if_u1.if_extents[lastx]; + ep = xfs_iext_get_ext(ifp, lastx); nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); xfs_bmbt_get_all(ep, &got); /* @@ -5124,9 +5109,10 @@ xfs_bmapi( continue; } - ASSERT(!trim || + ASSERT((flags & XFS_BMAPI_ENTIRE) || ((mval->br_startoff + mval->br_blockcount) <= end)); - ASSERT(!trim || (mval->br_blockcount <= len) || + ASSERT((flags & XFS_BMAPI_ENTIRE) || + (mval->br_blockcount <= len) || (mval->br_startoff < obno)); bno = mval->br_startoff + mval->br_blockcount; len = end - bno; @@ -5141,7 +5127,8 @@ xfs_bmapi( mval[-1].br_startblock != HOLESTARTBLOCK && mval->br_startblock == mval[-1].br_startblock + mval[-1].br_blockcount && - (stateless || mval[-1].br_state == mval->br_state)) { + ((flags & XFS_BMAPI_IGSTATE) || + mval[-1].br_state == mval->br_state)) { ASSERT(mval->br_startoff == mval[-1].br_startoff + mval[-1].br_blockcount); mval[-1].br_blockcount += mval->br_blockcount; @@ -5168,8 +5155,7 @@ xfs_bmapi( /* * Else go on to the next record. */ - ep++; - lastx++; + ep = xfs_iext_get_ext(ifp, ++lastx); if (lastx >= nextents) { eof = 1; prev = got; @@ -5199,7 +5185,7 @@ xfs_bmapi( error0: /* * Log everything. Do this after conversion, there's no point in - * logging the extent list if we've converted to btree format. + * logging the extent records if we've converted to btree format. */ if ((logflags & XFS_ILOG_FEXT(whichfork)) && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) @@ -5252,12 +5238,12 @@ xfs_bmapi_single( xfs_fsblock_t *fsb, /* output: mapped block */ xfs_fileoff_t bno) /* starting file offs. mapped */ { - int eof; /* we've hit the end of extent list */ + int eof; /* we've hit the end of extents */ int error; /* error return */ - xfs_bmbt_irec_t got; /* current extent list record */ + xfs_bmbt_irec_t got; /* current file extent record */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_extnum_t lastx; /* last useful extent number */ - xfs_bmbt_irec_t prev; /* previous extent list record */ + xfs_bmbt_irec_t prev; /* previous file extent record */ ifp = XFS_IFORK_PTR(ip, whichfork); if (unlikely( @@ -5312,18 +5298,18 @@ xfs_bunmapi( xfs_btree_cur_t *cur; /* bmap btree cursor */ xfs_bmbt_irec_t del; /* extent being deleted */ int eof; /* is deleting at eof */ - xfs_bmbt_rec_t *ep; /* extent list entry pointer */ + xfs_bmbt_rec_t *ep; /* extent record pointer */ int error; /* error return value */ xfs_extnum_t extno; /* extent number in list */ - xfs_bmbt_irec_t got; /* current extent list entry */ + xfs_bmbt_irec_t got; /* current extent record */ xfs_ifork_t *ifp; /* inode fork pointer */ int isrt; /* freeing in rt area */ xfs_extnum_t lastx; /* last extent index used */ int logflags; /* transaction logging flags */ xfs_extlen_t mod; /* rt extent offset */ xfs_mount_t *mp; /* mount structure */ - xfs_extnum_t nextents; /* size of extent list */ - xfs_bmbt_irec_t prev; /* previous extent list entry */ + xfs_extnum_t nextents; /* number of file extents */ + xfs_bmbt_irec_t prev; /* previous extent record */ xfs_fileoff_t start; /* first file offset deleted */ int tmp_logflags; /* partial logging flags */ int wasdel; /* was a delayed alloc extent */ @@ -5369,7 +5355,7 @@ xfs_bunmapi( * file, back up to the last block if so... */ if (eof) { - ep = &ifp->if_u1.if_extents[--lastx]; + ep = xfs_iext_get_ext(ifp, --lastx); xfs_bmbt_get_all(ep, &got); bno = got.br_startoff + got.br_blockcount - 1; } @@ -5393,7 +5379,7 @@ xfs_bunmapi( if (got.br_startoff > bno) { if (--lastx < 0) break; - ep--; + ep = xfs_iext_get_ext(ifp, lastx); xfs_bmbt_get_all(ep, &got); } /* @@ -5440,7 +5426,8 @@ xfs_bunmapi( del.br_blockcount : mod; if (bno < got.br_startoff) { if (--lastx >= 0) - xfs_bmbt_get_all(--ep, &got); + xfs_bmbt_get_all(xfs_iext_get_ext( + ifp, lastx), &got); } continue; } @@ -5500,7 +5487,8 @@ xfs_bunmapi( * try again. */ ASSERT(lastx > 0); - xfs_bmbt_get_all(ep - 1, &prev); + xfs_bmbt_get_all(xfs_iext_get_ext(ifp, + lastx - 1), &prev); ASSERT(prev.br_state == XFS_EXT_NORM); ASSERT(!ISNULLSTARTBLOCK(prev.br_startblock)); ASSERT(del.br_startblock == @@ -5587,12 +5575,12 @@ nodelete: * If not done go on to the next (previous) record. * Reset ep in case the extents array was re-alloced. */ - ep = &ifp->if_u1.if_extents[lastx]; + ep = xfs_iext_get_ext(ifp, lastx); if (bno != (xfs_fileoff_t)-1 && bno >= start) { if (lastx >= XFS_IFORK_NEXTENTS(ip, whichfork) || xfs_bmbt_get_startoff(ep) > bno) { - lastx--; - ep--; + if (--lastx >= 0) + ep = xfs_iext_get_ext(ifp, lastx); } if (lastx >= 0) xfs_bmbt_get_all(ep, &got); @@ -5636,7 +5624,7 @@ nodelete: error0: /* * Log everything. Do this after conversion, there's no point in - * logging the extent list if we've converted to btree format. + * logging the extent records if we've converted to btree format. */ if ((logflags & XFS_ILOG_FEXT(whichfork)) && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) @@ -5892,9 +5880,9 @@ xfs_bmap_isaeof( { int error; /* error return value */ xfs_ifork_t *ifp; /* inode fork pointer */ - xfs_bmbt_rec_t *lastrec; /* extent list entry pointer */ - xfs_extnum_t nextents; /* size of extent list */ - xfs_bmbt_irec_t s; /* expanded extent list entry */ + xfs_bmbt_rec_t *lastrec; /* extent record pointer */ + xfs_extnum_t nextents; /* number of file extents */ + xfs_bmbt_irec_t s; /* expanded extent record */ ASSERT(whichfork == XFS_DATA_FORK); ifp = XFS_IFORK_PTR(ip, whichfork); @@ -5909,7 +5897,7 @@ xfs_bmap_isaeof( /* * Go to the last extent */ - lastrec = &ifp->if_u1.if_extents[nextents - 1]; + lastrec = xfs_iext_get_ext(ifp, nextents - 1); xfs_bmbt_get_all(lastrec, &s); /* * Check we are allocating in the last extent (for delayed allocations) @@ -5936,8 +5924,8 @@ xfs_bmap_eof( xfs_fsblock_t blockcount; /* extent block count */ int error; /* error return value */ xfs_ifork_t *ifp; /* inode fork pointer */ - xfs_bmbt_rec_t *lastrec; /* extent list entry pointer */ - xfs_extnum_t nextents; /* size of extent list */ + xfs_bmbt_rec_t *lastrec; /* extent record pointer */ + xfs_extnum_t nextents; /* number of file extents */ xfs_fileoff_t startoff; /* extent starting file offset */ ASSERT(whichfork == XFS_DATA_FORK); @@ -5953,7 +5941,7 @@ xfs_bmap_eof( /* * Go to the last extent */ - lastrec = &ifp->if_u1.if_extents[nextents - 1]; + lastrec = xfs_iext_get_ext(ifp, nextents - 1); startoff = xfs_bmbt_get_startoff(lastrec); blockcount = xfs_bmbt_get_blockcount(lastrec); *eof = endoff >= startoff + blockcount; @@ -5969,18 +5957,21 @@ xfs_bmap_check_extents( xfs_inode_t *ip, /* incore inode pointer */ int whichfork) /* data or attr fork */ { - xfs_bmbt_rec_t *base; /* base of extents list */ xfs_bmbt_rec_t *ep; /* current extent entry */ + xfs_extnum_t idx; /* extent record index */ xfs_ifork_t *ifp; /* inode fork pointer */ xfs_extnum_t nextents; /* number of extents in list */ + xfs_bmbt_rec_t *nextp; /* next extent entry */ ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(ifp->if_flags & XFS_IFEXTENTS); - base = ifp->if_u1.if_extents; nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); - for (ep = base; ep < &base[nextents - 1]; ep++) { + ep = xfs_iext_get_ext(ifp, 0); + for (idx = 0; idx < nextents - 1; idx++) { + nextp = xfs_iext_get_ext(ifp, idx + 1); xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep, - (void *)(ep + 1)); + (void *)(nextp)); + ep = nextp; } } @@ -6119,12 +6110,14 @@ xfs_bmap_check_leaf_extents( xfs_fsblock_t bno; /* block # of "block" */ xfs_buf_t *bp; /* buffer for "block" */ int error; /* error return value */ - xfs_extnum_t i=0; /* index into the extents list */ + xfs_extnum_t i=0, j; /* index into the extents list */ xfs_ifork_t *ifp; /* fork structure */ int level; /* btree level, for checking */ xfs_mount_t *mp; /* file system mount structure */ xfs_bmbt_ptr_t *pp; /* pointer to block address */ - xfs_bmbt_rec_t *ep, *lastp; /* extent pointers in block entry */ + xfs_bmbt_rec_t *ep; /* pointer to current extent */ + xfs_bmbt_rec_t *lastp; /* pointer to previous extent */ + xfs_bmbt_rec_t *nextp; /* pointer to next extent */ int bp_release = 0; if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) { @@ -6194,7 +6187,6 @@ xfs_bmap_check_leaf_extents( */ lastp = NULL; for (;;) { - xfs_bmbt_rec_t *frp; xfs_fsblock_t nextbno; xfs_extnum_t num_recs; @@ -6213,18 +6205,20 @@ xfs_bmap_check_leaf_extents( * conform with the first entry in this one. */ - frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, + ep = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block, 1, mp->m_bmap_dmxr[0]); - - for (ep = frp;ep < frp + (num_recs - 1); ep++) { + for (j = 1; j < num_recs; j++) { + nextp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, + block, j + 1, mp->m_bmap_dmxr[0]); if (lastp) { xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)lastp, (void *)ep); } xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep, - (void *)(ep + 1)); + (void *)(nextp)); + lastp = ep; + ep = nextp; } - lastp = frp + num_recs - 1; /* For the next iteration */ i += num_recs; if (bp_release) { @@ -6288,7 +6282,7 @@ xfs_bmap_count_blocks( mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) { - if (unlikely(xfs_bmap_count_leaves(ifp->if_u1.if_extents, + if (unlikely(xfs_bmap_count_leaves(ifp, 0, ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t), count) < 0)) { XFS_ERROR_REPORT("xfs_bmap_count_blocks(1)", @@ -6310,7 +6304,7 @@ xfs_bmap_count_blocks( ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks); bno = INT_GET(*pp, ARCH_CONVERT); - if (unlikely(xfs_bmap_count_tree(mp, tp, bno, level, count) < 0)) { + if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) { XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); @@ -6327,6 +6321,7 @@ int /* error */ xfs_bmap_count_tree( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ + xfs_ifork_t *ifp, /* inode fork pointer */ xfs_fsblock_t blockno, /* file system block number */ int levelin, /* level in btree */ int *count) /* Count of blocks */ @@ -6339,7 +6334,6 @@ xfs_bmap_count_tree( xfs_fsblock_t nextbno; xfs_bmbt_block_t *block, *nextblock; int numrecs; - xfs_bmbt_rec_t *frp; if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF))) return error; @@ -6364,7 +6358,7 @@ xfs_bmap_count_tree( xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]); bno = INT_GET(*pp, ARCH_CONVERT); if (unlikely((error = - xfs_bmap_count_tree(mp, tp, bno, level, count)) < 0)) { + xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) { xfs_trans_brelse(tp, bp); XFS_ERROR_REPORT("xfs_bmap_count_tree(1)", XFS_ERRLEVEL_LOW, mp); @@ -6376,9 +6370,8 @@ xfs_bmap_count_tree( for (;;) { nextbno = be64_to_cpu(block->bb_rightsib); numrecs = be16_to_cpu(block->bb_numrecs); - frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, - xfs_bmbt, block, 1, mp->m_bmap_dmxr[0]); - if (unlikely(xfs_bmap_disk_count_leaves(frp, numrecs, count) < 0)) { + if (unlikely(xfs_bmap_disk_count_leaves(ifp, mp, + 0, block, numrecs, count) < 0)) { xfs_trans_brelse(tp, bp); XFS_ERROR_REPORT("xfs_bmap_count_tree(2)", XFS_ERRLEVEL_LOW, mp); @@ -6399,33 +6392,45 @@ xfs_bmap_count_tree( } /* - * Count leaf blocks given a pointer to an extent list. + * Count leaf blocks given a range of extent records. */ int xfs_bmap_count_leaves( - xfs_bmbt_rec_t *frp, + xfs_ifork_t *ifp, + xfs_extnum_t idx, int numrecs, int *count) { int b; + xfs_bmbt_rec_t *frp; - for ( b = 1; b <= numrecs; b++, frp++) + for (b = 0; b < numrecs; b++) { + frp = xfs_iext_get_ext(ifp, idx + b); *count += xfs_bmbt_get_blockcount(frp); + } return 0; } /* - * Count leaf blocks given a pointer to an extent list originally in btree format. + * Count leaf blocks given a range of extent records originally + * in btree format. */ int xfs_bmap_disk_count_leaves( - xfs_bmbt_rec_t *frp, + xfs_ifork_t *ifp, + xfs_mount_t *mp, + xfs_extnum_t idx, + xfs_bmbt_block_t *block, int numrecs, int *count) { int b; + xfs_bmbt_rec_t *frp; - for ( b = 1; b <= numrecs; b++, frp++) + for (b = 1; b <= numrecs; b++) { + frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, + xfs_bmbt, block, idx + b, mp->m_bmap_dmxr[0]); *count += xfs_bmbt_disk_get_blockcount(frp); + } return 0; } diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 12cc63dfc2c4..011ccaa9a1c0 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h @@ -20,6 +20,7 @@ struct getbmap; struct xfs_bmbt_irec; +struct xfs_ifork; struct xfs_inode; struct xfs_mount; struct xfs_trans; @@ -347,9 +348,28 @@ xfs_bmap_count_blocks( */ int xfs_check_nostate_extents( - xfs_bmbt_rec_t *ep, + struct xfs_ifork *ifp, + xfs_extnum_t idx, xfs_extnum_t num); +/* + * Call xfs_bmap_do_search_extents() to search for the extent + * record containing block bno. If in multi-level in-core extent + * allocation mode, find and extract the target extent buffer, + * otherwise just use the direct extent list. + */ +xfs_bmbt_rec_t * +xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *, + xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *); + +/* + * Search an extent list for the extent which includes block + * bno. + */ +xfs_bmbt_rec_t *xfs_bmap_do_search_extents(xfs_bmbt_rec_t *, + xfs_extnum_t, xfs_extnum_t, xfs_fileoff_t, int *, + xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *); + #endif /* __KERNEL__ */ #endif /* __XFS_BMAP_H__ */ diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 3f1383d160e8..bea44709afbe 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -2754,7 +2754,7 @@ xfs_bmbt_update( } /* - * Check an extent list, which has just been read, for + * Check extent records, which have just been read, for * any bit in the extent flag field. ASSERT on debug * kernels, as this condition should not occur. * Return an error condition (1) if any flags found, @@ -2763,10 +2763,14 @@ xfs_bmbt_update( int xfs_check_nostate_extents( - xfs_bmbt_rec_t *ep, + xfs_ifork_t *ifp, + xfs_extnum_t idx, xfs_extnum_t num) { - for (; num > 0; num--, ep++) { + xfs_bmbt_rec_t *ep; + + for (; num > 0; num--, idx++) { + ep = xfs_iext_get_ext(ifp, idx); if ((ep->l0 >> (64 - BMBT_EXNTFLAG_BITLEN)) != 0) { ASSERT(0); diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h index e095a2d344ae..6478cfa0e539 100644 --- a/fs/xfs/xfs_bmap_btree.h +++ b/fs/xfs/xfs_bmap_btree.h @@ -372,14 +372,6 @@ extern int xfs_bmbt_get_rec(struct xfs_btree_cur *, xfs_fileoff_t *, xfs_exntst_t *, int *); #endif -/* - * Search an extent list for the extent which includes block - * bno. - */ -xfs_bmbt_rec_t *xfs_bmap_do_search_extents(xfs_bmbt_rec_t *, - xfs_extnum_t, xfs_extnum_t, xfs_fileoff_t, int *, - xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *); - #endif /* __KERNEL__ */ #endif /* __XFS_BMAP_BTREE_H__ */ diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h index f57cc9ac875e..022fff62085b 100644 --- a/fs/xfs/xfs_clnt.h +++ b/fs/xfs/xfs_clnt.h @@ -68,8 +68,6 @@ struct xfs_mount_args { * enforcement */ #define XFSMNT_PQUOTAENF 0x00000040 /* IRIX project quota limit * enforcement */ -#define XFSMNT_NOATIME 0x00000100 /* don't modify access - * times on reads */ #define XFSMNT_NOALIGN 0x00000200 /* don't allocate at * stripe boundaries*/ #define XFSMNT_RETERR 0x00000400 /* return error to user */ diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 473671fa5c13..4bae3a76c678 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -126,10 +126,10 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level, node = bp->data; node->hdr.info.forw = 0; node->hdr.info.back = 0; - INT_SET(node->hdr.info.magic, ARCH_CONVERT, XFS_DA_NODE_MAGIC); + node->hdr.info.magic = cpu_to_be16(XFS_DA_NODE_MAGIC); node->hdr.info.pad = 0; node->hdr.count = 0; - INT_SET(node->hdr.level, ARCH_CONVERT, level); + node->hdr.level = cpu_to_be16(level); xfs_da_log_buf(tp, bp, XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr))); @@ -290,28 +290,28 @@ xfs_da_split(xfs_da_state_t *state) node = oldblk->bp->data; if (node->hdr.info.forw) { - if (INT_GET(node->hdr.info.forw, ARCH_CONVERT) == addblk->blkno) { + if (be32_to_cpu(node->hdr.info.forw) == addblk->blkno) { bp = addblk->bp; } else { ASSERT(state->extravalid); bp = state->extrablk.bp; } node = bp->data; - INT_SET(node->hdr.info.back, ARCH_CONVERT, oldblk->blkno); + node->hdr.info.back = cpu_to_be32(oldblk->blkno); xfs_da_log_buf(state->args->trans, bp, XFS_DA_LOGRANGE(node, &node->hdr.info, sizeof(node->hdr.info))); } node = oldblk->bp->data; - if (INT_GET(node->hdr.info.back, ARCH_CONVERT)) { - if (INT_GET(node->hdr.info.back, ARCH_CONVERT) == addblk->blkno) { + if (node->hdr.info.back) { + if (be32_to_cpu(node->hdr.info.back) == addblk->blkno) { bp = addblk->bp; } else { ASSERT(state->extravalid); bp = state->extrablk.bp; } node = bp->data; - INT_SET(node->hdr.info.forw, ARCH_CONVERT, oldblk->blkno); + node->hdr.info.forw = cpu_to_be32(oldblk->blkno); xfs_da_log_buf(state->args->trans, bp, XFS_DA_LOGRANGE(node, &node->hdr.info, sizeof(node->hdr.info))); @@ -359,14 +359,14 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, ASSERT(bp != NULL); node = bp->data; oldroot = blk1->bp->data; - if (INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) { - size = (int)((char *)&oldroot->btree[INT_GET(oldroot->hdr.count, ARCH_CONVERT)] - + if (be16_to_cpu(oldroot->hdr.info.magic) == XFS_DA_NODE_MAGIC) { + size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - (char *)oldroot); } else { ASSERT(XFS_DIR_IS_V2(mp)); - ASSERT(INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); leaf = (xfs_dir2_leaf_t *)oldroot; - size = (int)((char *)&leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT)] - + size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] - (char *)leaf); } memcpy(node, oldroot, size); @@ -381,18 +381,18 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, error = xfs_da_node_create(args, args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp) ? mp->m_dirleafblk : 0, - INT_GET(node->hdr.level, ARCH_CONVERT) + 1, &bp, args->whichfork); + be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork); if (error) return(error); node = bp->data; - INT_SET(node->btree[0].hashval, ARCH_CONVERT, blk1->hashval); - INT_SET(node->btree[0].before, ARCH_CONVERT, blk1->blkno); - INT_SET(node->btree[1].hashval, ARCH_CONVERT, blk2->hashval); - INT_SET(node->btree[1].before, ARCH_CONVERT, blk2->blkno); - INT_SET(node->hdr.count, ARCH_CONVERT, 2); + node->btree[0].hashval = cpu_to_be32(blk1->hashval); + node->btree[0].before = cpu_to_be32(blk1->blkno); + node->btree[1].hashval = cpu_to_be32(blk2->hashval); + node->btree[1].before = cpu_to_be32(blk2->blkno); + node->hdr.count = cpu_to_be16(2); #ifdef DEBUG - if (INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) { + if (be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC) { ASSERT(blk1->blkno >= mp->m_dirleafblk && blk1->blkno < mp->m_dirfreeblk); ASSERT(blk2->blkno >= mp->m_dirleafblk && @@ -424,7 +424,7 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, int useextra; node = oldblk->bp->data; - ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); /* * With V2 the extra block is data or freespace. @@ -435,7 +435,7 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, /* * Do we have to split the node? */ - if ((INT_GET(node->hdr.count, ARCH_CONVERT) + newcount) > state->node_ents) { + if ((be16_to_cpu(node->hdr.count) + newcount) > state->node_ents) { /* * Allocate a new node, add to the doubly linked chain of * nodes, then move some of our excess entries into it. @@ -472,7 +472,7 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, * If we had double-split op below us, then add the extra block too. */ node = oldblk->bp->data; - if (oldblk->index <= INT_GET(node->hdr.count, ARCH_CONVERT)) { + if (oldblk->index <= be16_to_cpu(node->hdr.count)) { oldblk->index++; xfs_da_node_add(state, oldblk, addblk); if (useextra) { @@ -516,17 +516,17 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * Figure out how many entries need to move, and in which direction. * Swap the nodes around if that makes it simpler. */ - if ((INT_GET(node1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(node2->hdr.count, ARCH_CONVERT) > 0) && - ((INT_GET(node2->btree[ 0 ].hashval, ARCH_CONVERT) < INT_GET(node1->btree[ 0 ].hashval, ARCH_CONVERT)) || - (INT_GET(node2->btree[ INT_GET(node2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) < - INT_GET(node1->btree[ INT_GET(node1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) { + if ((be16_to_cpu(node1->hdr.count) > 0) && (be16_to_cpu(node2->hdr.count) > 0) && + ((be32_to_cpu(node2->btree[0].hashval) < be32_to_cpu(node1->btree[0].hashval)) || + (be32_to_cpu(node2->btree[be16_to_cpu(node2->hdr.count)-1].hashval) < + be32_to_cpu(node1->btree[be16_to_cpu(node1->hdr.count)-1].hashval)))) { tmpnode = node1; node1 = node2; node2 = tmpnode; } - ASSERT(INT_GET(node1->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); - ASSERT(INT_GET(node2->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); - count = (INT_GET(node1->hdr.count, ARCH_CONVERT) - INT_GET(node2->hdr.count, ARCH_CONVERT)) / 2; + ASSERT(be16_to_cpu(node1->hdr.info.magic) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(node2->hdr.info.magic) == XFS_DA_NODE_MAGIC); + count = (be16_to_cpu(node1->hdr.count) - be16_to_cpu(node2->hdr.count)) / 2; if (count == 0) return; tp = state->args->trans; @@ -537,7 +537,7 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Move elements in node2 up to make a hole. */ - if ((tmp = INT_GET(node2->hdr.count, ARCH_CONVERT)) > 0) { + if ((tmp = be16_to_cpu(node2->hdr.count)) > 0) { tmp *= (uint)sizeof(xfs_da_node_entry_t); btree_s = &node2->btree[0]; btree_d = &node2->btree[count]; @@ -548,13 +548,12 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * Move the req'd B-tree elements from high in node1 to * low in node2. */ - INT_MOD(node2->hdr.count, ARCH_CONVERT, count); + be16_add(&node2->hdr.count, count); tmp = count * (uint)sizeof(xfs_da_node_entry_t); - btree_s = &node1->btree[INT_GET(node1->hdr.count, ARCH_CONVERT) - count]; + btree_s = &node1->btree[be16_to_cpu(node1->hdr.count) - count]; btree_d = &node2->btree[0]; memcpy(btree_d, btree_s, tmp); - INT_MOD(node1->hdr.count, ARCH_CONVERT, -(count)); - + be16_add(&node1->hdr.count, -count); } else { /* * Move the req'd B-tree elements from low in node2 to @@ -563,21 +562,21 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, count = -count; tmp = count * (uint)sizeof(xfs_da_node_entry_t); btree_s = &node2->btree[0]; - btree_d = &node1->btree[INT_GET(node1->hdr.count, ARCH_CONVERT)]; + btree_d = &node1->btree[be16_to_cpu(node1->hdr.count)]; memcpy(btree_d, btree_s, tmp); - INT_MOD(node1->hdr.count, ARCH_CONVERT, count); + be16_add(&node1->hdr.count, count); xfs_da_log_buf(tp, blk1->bp, XFS_DA_LOGRANGE(node1, btree_d, tmp)); /* * Move elements in node2 down to fill the hole. */ - tmp = INT_GET(node2->hdr.count, ARCH_CONVERT) - count; + tmp = be16_to_cpu(node2->hdr.count) - count; tmp *= (uint)sizeof(xfs_da_node_entry_t); btree_s = &node2->btree[count]; btree_d = &node2->btree[0]; memmove(btree_d, btree_s, tmp); - INT_MOD(node2->hdr.count, ARCH_CONVERT, -(count)); + be16_add(&node2->hdr.count, -count); } /* @@ -588,7 +587,7 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_da_log_buf(tp, blk2->bp, XFS_DA_LOGRANGE(node2, &node2->hdr, sizeof(node2->hdr) + - sizeof(node2->btree[0]) * INT_GET(node2->hdr.count, ARCH_CONVERT))); + sizeof(node2->btree[0]) * be16_to_cpu(node2->hdr.count))); /* * Record the last hashval from each block for upward propagation. @@ -596,15 +595,15 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, */ node1 = blk1->bp->data; node2 = blk2->bp->data; - blk1->hashval = INT_GET(node1->btree[ INT_GET(node1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); - blk2->hashval = INT_GET(node2->btree[ INT_GET(node2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); + blk1->hashval = be32_to_cpu(node1->btree[be16_to_cpu(node1->hdr.count)-1].hashval); + blk2->hashval = be32_to_cpu(node2->btree[be16_to_cpu(node2->hdr.count)-1].hashval); /* * Adjust the expected index for insertion. */ - if (blk1->index >= INT_GET(node1->hdr.count, ARCH_CONVERT)) { - blk2->index = blk1->index - INT_GET(node1->hdr.count, ARCH_CONVERT); - blk1->index = INT_GET(node1->hdr.count, ARCH_CONVERT) + 1; /* make it invalid */ + if (blk1->index >= be16_to_cpu(node1->hdr.count)) { + blk2->index = blk1->index - be16_to_cpu(node1->hdr.count); + blk1->index = be16_to_cpu(node1->hdr.count) + 1; /* make it invalid */ } } @@ -622,8 +621,8 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, node = oldblk->bp->data; mp = state->mp; - ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); - ASSERT((oldblk->index >= 0) && (oldblk->index <= INT_GET(node->hdr.count, ARCH_CONVERT))); + ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); + ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); ASSERT(newblk->blkno != 0); if (state->args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) ASSERT(newblk->blkno >= mp->m_dirleafblk && @@ -634,22 +633,22 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, */ tmp = 0; btree = &node->btree[ oldblk->index ]; - if (oldblk->index < INT_GET(node->hdr.count, ARCH_CONVERT)) { - tmp = (INT_GET(node->hdr.count, ARCH_CONVERT) - oldblk->index) * (uint)sizeof(*btree); + if (oldblk->index < be16_to_cpu(node->hdr.count)) { + tmp = (be16_to_cpu(node->hdr.count) - oldblk->index) * (uint)sizeof(*btree); memmove(btree + 1, btree, tmp); } - INT_SET(btree->hashval, ARCH_CONVERT, newblk->hashval); - INT_SET(btree->before, ARCH_CONVERT, newblk->blkno); + btree->hashval = cpu_to_be32(newblk->hashval); + btree->before = cpu_to_be32(newblk->blkno); xfs_da_log_buf(state->args->trans, oldblk->bp, XFS_DA_LOGRANGE(node, btree, tmp + sizeof(*btree))); - INT_MOD(node->hdr.count, ARCH_CONVERT, +1); + be16_add(&node->hdr.count, 1); xfs_da_log_buf(state->args->trans, oldblk->bp, XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr))); /* * Copy the last hash value from the oldblk to propagate upwards. */ - oldblk->hashval = INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); + oldblk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1 ].hashval); } /*======================================================================== @@ -768,21 +767,21 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk) ASSERT(args != NULL); ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC); oldroot = root_blk->bp->data; - ASSERT(INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DA_NODE_MAGIC); ASSERT(!oldroot->hdr.info.forw); ASSERT(!oldroot->hdr.info.back); /* * If the root has more than one child, then don't do anything. */ - if (INT_GET(oldroot->hdr.count, ARCH_CONVERT) > 1) + if (be16_to_cpu(oldroot->hdr.count) > 1) return(0); /* * Read in the (only) child block, then copy those bytes into * the root block's buffer and free the original child block. */ - child = INT_GET(oldroot->btree[ 0 ].before, ARCH_CONVERT); + child = be32_to_cpu(oldroot->btree[0].before); ASSERT(child != 0); error = xfs_da_read_buf(args->trans, args->dp, child, -1, &bp, args->whichfork); @@ -790,11 +789,11 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk) return(error); ASSERT(bp != NULL); blkinfo = bp->data; - if (INT_GET(oldroot->hdr.level, ARCH_CONVERT) == 1) { - ASSERT(INT_GET(blkinfo->magic, ARCH_CONVERT) == XFS_DIRX_LEAF_MAGIC(state->mp) || - INT_GET(blkinfo->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC); + if (be16_to_cpu(oldroot->hdr.level) == 1) { + ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || + be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC); } else { - ASSERT(INT_GET(blkinfo->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC); } ASSERT(!blkinfo->forw); ASSERT(!blkinfo->back); @@ -830,9 +829,9 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) */ blk = &state->path.blk[ state->path.active-1 ]; info = blk->bp->data; - ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC); node = (xfs_da_intnode_t *)info; - count = INT_GET(node->hdr.count, ARCH_CONVERT); + count = be16_to_cpu(node->hdr.count); if (count > (state->node_ents >> 1)) { *action = 0; /* blk over 50%, don't try to join */ return(0); /* blk over 50%, don't try to join */ @@ -849,7 +848,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) * Make altpath point to the block we want to keep and * path point to the block we want to drop (this one). */ - forward = info->forw; + forward = (info->forw != 0); memcpy(&state->altpath, &state->path, sizeof(state->path)); error = xfs_da_path_shift(state, &state->altpath, forward, 0, &retval); @@ -871,13 +870,12 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) * to shrink a directory over time. */ /* start with smaller blk num */ - forward = (INT_GET(info->forw, ARCH_CONVERT) - < INT_GET(info->back, ARCH_CONVERT)); + forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); for (i = 0; i < 2; forward = !forward, i++) { if (forward) - blkno = INT_GET(info->forw, ARCH_CONVERT); + blkno = be32_to_cpu(info->forw); else - blkno = INT_GET(info->back, ARCH_CONVERT); + blkno = be32_to_cpu(info->back); if (blkno == 0) continue; error = xfs_da_read_buf(state->args->trans, state->args->dp, @@ -889,10 +887,10 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) node = (xfs_da_intnode_t *)info; count = state->node_ents; count -= state->node_ents >> 2; - count -= INT_GET(node->hdr.count, ARCH_CONVERT); + count -= be16_to_cpu(node->hdr.count); node = bp->data; - ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); - count -= INT_GET(node->hdr.count, ARCH_CONVERT); + ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); + count -= be16_to_cpu(node->hdr.count); xfs_da_brelse(state->args->trans, bp); if (count >= 0) break; /* fits with at least 25% to spare */ @@ -973,16 +971,16 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path) } for (blk--, level--; level >= 0; blk--, level--) { node = blk->bp->data; - ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); btree = &node->btree[ blk->index ]; - if (INT_GET(btree->hashval, ARCH_CONVERT) == lasthash) + if (be32_to_cpu(btree->hashval) == lasthash) break; blk->hashval = lasthash; - INT_SET(btree->hashval, ARCH_CONVERT, lasthash); + btree->hashval = cpu_to_be32(lasthash); xfs_da_log_buf(state->args->trans, blk->bp, XFS_DA_LOGRANGE(node, btree, sizeof(*btree))); - lasthash = INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); + lasthash = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval); } } @@ -997,25 +995,25 @@ xfs_da_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk) int tmp; node = drop_blk->bp->data; - ASSERT(drop_blk->index < INT_GET(node->hdr.count, ARCH_CONVERT)); + ASSERT(drop_blk->index < be16_to_cpu(node->hdr.count)); ASSERT(drop_blk->index >= 0); /* * Copy over the offending entry, or just zero it out. */ btree = &node->btree[drop_blk->index]; - if (drop_blk->index < (INT_GET(node->hdr.count, ARCH_CONVERT)-1)) { - tmp = INT_GET(node->hdr.count, ARCH_CONVERT) - drop_blk->index - 1; + if (drop_blk->index < (be16_to_cpu(node->hdr.count)-1)) { + tmp = be16_to_cpu(node->hdr.count) - drop_blk->index - 1; tmp *= (uint)sizeof(xfs_da_node_entry_t); memmove(btree, btree + 1, tmp); xfs_da_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, btree, tmp)); - btree = &node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ]; + btree = &node->btree[be16_to_cpu(node->hdr.count)-1]; } memset((char *)btree, 0, sizeof(xfs_da_node_entry_t)); xfs_da_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, btree, sizeof(*btree))); - INT_MOD(node->hdr.count, ARCH_CONVERT, -1); + be16_add(&node->hdr.count, -1); xfs_da_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr))); @@ -1023,7 +1021,7 @@ xfs_da_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk) * Copy the last hash value from the block to propagate upwards. */ btree--; - drop_blk->hashval = INT_GET(btree->hashval, ARCH_CONVERT); + drop_blk->hashval = be32_to_cpu(btree->hashval); } /* @@ -1041,40 +1039,40 @@ xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, drop_node = drop_blk->bp->data; save_node = save_blk->bp->data; - ASSERT(INT_GET(drop_node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); - ASSERT(INT_GET(save_node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(drop_node->hdr.info.magic) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(save_node->hdr.info.magic) == XFS_DA_NODE_MAGIC); tp = state->args->trans; /* * If the dying block has lower hashvals, then move all the * elements in the remaining block up to make a hole. */ - if ((INT_GET(drop_node->btree[ 0 ].hashval, ARCH_CONVERT) < INT_GET(save_node->btree[ 0 ].hashval, ARCH_CONVERT)) || - (INT_GET(drop_node->btree[ INT_GET(drop_node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) < - INT_GET(save_node->btree[ INT_GET(save_node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT))) + if ((be32_to_cpu(drop_node->btree[0].hashval) < be32_to_cpu(save_node->btree[ 0 ].hashval)) || + (be32_to_cpu(drop_node->btree[be16_to_cpu(drop_node->hdr.count)-1].hashval) < + be32_to_cpu(save_node->btree[be16_to_cpu(save_node->hdr.count)-1].hashval))) { - btree = &save_node->btree[ INT_GET(drop_node->hdr.count, ARCH_CONVERT) ]; - tmp = INT_GET(save_node->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_da_node_entry_t); + btree = &save_node->btree[be16_to_cpu(drop_node->hdr.count)]; + tmp = be16_to_cpu(save_node->hdr.count) * (uint)sizeof(xfs_da_node_entry_t); memmove(btree, &save_node->btree[0], tmp); btree = &save_node->btree[0]; xfs_da_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, btree, - (INT_GET(save_node->hdr.count, ARCH_CONVERT) + INT_GET(drop_node->hdr.count, ARCH_CONVERT)) * + (be16_to_cpu(save_node->hdr.count) + be16_to_cpu(drop_node->hdr.count)) * sizeof(xfs_da_node_entry_t))); } else { - btree = &save_node->btree[ INT_GET(save_node->hdr.count, ARCH_CONVERT) ]; + btree = &save_node->btree[be16_to_cpu(save_node->hdr.count)]; xfs_da_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, btree, - INT_GET(drop_node->hdr.count, ARCH_CONVERT) * + be16_to_cpu(drop_node->hdr.count) * sizeof(xfs_da_node_entry_t))); } /* * Move all the B-tree elements from drop_blk to save_blk. */ - tmp = INT_GET(drop_node->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_da_node_entry_t); + tmp = be16_to_cpu(drop_node->hdr.count) * (uint)sizeof(xfs_da_node_entry_t); memcpy(btree, &drop_node->btree[0], tmp); - INT_MOD(save_node->hdr.count, ARCH_CONVERT, INT_GET(drop_node->hdr.count, ARCH_CONVERT)); + be16_add(&save_node->hdr.count, be16_to_cpu(drop_node->hdr.count)); xfs_da_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, &save_node->hdr, @@ -1083,7 +1081,7 @@ xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, /* * Save the last hashval in the remaining block for upward propagation. */ - save_blk->hashval = INT_GET(save_node->btree[ INT_GET(save_node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); + save_blk->hashval = be32_to_cpu(save_node->btree[be16_to_cpu(save_node->hdr.count)-1].hashval); } /*======================================================================== @@ -1138,46 +1136,46 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) return(error); } curr = blk->bp->data; - ASSERT(INT_GET(curr->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC || - INT_GET(curr->magic, ARCH_CONVERT) == XFS_DIRX_LEAF_MAGIC(state->mp) || - INT_GET(curr->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC); + ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC || + be16_to_cpu(curr->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || + be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC); /* * Search an intermediate node for a match. */ - blk->magic = INT_GET(curr->magic, ARCH_CONVERT); - if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) { + blk->magic = be16_to_cpu(curr->magic); + if (blk->magic == XFS_DA_NODE_MAGIC) { node = blk->bp->data; - blk->hashval = INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); + blk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval); /* * Binary search. (note: small blocks will skip loop) */ - max = INT_GET(node->hdr.count, ARCH_CONVERT); + max = be16_to_cpu(node->hdr.count); probe = span = max / 2; hashval = args->hashval; for (btree = &node->btree[probe]; span > 4; btree = &node->btree[probe]) { span /= 2; - if (INT_GET(btree->hashval, ARCH_CONVERT) < hashval) + if (be32_to_cpu(btree->hashval) < hashval) probe += span; - else if (INT_GET(btree->hashval, ARCH_CONVERT) > hashval) + else if (be32_to_cpu(btree->hashval) > hashval) probe -= span; else break; } ASSERT((probe >= 0) && (probe < max)); - ASSERT((span <= 4) || (INT_GET(btree->hashval, ARCH_CONVERT) == hashval)); + ASSERT((span <= 4) || (be32_to_cpu(btree->hashval) == hashval)); /* * Since we may have duplicate hashval's, find the first * matching hashval in the node. */ - while ((probe > 0) && (INT_GET(btree->hashval, ARCH_CONVERT) >= hashval)) { + while ((probe > 0) && (be32_to_cpu(btree->hashval) >= hashval)) { btree--; probe--; } - while ((probe < max) && (INT_GET(btree->hashval, ARCH_CONVERT) < hashval)) { + while ((probe < max) && (be32_to_cpu(btree->hashval) < hashval)) { btree++; probe++; } @@ -1187,21 +1185,21 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) */ if (probe == max) { blk->index = max-1; - blkno = INT_GET(node->btree[ max-1 ].before, ARCH_CONVERT); + blkno = be32_to_cpu(node->btree[max-1].before); } else { blk->index = probe; - blkno = INT_GET(btree->before, ARCH_CONVERT); + blkno = be32_to_cpu(btree->before); } } - else if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC) { + else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) { blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); break; } - else if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC) { + else if (be16_to_cpu(curr->magic) == XFS_DIR_LEAF_MAGIC) { blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL); break; } - else if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) { + else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) { blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); break; } @@ -1274,8 +1272,8 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC || old_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || old_blk->magic == XFS_ATTR_LEAF_MAGIC); - ASSERT(old_blk->magic == INT_GET(old_info->magic, ARCH_CONVERT)); - ASSERT(new_blk->magic == INT_GET(new_info->magic, ARCH_CONVERT)); + ASSERT(old_blk->magic == be16_to_cpu(old_info->magic)); + ASSERT(new_blk->magic == be16_to_cpu(new_info->magic)); ASSERT(old_blk->magic == new_blk->magic); switch (old_blk->magic) { @@ -1302,47 +1300,44 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, /* * Link new block in before existing block. */ - INT_SET(new_info->forw, ARCH_CONVERT, old_blk->blkno); - new_info->back = old_info->back; /* INT_: direct copy */ - if (INT_GET(old_info->back, ARCH_CONVERT)) { + new_info->forw = cpu_to_be32(old_blk->blkno); + new_info->back = old_info->back; + if (old_info->back) { error = xfs_da_read_buf(args->trans, args->dp, - INT_GET(old_info->back, - ARCH_CONVERT), -1, &bp, - args->whichfork); + be32_to_cpu(old_info->back), + -1, &bp, args->whichfork); if (error) return(error); ASSERT(bp != NULL); tmp_info = bp->data; - ASSERT(INT_GET(tmp_info->magic, ARCH_CONVERT) == INT_GET(old_info->magic, ARCH_CONVERT)); - ASSERT(INT_GET(tmp_info->forw, ARCH_CONVERT) == old_blk->blkno); - INT_SET(tmp_info->forw, ARCH_CONVERT, new_blk->blkno); + ASSERT(be16_to_cpu(tmp_info->magic) == be16_to_cpu(old_info->magic)); + ASSERT(be32_to_cpu(tmp_info->forw) == old_blk->blkno); + tmp_info->forw = cpu_to_be32(new_blk->blkno); xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1); xfs_da_buf_done(bp); } - INT_SET(old_info->back, ARCH_CONVERT, new_blk->blkno); + old_info->back = cpu_to_be32(new_blk->blkno); } else { /* * Link new block in after existing block. */ - new_info->forw = old_info->forw; /* INT_: direct copy */ - INT_SET(new_info->back, ARCH_CONVERT, old_blk->blkno); - if (INT_GET(old_info->forw, ARCH_CONVERT)) { + new_info->forw = old_info->forw; + new_info->back = cpu_to_be32(old_blk->blkno); + if (old_info->forw) { error = xfs_da_read_buf(args->trans, args->dp, - INT_GET(old_info->forw, ARCH_CONVERT), -1, &bp, - args->whichfork); + be32_to_cpu(old_info->forw), + -1, &bp, args->whichfork); if (error) return(error); ASSERT(bp != NULL); tmp_info = bp->data; - ASSERT(INT_GET(tmp_info->magic, ARCH_CONVERT) - == INT_GET(old_info->magic, ARCH_CONVERT)); - ASSERT(INT_GET(tmp_info->back, ARCH_CONVERT) - == old_blk->blkno); - INT_SET(tmp_info->back, ARCH_CONVERT, new_blk->blkno); + ASSERT(tmp_info->magic == old_info->magic); + ASSERT(be32_to_cpu(tmp_info->back) == old_blk->blkno); + tmp_info->back = cpu_to_be32(new_blk->blkno); xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1); xfs_da_buf_done(bp); } - INT_SET(old_info->forw, ARCH_CONVERT, new_blk->blkno); + old_info->forw = cpu_to_be32(new_blk->blkno); } xfs_da_log_buf(args->trans, old_blk->bp, 0, sizeof(*tmp_info) - 1); @@ -1360,13 +1355,13 @@ xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp) node1 = node1_bp->data; node2 = node2_bp->data; - ASSERT((INT_GET(node1->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) && - (INT_GET(node2->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC)); - if ((INT_GET(node1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(node2->hdr.count, ARCH_CONVERT) > 0) && - ((INT_GET(node2->btree[ 0 ].hashval, ARCH_CONVERT) < - INT_GET(node1->btree[ 0 ].hashval, ARCH_CONVERT)) || - (INT_GET(node2->btree[ INT_GET(node2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) < - INT_GET(node1->btree[ INT_GET(node1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) { + ASSERT((be16_to_cpu(node1->hdr.info.magic) == XFS_DA_NODE_MAGIC) && + (be16_to_cpu(node2->hdr.info.magic) == XFS_DA_NODE_MAGIC)); + if ((be16_to_cpu(node1->hdr.count) > 0) && (be16_to_cpu(node2->hdr.count) > 0) && + ((be32_to_cpu(node2->btree[0].hashval) < + be32_to_cpu(node1->btree[0].hashval)) || + (be32_to_cpu(node2->btree[be16_to_cpu(node2->hdr.count)-1].hashval) < + be32_to_cpu(node1->btree[be16_to_cpu(node1->hdr.count)-1].hashval)))) { return(1); } return(0); @@ -1381,12 +1376,12 @@ xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count) xfs_da_intnode_t *node; node = bp->data; - ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); if (count) - *count = INT_GET(node->hdr.count, ARCH_CONVERT); + *count = be16_to_cpu(node->hdr.count); if (!node->hdr.count) return(0); - return(INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)); + return be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval); } /* @@ -1411,50 +1406,47 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC || save_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || save_blk->magic == XFS_ATTR_LEAF_MAGIC); - ASSERT(save_blk->magic == INT_GET(save_info->magic, ARCH_CONVERT)); - ASSERT(drop_blk->magic == INT_GET(drop_info->magic, ARCH_CONVERT)); + ASSERT(save_blk->magic == be16_to_cpu(save_info->magic)); + ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic)); ASSERT(save_blk->magic == drop_blk->magic); - ASSERT((INT_GET(save_info->forw, ARCH_CONVERT) == drop_blk->blkno) || - (INT_GET(save_info->back, ARCH_CONVERT) == drop_blk->blkno)); - ASSERT((INT_GET(drop_info->forw, ARCH_CONVERT) == save_blk->blkno) || - (INT_GET(drop_info->back, ARCH_CONVERT) == save_blk->blkno)); + ASSERT((be32_to_cpu(save_info->forw) == drop_blk->blkno) || + (be32_to_cpu(save_info->back) == drop_blk->blkno)); + ASSERT((be32_to_cpu(drop_info->forw) == save_blk->blkno) || + (be32_to_cpu(drop_info->back) == save_blk->blkno)); /* * Unlink the leaf block from the doubly linked chain of leaves. */ - if (INT_GET(save_info->back, ARCH_CONVERT) == drop_blk->blkno) { - save_info->back = drop_info->back; /* INT_: direct copy */ - if (INT_GET(drop_info->back, ARCH_CONVERT)) { + if (be32_to_cpu(save_info->back) == drop_blk->blkno) { + save_info->back = drop_info->back; + if (drop_info->back) { error = xfs_da_read_buf(args->trans, args->dp, - INT_GET(drop_info->back, - ARCH_CONVERT), -1, &bp, - args->whichfork); + be32_to_cpu(drop_info->back), + -1, &bp, args->whichfork); if (error) return(error); ASSERT(bp != NULL); tmp_info = bp->data; - ASSERT(INT_GET(tmp_info->magic, ARCH_CONVERT) == INT_GET(save_info->magic, ARCH_CONVERT)); - ASSERT(INT_GET(tmp_info->forw, ARCH_CONVERT) == drop_blk->blkno); - INT_SET(tmp_info->forw, ARCH_CONVERT, save_blk->blkno); + ASSERT(tmp_info->magic == save_info->magic); + ASSERT(be32_to_cpu(tmp_info->forw) == drop_blk->blkno); + tmp_info->forw = cpu_to_be32(save_blk->blkno); xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info) - 1); xfs_da_buf_done(bp); } } else { - save_info->forw = drop_info->forw; /* INT_: direct copy */ - if (INT_GET(drop_info->forw, ARCH_CONVERT)) { + save_info->forw = drop_info->forw; + if (drop_info->forw) { error = xfs_da_read_buf(args->trans, args->dp, - INT_GET(drop_info->forw, ARCH_CONVERT), -1, &bp, - args->whichfork); + be32_to_cpu(drop_info->forw), + -1, &bp, args->whichfork); if (error) return(error); ASSERT(bp != NULL); tmp_info = bp->data; - ASSERT(INT_GET(tmp_info->magic, ARCH_CONVERT) - == INT_GET(save_info->magic, ARCH_CONVERT)); - ASSERT(INT_GET(tmp_info->back, ARCH_CONVERT) - == drop_blk->blkno); - INT_SET(tmp_info->back, ARCH_CONVERT, save_blk->blkno); + ASSERT(tmp_info->magic == save_info->magic); + ASSERT(be32_to_cpu(tmp_info->back) == drop_blk->blkno); + tmp_info->back = cpu_to_be32(save_blk->blkno); xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info) - 1); xfs_da_buf_done(bp); @@ -1497,14 +1489,14 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, for (blk = &path->blk[level]; level >= 0; blk--, level--) { ASSERT(blk->bp != NULL); node = blk->bp->data; - ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); - if (forward && (blk->index < INT_GET(node->hdr.count, ARCH_CONVERT)-1)) { + ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); + if (forward && (blk->index < be16_to_cpu(node->hdr.count)-1)) { blk->index++; - blkno = INT_GET(node->btree[ blk->index ].before, ARCH_CONVERT); + blkno = be32_to_cpu(node->btree[blk->index].before); break; } else if (!forward && (blk->index > 0)) { blk->index--; - blkno = INT_GET(node->btree[ blk->index ].before, ARCH_CONVERT); + blkno = be32_to_cpu(node->btree[blk->index].before); break; } } @@ -1536,18 +1528,18 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, return(error); ASSERT(blk->bp != NULL); info = blk->bp->data; - ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC || - INT_GET(info->magic, ARCH_CONVERT) == XFS_DIRX_LEAF_MAGIC(state->mp) || - INT_GET(info->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC); - blk->magic = INT_GET(info->magic, ARCH_CONVERT); - if (INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) { + ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC || + be16_to_cpu(info->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || + be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC); + blk->magic = be16_to_cpu(info->magic); + if (blk->magic == XFS_DA_NODE_MAGIC) { node = (xfs_da_intnode_t *)info; - blk->hashval = INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); + blk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval); if (forward) blk->index = 0; else - blk->index = INT_GET(node->hdr.count, ARCH_CONVERT)-1; - blkno = INT_GET(node->btree[ blk->index ].before, ARCH_CONVERT); + blk->index = be16_to_cpu(node->hdr.count)-1; + blkno = be32_to_cpu(node->btree[blk->index].before); } else { ASSERT(level == path->active-1); blk->index = 0; @@ -1788,40 +1780,40 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, /* * Get values from the moved block. */ - if (INT_GET(dead_info->magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC) { + if (be16_to_cpu(dead_info->magic) == XFS_DIR_LEAF_MAGIC) { ASSERT(XFS_DIR_IS_V1(mp)); dead_leaf = (xfs_dir_leafblock_t *)dead_info; dead_level = 0; dead_hash = INT_GET(dead_leaf->entries[INT_GET(dead_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT); - } else if (INT_GET(dead_info->magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) { + } else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) { ASSERT(XFS_DIR_IS_V2(mp)); dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; dead_level = 0; - dead_hash = INT_GET(dead_leaf2->ents[INT_GET(dead_leaf2->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT); + dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval); } else { - ASSERT(INT_GET(dead_info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); + ASSERT(be16_to_cpu(dead_info->magic) == XFS_DA_NODE_MAGIC); dead_node = (xfs_da_intnode_t *)dead_info; - dead_level = INT_GET(dead_node->hdr.level, ARCH_CONVERT); - dead_hash = INT_GET(dead_node->btree[INT_GET(dead_node->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT); + dead_level = be16_to_cpu(dead_node->hdr.level); + dead_hash = be32_to_cpu(dead_node->btree[be16_to_cpu(dead_node->hdr.count) - 1].hashval); } sib_buf = par_buf = NULL; /* * If the moved block has a left sibling, fix up the pointers. */ - if ((sib_blkno = INT_GET(dead_info->back, ARCH_CONVERT))) { + if ((sib_blkno = be32_to_cpu(dead_info->back))) { if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w))) goto done; sib_info = sib_buf->data; if (unlikely( - INT_GET(sib_info->forw, ARCH_CONVERT) != last_blkno || - INT_GET(sib_info->magic, ARCH_CONVERT) != INT_GET(dead_info->magic, ARCH_CONVERT))) { + be32_to_cpu(sib_info->forw) != last_blkno || + sib_info->magic != dead_info->magic)) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(2)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } - INT_SET(sib_info->forw, ARCH_CONVERT, dead_blkno); + sib_info->forw = cpu_to_be32(dead_blkno); xfs_da_log_buf(tp, sib_buf, XFS_DA_LOGRANGE(sib_info, &sib_info->forw, sizeof(sib_info->forw))); @@ -1831,20 +1823,19 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, /* * If the moved block has a right sibling, fix up the pointers. */ - if ((sib_blkno = INT_GET(dead_info->forw, ARCH_CONVERT))) { + if ((sib_blkno = be32_to_cpu(dead_info->forw))) { if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w))) goto done; sib_info = sib_buf->data; if (unlikely( - INT_GET(sib_info->back, ARCH_CONVERT) != last_blkno - || INT_GET(sib_info->magic, ARCH_CONVERT) - != INT_GET(dead_info->magic, ARCH_CONVERT))) { + be32_to_cpu(sib_info->back) != last_blkno || + sib_info->magic != dead_info->magic)) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(3)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } - INT_SET(sib_info->back, ARCH_CONVERT, dead_blkno); + sib_info->back = cpu_to_be32(dead_blkno); xfs_da_log_buf(tp, sib_buf, XFS_DA_LOGRANGE(sib_info, &sib_info->back, sizeof(sib_info->back))); @@ -1861,26 +1852,26 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, goto done; par_node = par_buf->data; if (unlikely( - INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC || - (level >= 0 && level != INT_GET(par_node->hdr.level, ARCH_CONVERT) + 1))) { + be16_to_cpu(par_node->hdr.info.magic) != XFS_DA_NODE_MAGIC || + (level >= 0 && level != be16_to_cpu(par_node->hdr.level) + 1))) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } - level = INT_GET(par_node->hdr.level, ARCH_CONVERT); + level = be16_to_cpu(par_node->hdr.level); for (entno = 0; - entno < INT_GET(par_node->hdr.count, ARCH_CONVERT) && - INT_GET(par_node->btree[entno].hashval, ARCH_CONVERT) < dead_hash; + entno < be16_to_cpu(par_node->hdr.count) && + be32_to_cpu(par_node->btree[entno].hashval) < dead_hash; entno++) continue; - if (unlikely(entno == INT_GET(par_node->hdr.count, ARCH_CONVERT))) { + if (unlikely(entno == be16_to_cpu(par_node->hdr.count))) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(5)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } - par_blkno = INT_GET(par_node->btree[entno].before, ARCH_CONVERT); + par_blkno = be32_to_cpu(par_node->btree[entno].before); if (level == dead_level + 1) break; xfs_da_brelse(tp, par_buf); @@ -1892,13 +1883,13 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, */ for (;;) { for (; - entno < INT_GET(par_node->hdr.count, ARCH_CONVERT) && - INT_GET(par_node->btree[entno].before, ARCH_CONVERT) != last_blkno; + entno < be16_to_cpu(par_node->hdr.count) && + be32_to_cpu(par_node->btree[entno].before) != last_blkno; entno++) continue; - if (entno < INT_GET(par_node->hdr.count, ARCH_CONVERT)) + if (entno < be16_to_cpu(par_node->hdr.count)) break; - par_blkno = INT_GET(par_node->hdr.info.forw, ARCH_CONVERT); + par_blkno = be32_to_cpu(par_node->hdr.info.forw); xfs_da_brelse(tp, par_buf); par_buf = NULL; if (unlikely(par_blkno == 0)) { @@ -1911,8 +1902,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, goto done; par_node = par_buf->data; if (unlikely( - INT_GET(par_node->hdr.level, ARCH_CONVERT) != level || - INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC)) { + be16_to_cpu(par_node->hdr.level) != level || + be16_to_cpu(par_node->hdr.info.magic) != XFS_DA_NODE_MAGIC)) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); @@ -1923,7 +1914,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, /* * Update the parent entry pointing to the moved block. */ - INT_SET(par_node->btree[entno].before, ARCH_CONVERT, dead_blkno); + par_node->btree[entno].before = cpu_to_be32(dead_blkno); xfs_da_log_buf(tp, par_buf, XFS_DA_LOGRANGE(par_node, &par_node->btree[entno].before, sizeof(par_node->btree[entno].before))); @@ -2203,8 +2194,8 @@ xfs_da_do_buf( info = rbp->data; data = rbp->data; free = rbp->data; - magic = INT_GET(info->magic, ARCH_CONVERT); - magic1 = INT_GET(data->hdr.magic, ARCH_CONVERT); + magic = be16_to_cpu(info->magic); + magic1 = be32_to_cpu(data->hdr.magic); if (unlikely( XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && (magic != XFS_DIR_LEAF_MAGIC) && @@ -2213,7 +2204,7 @@ xfs_da_do_buf( (magic != XFS_DIR2_LEAFN_MAGIC) && (magic1 != XFS_DIR2_BLOCK_MAGIC) && (magic1 != XFS_DIR2_DATA_MAGIC) && - (INT_GET(free->hdr.magic, ARCH_CONVERT) != XFS_DIR2_FREE_MAGIC), + (be32_to_cpu(free->hdr.magic) != XFS_DIR2_FREE_MAGIC), mp, XFS_ERRTAG_DA_READ_BUF, XFS_RANDOM_DA_READ_BUF))) { xfs_buftrace("DA READ ERROR", rbp->bps[0]); diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index 41352113721a..243a730d5ec8 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h @@ -45,10 +45,10 @@ struct zone; (XFS_DIR_IS_V1(mp) ? XFS_DIR_LEAF_MAGIC : XFS_DIR2_LEAFN_MAGIC) typedef struct xfs_da_blkinfo { - xfs_dablk_t forw; /* previous block in list */ - xfs_dablk_t back; /* following block in list */ - __uint16_t magic; /* validity check on block */ - __uint16_t pad; /* unused */ + __be32 forw; /* previous block in list */ + __be32 back; /* following block in list */ + __be16 magic; /* validity check on block */ + __be16 pad; /* unused */ } xfs_da_blkinfo_t; /* @@ -65,12 +65,12 @@ typedef struct xfs_da_blkinfo { typedef struct xfs_da_intnode { struct xfs_da_node_hdr { /* constant-structure header block */ xfs_da_blkinfo_t info; /* block type, links, etc. */ - __uint16_t count; /* count of active entries */ - __uint16_t level; /* level above leaves (leaf == 0) */ + __be16 count; /* count of active entries */ + __be16 level; /* level above leaves (leaf == 0) */ } hdr; struct xfs_da_node_entry { - xfs_dahash_t hashval; /* hash value for this descendant */ - xfs_dablk_t before; /* Btree block before this key */ + __be32 hashval; /* hash value for this descendant */ + __be32 before; /* Btree block before this key */ } btree[1]; /* variable sized array of keys */ } xfs_da_intnode_t; typedef struct xfs_da_node_hdr xfs_da_node_hdr_t; diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index c6191d00ad27..4968a6358e61 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -83,7 +83,7 @@ xfs_swapext( /* Pull information for the target fd */ if (((fp = fget((int)sxp->sx_fdtarget)) == NULL) || - ((vp = LINVFS_GET_VP(fp->f_dentry->d_inode)) == NULL)) { + ((vp = vn_from_inode(fp->f_dentry->d_inode)) == NULL)) { error = XFS_ERROR(EINVAL); goto error0; } @@ -95,7 +95,7 @@ xfs_swapext( } if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) || - ((tvp = LINVFS_GET_VP(tfp->f_dentry->d_inode)) == NULL)) { + ((tvp = vn_from_inode(tfp->f_dentry->d_inode)) == NULL)) { error = XFS_ERROR(EINVAL); goto error0; } diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c index bb87d2a700a9..9cc702a839a3 100644 --- a/fs/xfs/xfs_dir.c +++ b/fs/xfs/xfs_dir.c @@ -634,7 +634,7 @@ xfs_dir_leaf_removename(xfs_da_args_t *args, int *count, int *totallen) return(retval); ASSERT(bp != NULL); leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); retval = xfs_dir_leaf_lookup_int(bp, args, &index); if (retval == EEXIST) { (void)xfs_dir_leaf_remove(args->trans, bp, index); @@ -912,7 +912,7 @@ xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, return(error); if (bp) leaf = bp->data; - if (bp && INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) { + if (bp && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) { xfs_dir_trace_g_dub("node: block not a leaf", dp, uio, bno); xfs_da_brelse(trans, bp); @@ -949,17 +949,17 @@ xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, if (bp == NULL) return(XFS_ERROR(EFSCORRUPTED)); node = bp->data; - if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) + if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) break; btree = &node->btree[0]; xfs_dir_trace_g_dun("node: node detail", dp, uio, node); - for (i = 0; i < INT_GET(node->hdr.count, ARCH_CONVERT); btree++, i++) { - if (INT_GET(btree->hashval, ARCH_CONVERT) >= cookhash) { - bno = INT_GET(btree->before, ARCH_CONVERT); + for (i = 0; i < be16_to_cpu(node->hdr.count); btree++, i++) { + if (be32_to_cpu(btree->hashval) >= cookhash) { + bno = be32_to_cpu(btree->before); break; } } - if (i == INT_GET(node->hdr.count, ARCH_CONVERT)) { + if (i == be16_to_cpu(node->hdr.count)) { xfs_da_brelse(trans, bp); xfs_dir_trace_g_du("node: hash beyond EOF", dp, uio); @@ -982,7 +982,7 @@ xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, */ for (;;) { leaf = bp->data; - if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC)) { + if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC)) { xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf); xfs_da_brelse(trans, bp); XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)", @@ -990,7 +990,7 @@ xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, return XFS_ERROR(EFSCORRUPTED); } xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf); - if ((nextbno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT))) { + if ((nextbno = be32_to_cpu(leaf->hdr.info.forw))) { nextda = xfs_da_reada_buf(trans, dp, nextbno, XFS_DATA_FORK); } else @@ -1118,21 +1118,20 @@ void xfs_dir_trace_g_dun(char *where, xfs_inode_t *dp, uio_t *uio, xfs_da_intnode_t *node) { - int last = INT_GET(node->hdr.count, ARCH_CONVERT) - 1; + int last = be16_to_cpu(node->hdr.count) - 1; xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUN, where, (void *)dp, (void *)dp->i_mount, (void *)((unsigned long)(uio->uio_offset >> 32)), (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), (void *)(unsigned long)uio->uio_resid, + (void *)(unsigned long)be32_to_cpu(node->hdr.info.forw), (void *)(unsigned long) - INT_GET(node->hdr.info.forw, ARCH_CONVERT), + be16_to_cpu(node->hdr.count), (void *)(unsigned long) - INT_GET(node->hdr.count, ARCH_CONVERT), + be32_to_cpu(node->btree[0].hashval), (void *)(unsigned long) - INT_GET(node->btree[0].hashval, ARCH_CONVERT), - (void *)(unsigned long) - INT_GET(node->btree[last].hashval, ARCH_CONVERT), + be32_to_cpu(node->btree[last].hashval), NULL, NULL, NULL); } @@ -1150,8 +1149,7 @@ xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio, (void *)((unsigned long)(uio->uio_offset >> 32)), (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), (void *)(unsigned long)uio->uio_resid, - (void *)(unsigned long) - INT_GET(leaf->hdr.info.forw, ARCH_CONVERT), + (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw), (void *)(unsigned long) INT_GET(leaf->hdr.count, ARCH_CONVERT), (void *)(unsigned long) diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 3158f5dc431f..7dd364b1e038 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -55,16 +55,16 @@ typedef __uint32_t xfs_dir2_db_t; /* * Byte offset in a directory. */ -typedef xfs_off_t xfs_dir2_off_t; +typedef xfs_off_t xfs_dir2_off_t; /* * For getdents, argument struct for put routines. */ typedef int (*xfs_dir2_put_t)(struct xfs_dir2_put_args *pa); typedef struct xfs_dir2_put_args { - xfs_off_t cook; /* cookie of (next) entry */ + xfs_off_t cook; /* cookie of (next) entry */ xfs_intino_t ino; /* inode number */ - struct xfs_dirent *dbp; /* buffer pointer */ + xfs_dirent_t *dbp; /* buffer pointer */ char *name; /* directory entry name */ int namelen; /* length of name */ int done; /* output: set if value was stored */ @@ -75,18 +75,13 @@ typedef struct xfs_dir2_put_args { /* * Other interfaces used by the rest of the dir v2 code. */ -extern int - xfs_dir2_grow_inode(struct xfs_da_args *args, int space, - xfs_dir2_db_t *dbp); - -extern int - xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *vp); - -extern int - xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *vp); - -extern int - xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, - struct xfs_dabuf *bp); +extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, + xfs_dir2_db_t *dbp); +extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, + int *vp); +extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, + int *vp); +extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, + struct xfs_dabuf *bp); #endif /* __XFS_DIR2_H__ */ diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 31bc99faa704..bd5cee6aa51a 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -81,7 +81,7 @@ xfs_dir2_block_addname( xfs_mount_t *mp; /* filesystem mount point */ int needlog; /* need to log header */ int needscan; /* need to rescan freespace */ - xfs_dir2_data_off_t *tagp; /* pointer to tag value */ + __be16 *tagp; /* pointer to tag value */ xfs_trans_t *tp; /* transaction structure */ xfs_dir2_trace_args("block_addname", args); @@ -100,8 +100,7 @@ xfs_dir2_block_addname( /* * Check the magic number, corrupted if wrong. */ - if (unlikely(INT_GET(block->hdr.magic, ARCH_CONVERT) - != XFS_DIR2_BLOCK_MAGIC)) { + if (unlikely(be32_to_cpu(block->hdr.magic) != XFS_DIR2_BLOCK_MAGIC)) { XFS_CORRUPTION_ERROR("xfs_dir2_block_addname", XFS_ERRLEVEL_LOW, mp, block); xfs_da_brelse(tp, bp); @@ -121,38 +120,38 @@ xfs_dir2_block_addname( /* * Tag just before the first leaf entry. */ - tagp = (xfs_dir2_data_off_t *)blp - 1; + tagp = (__be16 *)blp - 1; /* * Data object just before the first leaf entry. */ - enddup = (xfs_dir2_data_unused_t *)((char *)block + INT_GET(*tagp, ARCH_CONVERT)); + enddup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp)); /* * If it's not free then can't do this add without cleaning up: * the space before the first leaf entry needs to be free so it * can be expanded to hold the pointer to the new entry. */ - if (INT_GET(enddup->freetag, ARCH_CONVERT) != XFS_DIR2_DATA_FREE_TAG) + if (be16_to_cpu(enddup->freetag) != XFS_DIR2_DATA_FREE_TAG) dup = enddup = NULL; /* * Check out the biggest freespace and see if it's the same one. */ else { dup = (xfs_dir2_data_unused_t *) - ((char *)block + INT_GET(bf[0].offset, ARCH_CONVERT)); + ((char *)block + be16_to_cpu(bf[0].offset)); if (dup == enddup) { /* * It is the biggest freespace, is it too small * to hold the new leaf too? */ - if (INT_GET(dup->length, ARCH_CONVERT) < len + (uint)sizeof(*blp)) { + if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) { /* * Yes, we use the second-largest * entry instead if it works. */ - if (INT_GET(bf[1].length, ARCH_CONVERT) >= len) + if (be16_to_cpu(bf[1].length) >= len) dup = (xfs_dir2_data_unused_t *) ((char *)block + - INT_GET(bf[1].offset, ARCH_CONVERT)); + be16_to_cpu(bf[1].offset)); else dup = NULL; } @@ -161,7 +160,7 @@ xfs_dir2_block_addname( * Not the same free entry, * just check its length. */ - if (INT_GET(dup->length, ARCH_CONVERT) < len) { + if (be16_to_cpu(dup->length) < len) { dup = NULL; } } @@ -172,9 +171,9 @@ xfs_dir2_block_addname( * If there are stale entries we'll use one for the leaf. * Is the biggest entry enough to avoid compaction? */ - else if (INT_GET(bf[0].length, ARCH_CONVERT) >= len) { + else if (be16_to_cpu(bf[0].length) >= len) { dup = (xfs_dir2_data_unused_t *) - ((char *)block + INT_GET(bf[0].offset, ARCH_CONVERT)); + ((char *)block + be16_to_cpu(bf[0].offset)); compact = 0; } /* @@ -184,20 +183,20 @@ xfs_dir2_block_addname( /* * Tag just before the first leaf entry. */ - tagp = (xfs_dir2_data_off_t *)blp - 1; + tagp = (__be16 *)blp - 1; /* * Data object just before the first leaf entry. */ - dup = (xfs_dir2_data_unused_t *)((char *)block + INT_GET(*tagp, ARCH_CONVERT)); + dup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp)); /* * If it's not free then the data will go where the * leaf data starts now, if it works at all. */ - if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) { - if (INT_GET(dup->length, ARCH_CONVERT) + (INT_GET(btp->stale, ARCH_CONVERT) - 1) * + if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { + if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len) dup = NULL; - } else if ((INT_GET(btp->stale, ARCH_CONVERT) - 1) * (uint)sizeof(*blp) < len) + } else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len) dup = NULL; else dup = (xfs_dir2_data_unused_t *)blp; @@ -243,11 +242,11 @@ xfs_dir2_block_addname( int fromidx; /* source leaf index */ int toidx; /* target leaf index */ - for (fromidx = toidx = INT_GET(btp->count, ARCH_CONVERT) - 1, + for (fromidx = toidx = be32_to_cpu(btp->count) - 1, highstale = lfloghigh = -1; fromidx >= 0; fromidx--) { - if (INT_GET(blp[fromidx].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) { + if (be32_to_cpu(blp[fromidx].address) == XFS_DIR2_NULL_DATAPTR) { if (highstale == -1) highstale = toidx; else { @@ -260,15 +259,15 @@ xfs_dir2_block_addname( blp[toidx] = blp[fromidx]; toidx--; } - lfloglow = toidx + 1 - (INT_GET(btp->stale, ARCH_CONVERT) - 1); - lfloghigh -= INT_GET(btp->stale, ARCH_CONVERT) - 1; - INT_MOD(btp->count, ARCH_CONVERT, -(INT_GET(btp->stale, ARCH_CONVERT) - 1)); + lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1); + lfloghigh -= be32_to_cpu(btp->stale) - 1; + be32_add(&btp->count, -(be32_to_cpu(btp->stale) - 1)); xfs_dir2_data_make_free(tp, bp, (xfs_dir2_data_aoff_t)((char *)blp - (char *)block), - (xfs_dir2_data_aoff_t)((INT_GET(btp->stale, ARCH_CONVERT) - 1) * sizeof(*blp)), + (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)), &needlog, &needscan); - blp += INT_GET(btp->stale, ARCH_CONVERT) - 1; - INT_SET(btp->stale, ARCH_CONVERT, 1); + blp += be32_to_cpu(btp->stale) - 1; + btp->stale = cpu_to_be32(1); /* * If we now need to rebuild the bestfree map, do so. * This needs to happen before the next call to use_free. @@ -283,23 +282,23 @@ xfs_dir2_block_addname( * Set leaf logging boundaries to impossible state. * For the no-stale case they're set explicitly. */ - else if (INT_GET(btp->stale, ARCH_CONVERT)) { - lfloglow = INT_GET(btp->count, ARCH_CONVERT); + else if (btp->stale) { + lfloglow = be32_to_cpu(btp->count); lfloghigh = -1; } /* * Find the slot that's first lower than our hash value, -1 if none. */ - for (low = 0, high = INT_GET(btp->count, ARCH_CONVERT) - 1; low <= high; ) { + for (low = 0, high = be32_to_cpu(btp->count) - 1; low <= high; ) { mid = (low + high) >> 1; - if ((hash = INT_GET(blp[mid].hashval, ARCH_CONVERT)) == args->hashval) + if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval) break; if (hash < args->hashval) low = mid + 1; else high = mid - 1; } - while (mid >= 0 && INT_GET(blp[mid].hashval, ARCH_CONVERT) >= args->hashval) { + while (mid >= 0 && be32_to_cpu(blp[mid].hashval) >= args->hashval) { mid--; } /* @@ -311,14 +310,14 @@ xfs_dir2_block_addname( */ xfs_dir2_data_use_free(tp, bp, enddup, (xfs_dir2_data_aoff_t) - ((char *)enddup - (char *)block + INT_GET(enddup->length, ARCH_CONVERT) - + ((char *)enddup - (char *)block + be16_to_cpu(enddup->length) - sizeof(*blp)), (xfs_dir2_data_aoff_t)sizeof(*blp), &needlog, &needscan); /* * Update the tail (entry count). */ - INT_MOD(btp->count, ARCH_CONVERT, +1); + be32_add(&btp->count, 1); /* * If we now need to rebuild the bestfree map, do so. * This needs to happen before the next call to use_free. @@ -346,12 +345,12 @@ xfs_dir2_block_addname( else { for (lowstale = mid; lowstale >= 0 && - INT_GET(blp[lowstale].address, ARCH_CONVERT) != XFS_DIR2_NULL_DATAPTR; + be32_to_cpu(blp[lowstale].address) != XFS_DIR2_NULL_DATAPTR; lowstale--) continue; for (highstale = mid + 1; - highstale < INT_GET(btp->count, ARCH_CONVERT) && - INT_GET(blp[highstale].address, ARCH_CONVERT) != XFS_DIR2_NULL_DATAPTR && + highstale < be32_to_cpu(btp->count) && + be32_to_cpu(blp[highstale].address) != XFS_DIR2_NULL_DATAPTR && (lowstale < 0 || mid - lowstale > highstale - mid); highstale++) continue; @@ -359,7 +358,7 @@ xfs_dir2_block_addname( * Move entries toward the low-numbered stale entry. */ if (lowstale >= 0 && - (highstale == INT_GET(btp->count, ARCH_CONVERT) || + (highstale == be32_to_cpu(btp->count) || mid - lowstale <= highstale - mid)) { if (mid - lowstale) memmove(&blp[lowstale], &blp[lowstale + 1], @@ -371,7 +370,7 @@ xfs_dir2_block_addname( * Move entries toward the high-numbered stale entry. */ else { - ASSERT(highstale < INT_GET(btp->count, ARCH_CONVERT)); + ASSERT(highstale < be32_to_cpu(btp->count)); mid++; if (highstale - mid) memmove(&blp[mid + 1], &blp[mid], @@ -379,7 +378,7 @@ xfs_dir2_block_addname( lfloglow = MIN(mid, lfloglow); lfloghigh = MAX(highstale, lfloghigh); } - INT_MOD(btp->stale, ARCH_CONVERT, -1); + be32_add(&btp->stale, -1); } /* * Point to the new data entry. @@ -388,8 +387,9 @@ xfs_dir2_block_addname( /* * Fill in the leaf entry. */ - INT_SET(blp[mid].hashval, ARCH_CONVERT, args->hashval); - INT_SET(blp[mid].address, ARCH_CONVERT, XFS_DIR2_BYTE_TO_DATAPTR(mp, (char *)dep - (char *)block)); + blp[mid].hashval = cpu_to_be32(args->hashval); + blp[mid].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp, + (char *)dep - (char *)block)); xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh); /* * Mark space for the data entry used. @@ -404,7 +404,7 @@ xfs_dir2_block_addname( dep->namelen = args->namelen; memcpy(dep->name, args->name, args->namelen); tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); - INT_SET(*tagp, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dep - (char *)block)); + *tagp = cpu_to_be16((char *)dep - (char *)block); /* * Clean up the bestfree array and log the header, tail, and entry. */ @@ -485,8 +485,8 @@ xfs_dir2_block_getdents( /* * Unused, skip it. */ - if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) { - ptr += INT_GET(dup->length, ARCH_CONVERT); + if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { + ptr += be16_to_cpu(dup->length); continue; } @@ -622,7 +622,7 @@ xfs_dir2_block_lookup( * Get the offset from the leaf entry, to point to the data. */ dep = (xfs_dir2_data_entry_t *) - ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, INT_GET(blp[ent].address, ARCH_CONVERT))); + ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address))); /* * Fill in inode number, release the block. */ @@ -674,10 +674,10 @@ xfs_dir2_block_lookup_int( * Loop doing a binary search for our hash value. * Find our entry, ENOENT if it's not there. */ - for (low = 0, high = INT_GET(btp->count, ARCH_CONVERT) - 1; ; ) { + for (low = 0, high = be32_to_cpu(btp->count) - 1; ; ) { ASSERT(low <= high); mid = (low + high) >> 1; - if ((hash = INT_GET(blp[mid].hashval, ARCH_CONVERT)) == args->hashval) + if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval) break; if (hash < args->hashval) low = mid + 1; @@ -692,7 +692,7 @@ xfs_dir2_block_lookup_int( /* * Back up to the first one with the right hash value. */ - while (mid > 0 && INT_GET(blp[mid - 1].hashval, ARCH_CONVERT) == args->hashval) { + while (mid > 0 && be32_to_cpu(blp[mid - 1].hashval) == args->hashval) { mid--; } /* @@ -700,7 +700,7 @@ xfs_dir2_block_lookup_int( * right hash value looking for our name. */ do { - if ((addr = INT_GET(blp[mid].address, ARCH_CONVERT)) == XFS_DIR2_NULL_DATAPTR) + if ((addr = be32_to_cpu(blp[mid].address)) == XFS_DIR2_NULL_DATAPTR) continue; /* * Get pointer to the entry from the leaf. @@ -717,7 +717,7 @@ xfs_dir2_block_lookup_int( *entno = mid; return 0; } - } while (++mid < INT_GET(btp->count, ARCH_CONVERT) && INT_GET(blp[mid].hashval, ARCH_CONVERT) == hash); + } while (++mid < be32_to_cpu(btp->count) && be32_to_cpu(blp[mid].hashval) == hash); /* * No match, release the buffer and return ENOENT. */ @@ -767,7 +767,7 @@ xfs_dir2_block_removename( * Point to the data entry using the leaf entry. */ dep = (xfs_dir2_data_entry_t *) - ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, INT_GET(blp[ent].address, ARCH_CONVERT))); + ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address))); /* * Mark the data entry's space free. */ @@ -778,12 +778,12 @@ xfs_dir2_block_removename( /* * Fix up the block tail. */ - INT_MOD(btp->stale, ARCH_CONVERT, +1); + be32_add(&btp->stale, 1); xfs_dir2_block_log_tail(tp, bp); /* * Remove the leaf entry by marking it stale. */ - INT_SET(blp[ent].address, ARCH_CONVERT, XFS_DIR2_NULL_DATAPTR); + blp[ent].address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); xfs_dir2_block_log_leaf(tp, bp, ent, ent); /* * Fix up bestfree, log the header if necessary. @@ -843,7 +843,7 @@ xfs_dir2_block_replace( * Point to the data entry we need to change. */ dep = (xfs_dir2_data_entry_t *) - ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, INT_GET(blp[ent].address, ARCH_CONVERT))); + ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address))); ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) != args->inumber); /* * Change the inode number to the new value. @@ -868,8 +868,8 @@ xfs_dir2_block_sort( la = a; lb = b; - return INT_GET(la->hashval, ARCH_CONVERT) < INT_GET(lb->hashval, ARCH_CONVERT) ? -1 : - (INT_GET(la->hashval, ARCH_CONVERT) > INT_GET(lb->hashval, ARCH_CONVERT) ? 1 : 0); + return be32_to_cpu(la->hashval) < be32_to_cpu(lb->hashval) ? -1 : + (be32_to_cpu(la->hashval) > be32_to_cpu(lb->hashval) ? 1 : 0); } /* @@ -881,7 +881,7 @@ xfs_dir2_leaf_to_block( xfs_dabuf_t *lbp, /* leaf buffer */ xfs_dabuf_t *dbp) /* data buffer */ { - xfs_dir2_data_off_t *bestsp; /* leaf bests table */ + __be16 *bestsp; /* leaf bests table */ xfs_dir2_block_t *block; /* block structure */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_inode_t *dp; /* incore directory inode */ @@ -896,7 +896,7 @@ xfs_dir2_leaf_to_block( int needscan; /* need to scan for bestfree */ xfs_dir2_sf_hdr_t sfh; /* shortform header */ int size; /* bytes used */ - xfs_dir2_data_off_t *tagp; /* end of entry (tag) */ + __be16 *tagp; /* end of entry (tag) */ int to; /* block/leaf to index */ xfs_trans_t *tp; /* transaction pointer */ @@ -905,7 +905,7 @@ xfs_dir2_leaf_to_block( tp = args->trans; mp = dp->i_mount; leaf = lbp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC); ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf); /* * If there are data blocks other than the first one, take this @@ -915,11 +915,11 @@ xfs_dir2_leaf_to_block( */ while (dp->i_d.di_size > mp->m_dirblksize) { bestsp = XFS_DIR2_LEAF_BESTS_P(ltp); - if (INT_GET(bestsp[INT_GET(ltp->bestcount, ARCH_CONVERT) - 1], ARCH_CONVERT) == + if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == mp->m_dirblksize - (uint)sizeof(block->hdr)) { if ((error = xfs_dir2_leaf_trim_data(args, lbp, - (xfs_dir2_db_t)(INT_GET(ltp->bestcount, ARCH_CONVERT) - 1)))) + (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1)))) goto out; } else { error = 0; @@ -935,28 +935,29 @@ xfs_dir2_leaf_to_block( goto out; } block = dbp->data; - ASSERT(INT_GET(block->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC); + ASSERT(be32_to_cpu(block->hdr.magic) == XFS_DIR2_DATA_MAGIC); /* * Size of the "leaf" area in the block. */ size = (uint)sizeof(block->tail) + - (uint)sizeof(*lep) * (INT_GET(leaf->hdr.count, ARCH_CONVERT) - INT_GET(leaf->hdr.stale, ARCH_CONVERT)); + (uint)sizeof(*lep) * (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)); /* * Look at the last data entry. */ - tagp = (xfs_dir2_data_off_t *)((char *)block + mp->m_dirblksize) - 1; - dup = (xfs_dir2_data_unused_t *)((char *)block + INT_GET(*tagp, ARCH_CONVERT)); + tagp = (__be16 *)((char *)block + mp->m_dirblksize) - 1; + dup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp)); /* * If it's not free or is too short we can't do it. */ - if (INT_GET(dup->freetag, ARCH_CONVERT) != XFS_DIR2_DATA_FREE_TAG || INT_GET(dup->length, ARCH_CONVERT) < size) { + if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG || + be16_to_cpu(dup->length) < size) { error = 0; goto out; } /* * Start converting it to block form. */ - INT_SET(block->hdr.magic, ARCH_CONVERT, XFS_DIR2_BLOCK_MAGIC); + block->hdr.magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC); needlog = 1; needscan = 0; /* @@ -968,20 +969,20 @@ xfs_dir2_leaf_to_block( * Initialize the block tail. */ btp = XFS_DIR2_BLOCK_TAIL_P(mp, block); - INT_SET(btp->count, ARCH_CONVERT, INT_GET(leaf->hdr.count, ARCH_CONVERT) - INT_GET(leaf->hdr.stale, ARCH_CONVERT)); + btp->count = cpu_to_be32(be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)); btp->stale = 0; xfs_dir2_block_log_tail(tp, dbp); /* * Initialize the block leaf area. We compact out stale entries. */ lep = XFS_DIR2_BLOCK_LEAF_P(btp); - for (from = to = 0; from < INT_GET(leaf->hdr.count, ARCH_CONVERT); from++) { - if (INT_GET(leaf->ents[from].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) { + if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR) continue; lep[to++] = leaf->ents[from]; } - ASSERT(to == INT_GET(btp->count, ARCH_CONVERT)); - xfs_dir2_block_log_leaf(tp, dbp, 0, INT_GET(btp->count, ARCH_CONVERT) - 1); + ASSERT(to == be32_to_cpu(btp->count)); + xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1); /* * Scan the bestfree if we need it and log the data block header. */ @@ -1043,7 +1044,7 @@ xfs_dir2_sf_to_block( int offset; /* target block offset */ xfs_dir2_sf_entry_t *sfep; /* sf entry pointer */ xfs_dir2_sf_t *sfp; /* shortform structure */ - xfs_dir2_data_off_t *tagp; /* end of data entry */ + __be16 *tagp; /* end of data entry */ xfs_trans_t *tp; /* transaction pointer */ xfs_dir2_trace_args("sf_to_block", args); @@ -1095,12 +1096,12 @@ xfs_dir2_sf_to_block( return error; } block = bp->data; - INT_SET(block->hdr.magic, ARCH_CONVERT, XFS_DIR2_BLOCK_MAGIC); + block->hdr.magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC); /* * Compute size of block "tail" area. */ i = (uint)sizeof(*btp) + - (INT_GET(sfp->hdr.count, ARCH_CONVERT) + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t); + (sfp->hdr.count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t); /* * The whole thing is initialized to free by the init routine. * Say we're using the leaf and tail area. @@ -1114,7 +1115,7 @@ xfs_dir2_sf_to_block( * Fill in the tail. */ btp = XFS_DIR2_BLOCK_TAIL_P(mp, block); - INT_SET(btp->count, ARCH_CONVERT, INT_GET(sfp->hdr.count, ARCH_CONVERT) + 2); /* ., .. */ + btp->count = cpu_to_be32(sfp->hdr.count + 2); /* ., .. */ btp->stale = 0; blp = XFS_DIR2_BLOCK_LEAF_P(btp); endoffset = (uint)((char *)blp - (char *)block); @@ -1123,7 +1124,7 @@ xfs_dir2_sf_to_block( */ xfs_dir2_data_use_free(tp, bp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)block), - INT_GET(dup->length, ARCH_CONVERT), &needlog, &needscan); + be16_to_cpu(dup->length), &needlog, &needscan); /* * Create entry for . */ @@ -1133,10 +1134,11 @@ xfs_dir2_sf_to_block( dep->namelen = 1; dep->name[0] = '.'; tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); - INT_SET(*tagp, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dep - (char *)block)); + *tagp = cpu_to_be16((char *)dep - (char *)block); xfs_dir2_data_log_entry(tp, bp, dep); - INT_SET(blp[0].hashval, ARCH_CONVERT, xfs_dir_hash_dot); - INT_SET(blp[0].address, ARCH_CONVERT, XFS_DIR2_BYTE_TO_DATAPTR(mp, (char *)dep - (char *)block)); + blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); + blp[0].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp, + (char *)dep - (char *)block)); /* * Create entry for .. */ @@ -1146,15 +1148,16 @@ xfs_dir2_sf_to_block( dep->namelen = 2; dep->name[0] = dep->name[1] = '.'; tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); - INT_SET(*tagp, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dep - (char *)block)); + *tagp = cpu_to_be16((char *)dep - (char *)block); xfs_dir2_data_log_entry(tp, bp, dep); - INT_SET(blp[1].hashval, ARCH_CONVERT, xfs_dir_hash_dotdot); - INT_SET(blp[1].address, ARCH_CONVERT, XFS_DIR2_BYTE_TO_DATAPTR(mp, (char *)dep - (char *)block)); + blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); + blp[1].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp, + (char *)dep - (char *)block)); offset = XFS_DIR2_DATA_FIRST_OFFSET; /* * Loop over existing entries, stuff them in. */ - if ((i = 0) == INT_GET(sfp->hdr.count, ARCH_CONVERT)) + if ((i = 0) == sfp->hdr.count) sfep = NULL; else sfep = XFS_DIR2_SF_FIRSTENTRY(sfp); @@ -1176,15 +1179,14 @@ xfs_dir2_sf_to_block( if (offset < newoffset) { dup = (xfs_dir2_data_unused_t *) ((char *)block + offset); - INT_SET(dup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG); - INT_SET(dup->length, ARCH_CONVERT, newoffset - offset); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT, - (xfs_dir2_data_off_t) + dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); + dup->length = cpu_to_be16(newoffset - offset); + *XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16( ((char *)dup - (char *)block)); xfs_dir2_data_log_unused(tp, bp, dup); (void)xfs_dir2_data_freeinsert((xfs_dir2_data_t *)block, dup, &dummy); - offset += INT_GET(dup->length, ARCH_CONVERT); + offset += be16_to_cpu(dup->length); continue; } /* @@ -1196,13 +1198,14 @@ xfs_dir2_sf_to_block( dep->namelen = sfep->namelen; memcpy(dep->name, sfep->name, dep->namelen); tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); - INT_SET(*tagp, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dep - (char *)block)); + *tagp = cpu_to_be16((char *)dep - (char *)block); xfs_dir2_data_log_entry(tp, bp, dep); - INT_SET(blp[2 + i].hashval, ARCH_CONVERT, xfs_da_hashname((char *)sfep->name, sfep->namelen)); - INT_SET(blp[2 + i].address, ARCH_CONVERT, XFS_DIR2_BYTE_TO_DATAPTR(mp, + blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname( + (char *)sfep->name, sfep->namelen)); + blp[2 + i].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp, (char *)dep - (char *)block)); offset = (int)((char *)(tagp + 1) - (char *)block); - if (++i == INT_GET(sfp->hdr.count, ARCH_CONVERT)) + if (++i == sfp->hdr.count) sfep = NULL; else sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep); @@ -1212,13 +1215,13 @@ xfs_dir2_sf_to_block( /* * Sort the leaf entries by hash value. */ - xfs_sort(blp, INT_GET(btp->count, ARCH_CONVERT), sizeof(*blp), xfs_dir2_block_sort); + xfs_sort(blp, be32_to_cpu(btp->count), sizeof(*blp), xfs_dir2_block_sort); /* * Log the leaf entry area and tail. * Already logged the header in data_init, ignore needlog. */ ASSERT(needscan == 0); - xfs_dir2_block_log_leaf(tp, bp, 0, INT_GET(btp->count, ARCH_CONVERT) - 1); + xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1); xfs_dir2_block_log_tail(tp, bp); xfs_dir2_data_check(dp, bp); xfs_da_buf_done(bp); diff --git a/fs/xfs/xfs_dir2_block.h b/fs/xfs/xfs_dir2_block.h index a2e5cb98a838..6722effd0b20 100644 --- a/fs/xfs/xfs_dir2_block.h +++ b/fs/xfs/xfs_dir2_block.h @@ -43,8 +43,8 @@ struct xfs_trans; #define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */ typedef struct xfs_dir2_block_tail { - __uint32_t count; /* count of leaf entries */ - __uint32_t stale; /* count of stale lf entries */ + __be32 count; /* count of leaf entries */ + __be32 stale; /* count of stale lf entries */ } xfs_dir2_block_tail_t; /* @@ -75,8 +75,7 @@ xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block) static inline struct xfs_dir2_leaf_entry * xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp) { - return (((struct xfs_dir2_leaf_entry *) - (btp)) - INT_GET((btp)->count, ARCH_CONVERT)); + return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count); } /* diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 5b7c47e2f14a..bb3d03ff002b 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -70,11 +70,11 @@ xfs_dir2_data_check( mp = dp->i_mount; d = bp->data; - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); bf = d->hdr.bestfree; p = (char *)d->u; - if (INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) { + if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) { btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d); lep = XFS_DIR2_BLOCK_LEAF_P(btp); endp = (char *)lep; @@ -96,8 +96,8 @@ xfs_dir2_data_check( ASSERT(!bf[2].offset); freeseen |= 1 << 2; } - ASSERT(INT_GET(bf[0].length, ARCH_CONVERT) >= INT_GET(bf[1].length, ARCH_CONVERT)); - ASSERT(INT_GET(bf[1].length, ARCH_CONVERT) >= INT_GET(bf[2].length, ARCH_CONVERT)); + ASSERT(be16_to_cpu(bf[0].length) >= be16_to_cpu(bf[1].length)); + ASSERT(be16_to_cpu(bf[1].length) >= be16_to_cpu(bf[2].length)); /* * Loop over the data/unused entries. */ @@ -108,18 +108,20 @@ xfs_dir2_data_check( * If we find it, account for that, else make sure it * doesn't need to be there. */ - if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) { + if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { ASSERT(lastfree == 0); - ASSERT(INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT) == + ASSERT(be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)) == (char *)dup - (char *)d); dfp = xfs_dir2_data_freefind(d, dup); if (dfp) { i = (int)(dfp - bf); ASSERT((freeseen & (1 << i)) == 0); freeseen |= 1 << i; - } else - ASSERT(INT_GET(dup->length, ARCH_CONVERT) <= INT_GET(bf[2].length, ARCH_CONVERT)); - p += INT_GET(dup->length, ARCH_CONVERT); + } else { + ASSERT(be16_to_cpu(dup->length) <= + be16_to_cpu(bf[2].length)); + } + p += be16_to_cpu(dup->length); lastfree = 1; continue; } @@ -132,21 +134,21 @@ xfs_dir2_data_check( dep = (xfs_dir2_data_entry_t *)p; ASSERT(dep->namelen != 0); ASSERT(xfs_dir_ino_validate(mp, INT_GET(dep->inumber, ARCH_CONVERT)) == 0); - ASSERT(INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(dep), ARCH_CONVERT) == + ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) == (char *)dep - (char *)d); count++; lastfree = 0; - if (INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) { + if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) { addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, (xfs_dir2_data_aoff_t) ((char *)dep - (char *)d)); hash = xfs_da_hashname((char *)dep->name, dep->namelen); - for (i = 0; i < INT_GET(btp->count, ARCH_CONVERT); i++) { - if (INT_GET(lep[i].address, ARCH_CONVERT) == addr && - INT_GET(lep[i].hashval, ARCH_CONVERT) == hash) + for (i = 0; i < be32_to_cpu(btp->count); i++) { + if (be32_to_cpu(lep[i].address) == addr && + be32_to_cpu(lep[i].hashval) == hash) break; } - ASSERT(i < INT_GET(btp->count, ARCH_CONVERT)); + ASSERT(i < be32_to_cpu(btp->count)); } p += XFS_DIR2_DATA_ENTSIZE(dep->namelen); } @@ -154,15 +156,15 @@ xfs_dir2_data_check( * Need to have seen all the entries and all the bestfree slots. */ ASSERT(freeseen == 7); - if (INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) { - for (i = stale = 0; i < INT_GET(btp->count, ARCH_CONVERT); i++) { - if (INT_GET(lep[i].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) { + for (i = stale = 0; i < be32_to_cpu(btp->count); i++) { + if (be32_to_cpu(lep[i].address) == XFS_DIR2_NULL_DATAPTR) stale++; if (i > 0) - ASSERT(INT_GET(lep[i].hashval, ARCH_CONVERT) >= INT_GET(lep[i - 1].hashval, ARCH_CONVERT)); + ASSERT(be32_to_cpu(lep[i].hashval) >= be32_to_cpu(lep[i - 1].hashval)); } - ASSERT(count == INT_GET(btp->count, ARCH_CONVERT) - INT_GET(btp->stale, ARCH_CONVERT)); - ASSERT(stale == INT_GET(btp->stale, ARCH_CONVERT)); + ASSERT(count == be32_to_cpu(btp->count) - be32_to_cpu(btp->stale)); + ASSERT(stale == be32_to_cpu(btp->stale)); } } #endif @@ -190,8 +192,8 @@ xfs_dir2_data_freefind( * Check order, non-overlapping entries, and if we find the * one we're looking for it has to be exact. */ - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); for (dfp = &d->hdr.bestfree[0], seenzero = matched = 0; dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT]; dfp++) { @@ -201,23 +203,24 @@ xfs_dir2_data_freefind( continue; } ASSERT(seenzero == 0); - if (INT_GET(dfp->offset, ARCH_CONVERT) == off) { + if (be16_to_cpu(dfp->offset) == off) { matched = 1; - ASSERT(INT_GET(dfp->length, ARCH_CONVERT) == INT_GET(dup->length, ARCH_CONVERT)); - } else if (off < INT_GET(dfp->offset, ARCH_CONVERT)) - ASSERT(off + INT_GET(dup->length, ARCH_CONVERT) <= INT_GET(dfp->offset, ARCH_CONVERT)); + ASSERT(dfp->length == dup->length); + } else if (off < be16_to_cpu(dfp->offset)) + ASSERT(off + be16_to_cpu(dup->length) <= be16_to_cpu(dfp->offset)); else - ASSERT(INT_GET(dfp->offset, ARCH_CONVERT) + INT_GET(dfp->length, ARCH_CONVERT) <= off); - ASSERT(matched || INT_GET(dfp->length, ARCH_CONVERT) >= INT_GET(dup->length, ARCH_CONVERT)); + ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off); + ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length)); if (dfp > &d->hdr.bestfree[0]) - ASSERT(INT_GET(dfp[-1].length, ARCH_CONVERT) >= INT_GET(dfp[0].length, ARCH_CONVERT)); + ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length)); } #endif /* * If this is smaller than the smallest bestfree entry, * it can't be there since they're sorted. */ - if (INT_GET(dup->length, ARCH_CONVERT) < INT_GET(d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length, ARCH_CONVERT)) + if (be16_to_cpu(dup->length) < + be16_to_cpu(d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length)) return NULL; /* * Look at the three bestfree entries for our guy. @@ -227,7 +230,7 @@ xfs_dir2_data_freefind( dfp++) { if (!dfp->offset) return NULL; - if (INT_GET(dfp->offset, ARCH_CONVERT) == off) + if (be16_to_cpu(dfp->offset) == off) return dfp; } /* @@ -249,29 +252,29 @@ xfs_dir2_data_freeinsert( xfs_dir2_data_free_t new; /* new bestfree entry */ #ifdef __KERNEL__ - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); #endif dfp = d->hdr.bestfree; - INT_COPY(new.length, dup->length, ARCH_CONVERT); - INT_SET(new.offset, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dup - (char *)d)); + new.length = dup->length; + new.offset = cpu_to_be16((char *)dup - (char *)d); /* * Insert at position 0, 1, or 2; or not at all. */ - if (INT_GET(new.length, ARCH_CONVERT) > INT_GET(dfp[0].length, ARCH_CONVERT)) { + if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) { dfp[2] = dfp[1]; dfp[1] = dfp[0]; dfp[0] = new; *loghead = 1; return &dfp[0]; } - if (INT_GET(new.length, ARCH_CONVERT) > INT_GET(dfp[1].length, ARCH_CONVERT)) { + if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) { dfp[2] = dfp[1]; dfp[1] = new; *loghead = 1; return &dfp[1]; } - if (INT_GET(new.length, ARCH_CONVERT) > INT_GET(dfp[2].length, ARCH_CONVERT)) { + if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) { dfp[2] = new; *loghead = 1; return &dfp[2]; @@ -289,8 +292,8 @@ xfs_dir2_data_freeremove( int *loghead) /* out: log data header */ { #ifdef __KERNEL__ - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); #endif /* * It's the first entry, slide the next 2 up. @@ -334,8 +337,8 @@ xfs_dir2_data_freescan( char *p; /* current entry pointer */ #ifdef __KERNEL__ - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); #endif /* * Start by clearing the table. @@ -348,7 +351,7 @@ xfs_dir2_data_freescan( p = (char *)d->u; if (aendp) endp = aendp; - else if (INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) { + else if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) { btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d); endp = (char *)XFS_DIR2_BLOCK_LEAF_P(btp); } else @@ -361,11 +364,11 @@ xfs_dir2_data_freescan( /* * If it's a free entry, insert it. */ - if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) { + if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { ASSERT((char *)dup - (char *)d == - INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT)); + be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup))); xfs_dir2_data_freeinsert(d, dup, loghead); - p += INT_GET(dup->length, ARCH_CONVERT); + p += be16_to_cpu(dup->length); } /* * For active entries, check their tags and skip them. @@ -373,7 +376,7 @@ xfs_dir2_data_freescan( else { dep = (xfs_dir2_data_entry_t *)p; ASSERT((char *)dep - (char *)d == - INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(dep), ARCH_CONVERT)); + be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep))); p += XFS_DIR2_DATA_ENTSIZE(dep->namelen); } } @@ -415,8 +418,8 @@ xfs_dir2_data_init( * Initialize the header. */ d = bp->data; - INT_SET(d->hdr.magic, ARCH_CONVERT, XFS_DIR2_DATA_MAGIC); - INT_SET(d->hdr.bestfree[0].offset, ARCH_CONVERT, (xfs_dir2_data_off_t)sizeof(d->hdr)); + d->hdr.magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); + d->hdr.bestfree[0].offset = cpu_to_be16(sizeof(d->hdr)); for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) { d->hdr.bestfree[i].length = 0; d->hdr.bestfree[i].offset = 0; @@ -425,13 +428,12 @@ xfs_dir2_data_init( * Set up an unused entry for the block's body. */ dup = &d->u[0].unused; - INT_SET(dup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG); + dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); t=mp->m_dirblksize - (uint)sizeof(d->hdr); - INT_SET(d->hdr.bestfree[0].length, ARCH_CONVERT, t); - INT_SET(dup->length, ARCH_CONVERT, t); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)dup - (char *)d)); + d->hdr.bestfree[0].length = cpu_to_be16(t); + dup->length = cpu_to_be16(t); + *XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16((char *)dup - (char *)d); /* * Log it and return it. */ @@ -453,8 +455,8 @@ xfs_dir2_data_log_entry( xfs_dir2_data_t *d; /* data block pointer */ d = bp->data; - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)d), (uint)((char *)(XFS_DIR2_DATA_ENTRY_TAG_P(dep) + 1) - (char *)d - 1)); @@ -471,8 +473,8 @@ xfs_dir2_data_log_header( xfs_dir2_data_t *d; /* data block pointer */ d = bp->data; - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); xfs_da_log_buf(tp, bp, (uint)((char *)&d->hdr - (char *)d), (uint)(sizeof(d->hdr) - 1)); } @@ -489,8 +491,8 @@ xfs_dir2_data_log_unused( xfs_dir2_data_t *d; /* data block pointer */ d = bp->data; - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); /* * Log the first part of the unused entry. */ @@ -533,12 +535,12 @@ xfs_dir2_data_make_free( /* * Figure out where the end of the data area is. */ - if (INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC) + if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC) endptr = (char *)d + mp->m_dirblksize; else { xfs_dir2_block_tail_t *btp; /* block tail */ - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d); endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp); } @@ -547,11 +549,11 @@ xfs_dir2_data_make_free( * the previous entry and see if it's free. */ if (offset > sizeof(d->hdr)) { - xfs_dir2_data_off_t *tagp; /* tag just before us */ + __be16 *tagp; /* tag just before us */ - tagp = (xfs_dir2_data_off_t *)((char *)d + offset) - 1; - prevdup = (xfs_dir2_data_unused_t *)((char *)d + INT_GET(*tagp, ARCH_CONVERT)); - if (INT_GET(prevdup->freetag, ARCH_CONVERT) != XFS_DIR2_DATA_FREE_TAG) + tagp = (__be16 *)((char *)d + offset) - 1; + prevdup = (xfs_dir2_data_unused_t *)((char *)d + be16_to_cpu(*tagp)); + if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG) prevdup = NULL; } else prevdup = NULL; @@ -562,7 +564,7 @@ xfs_dir2_data_make_free( if ((char *)d + offset + len < endptr) { postdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len); - if (INT_GET(postdup->freetag, ARCH_CONVERT) != XFS_DIR2_DATA_FREE_TAG) + if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG) postdup = NULL; } else postdup = NULL; @@ -586,13 +588,13 @@ xfs_dir2_data_make_free( * since the third bestfree is there, there might be more * entries. */ - needscan = d->hdr.bestfree[2].length; + needscan = (d->hdr.bestfree[2].length != 0); /* * Fix up the new big freespace. */ - INT_MOD(prevdup->length, ARCH_CONVERT, len + INT_GET(postdup->length, ARCH_CONVERT)); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)prevdup - (char *)d)); + be16_add(&prevdup->length, len + be16_to_cpu(postdup->length)); + *XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) = + cpu_to_be16((char *)prevdup - (char *)d); xfs_dir2_data_log_unused(tp, bp, prevdup); if (!needscan) { /* @@ -614,7 +616,7 @@ xfs_dir2_data_make_free( */ dfp = xfs_dir2_data_freeinsert(d, prevdup, needlogp); ASSERT(dfp == &d->hdr.bestfree[0]); - ASSERT(INT_GET(dfp->length, ARCH_CONVERT) == INT_GET(prevdup->length, ARCH_CONVERT)); + ASSERT(dfp->length == prevdup->length); ASSERT(!dfp[1].length); ASSERT(!dfp[2].length); } @@ -624,9 +626,9 @@ xfs_dir2_data_make_free( */ else if (prevdup) { dfp = xfs_dir2_data_freefind(d, prevdup); - INT_MOD(prevdup->length, ARCH_CONVERT, len); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)prevdup - (char *)d)); + be16_add(&prevdup->length, len); + *XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) = + cpu_to_be16((char *)prevdup - (char *)d); xfs_dir2_data_log_unused(tp, bp, prevdup); /* * If the previous entry was in the table, the new entry @@ -640,8 +642,10 @@ xfs_dir2_data_make_free( /* * Otherwise we need a scan if the new entry is big enough. */ - else - needscan = INT_GET(prevdup->length, ARCH_CONVERT) > INT_GET(d->hdr.bestfree[2].length, ARCH_CONVERT); + else { + needscan = be16_to_cpu(prevdup->length) > + be16_to_cpu(d->hdr.bestfree[2].length); + } } /* * The following entry is free, merge with it. @@ -649,10 +653,10 @@ xfs_dir2_data_make_free( else if (postdup) { dfp = xfs_dir2_data_freefind(d, postdup); newdup = (xfs_dir2_data_unused_t *)((char *)d + offset); - INT_SET(newdup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG); - INT_SET(newdup->length, ARCH_CONVERT, len + INT_GET(postdup->length, ARCH_CONVERT)); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)newdup - (char *)d)); + newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); + newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length)); + *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) = + cpu_to_be16((char *)newdup - (char *)d); xfs_dir2_data_log_unused(tp, bp, newdup); /* * If the following entry was in the table, the new entry @@ -666,18 +670,20 @@ xfs_dir2_data_make_free( /* * Otherwise we need a scan if the new entry is big enough. */ - else - needscan = INT_GET(newdup->length, ARCH_CONVERT) > INT_GET(d->hdr.bestfree[2].length, ARCH_CONVERT); + else { + needscan = be16_to_cpu(newdup->length) > + be16_to_cpu(d->hdr.bestfree[2].length); + } } /* * Neither neighbor is free. Make a new entry. */ else { newdup = (xfs_dir2_data_unused_t *)((char *)d + offset); - INT_SET(newdup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG); - INT_SET(newdup->length, ARCH_CONVERT, len); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)newdup - (char *)d)); + newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); + newdup->length = cpu_to_be16(len); + *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) = + cpu_to_be16((char *)newdup - (char *)d); xfs_dir2_data_log_unused(tp, bp, newdup); (void)xfs_dir2_data_freeinsert(d, newdup, needlogp); } @@ -707,18 +713,18 @@ xfs_dir2_data_use_free( int oldlen; /* old unused entry's length */ d = bp->data; - ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC || - INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC); - ASSERT(INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG); + ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC || + be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC); + ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG); ASSERT(offset >= (char *)dup - (char *)d); - ASSERT(offset + len <= (char *)dup + INT_GET(dup->length, ARCH_CONVERT) - (char *)d); - ASSERT((char *)dup - (char *)d == INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT)); + ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)d); + ASSERT((char *)dup - (char *)d == be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup))); /* * Look up the entry in the bestfree table. */ dfp = xfs_dir2_data_freefind(d, dup); - oldlen = INT_GET(dup->length, ARCH_CONVERT); - ASSERT(dfp || oldlen <= INT_GET(d->hdr.bestfree[2].length, ARCH_CONVERT)); + oldlen = be16_to_cpu(dup->length); + ASSERT(dfp || oldlen <= be16_to_cpu(d->hdr.bestfree[2].length)); /* * Check for alignment with front and back of the entry. */ @@ -732,7 +738,7 @@ xfs_dir2_data_use_free( */ if (matchfront && matchback) { if (dfp) { - needscan = d->hdr.bestfree[2].offset; + needscan = (d->hdr.bestfree[2].offset != 0); if (!needscan) xfs_dir2_data_freeremove(d, dfp, needlogp); } @@ -743,10 +749,10 @@ xfs_dir2_data_use_free( */ else if (matchfront) { newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len); - INT_SET(newdup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG); - INT_SET(newdup->length, ARCH_CONVERT, oldlen - len); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)newdup - (char *)d)); + newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); + newdup->length = cpu_to_be16(oldlen - len); + *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) = + cpu_to_be16((char *)newdup - (char *)d); xfs_dir2_data_log_unused(tp, bp, newdup); /* * If it was in the table, remove it and add the new one. @@ -755,8 +761,8 @@ xfs_dir2_data_use_free( xfs_dir2_data_freeremove(d, dfp, needlogp); dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp); ASSERT(dfp != NULL); - ASSERT(INT_GET(dfp->length, ARCH_CONVERT) == INT_GET(newdup->length, ARCH_CONVERT)); - ASSERT(INT_GET(dfp->offset, ARCH_CONVERT) == (char *)newdup - (char *)d); + ASSERT(dfp->length == newdup->length); + ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d); /* * If we got inserted at the last slot, * that means we don't know if there was a better @@ -771,10 +777,9 @@ xfs_dir2_data_use_free( */ else if (matchback) { newdup = dup; - INT_SET(newdup->length, ARCH_CONVERT, (xfs_dir2_data_off_t) - (((char *)d + offset) - (char *)newdup)); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)newdup - (char *)d)); + newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup); + *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) = + cpu_to_be16((char *)newdup - (char *)d); xfs_dir2_data_log_unused(tp, bp, newdup); /* * If it was in the table, remove it and add the new one. @@ -783,8 +788,8 @@ xfs_dir2_data_use_free( xfs_dir2_data_freeremove(d, dfp, needlogp); dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp); ASSERT(dfp != NULL); - ASSERT(INT_GET(dfp->length, ARCH_CONVERT) == INT_GET(newdup->length, ARCH_CONVERT)); - ASSERT(INT_GET(dfp->offset, ARCH_CONVERT) == (char *)newdup - (char *)d); + ASSERT(dfp->length == newdup->length); + ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d); /* * If we got inserted at the last slot, * that means we don't know if there was a better @@ -799,16 +804,15 @@ xfs_dir2_data_use_free( */ else { newdup = dup; - INT_SET(newdup->length, ARCH_CONVERT, (xfs_dir2_data_off_t) - (((char *)d + offset) - (char *)newdup)); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)newdup - (char *)d)); + newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup); + *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) = + cpu_to_be16((char *)newdup - (char *)d); xfs_dir2_data_log_unused(tp, bp, newdup); newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len); - INT_SET(newdup2->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG); - INT_SET(newdup2->length, ARCH_CONVERT, oldlen - len - INT_GET(newdup->length, ARCH_CONVERT)); - INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup2), ARCH_CONVERT, - (xfs_dir2_data_off_t)((char *)newdup2 - (char *)d)); + newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); + newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length)); + *XFS_DIR2_DATA_UNUSED_TAG_P(newdup2) = + cpu_to_be16((char *)newdup2 - (char *)d); xfs_dir2_data_log_unused(tp, bp, newdup2); /* * If the old entry was in the table, we need to scan @@ -819,7 +823,7 @@ xfs_dir2_data_use_free( * the 2 new will work. */ if (dfp) { - needscan = d->hdr.bestfree[2].length; + needscan = (d->hdr.bestfree[2].length != 0); if (!needscan) { xfs_dir2_data_freeremove(d, dfp, needlogp); (void)xfs_dir2_data_freeinsert(d, newdup, diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h index 5e3a7f9ec735..0847cbb53e17 100644 --- a/fs/xfs/xfs_dir2_data.h +++ b/fs/xfs/xfs_dir2_data.h @@ -65,8 +65,8 @@ struct xfs_trans; * The freespace will be formatted as a xfs_dir2_data_unused_t. */ typedef struct xfs_dir2_data_free { - xfs_dir2_data_off_t offset; /* start of freespace */ - xfs_dir2_data_off_t length; /* length of freespace */ + __be16 offset; /* start of freespace */ + __be16 length; /* length of freespace */ } xfs_dir2_data_free_t; /* @@ -75,7 +75,7 @@ typedef struct xfs_dir2_data_free { * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. */ typedef struct xfs_dir2_data_hdr { - __uint32_t magic; /* XFS_DIR2_DATA_MAGIC */ + __be32 magic; /* XFS_DIR2_DATA_MAGIC */ /* or XFS_DIR2_BLOCK_MAGIC */ xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; } xfs_dir2_data_hdr_t; @@ -97,10 +97,10 @@ typedef struct xfs_dir2_data_entry { * Tag appears as the last 2 bytes. */ typedef struct xfs_dir2_data_unused { - __uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */ - xfs_dir2_data_off_t length; /* total free length */ + __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */ + __be16 length; /* total free length */ /* variable offset */ - xfs_dir2_data_off_t tag; /* starting offset of us */ + __be16 tag; /* starting offset of us */ } xfs_dir2_data_unused_t; typedef union { @@ -134,12 +134,11 @@ static inline int xfs_dir2_data_entsize(int n) * Pointer to an entry's tag word. */ #define XFS_DIR2_DATA_ENTRY_TAG_P(dep) xfs_dir2_data_entry_tag_p(dep) -static inline xfs_dir2_data_off_t * +static inline __be16 * xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep) { - return (xfs_dir2_data_off_t *) \ - ((char *)(dep) + XFS_DIR2_DATA_ENTSIZE((dep)->namelen) - \ - (uint)sizeof(xfs_dir2_data_off_t)); + return (__be16 *)((char *)dep + + XFS_DIR2_DATA_ENTSIZE(dep->namelen) - sizeof(__be16)); } /* @@ -147,12 +146,11 @@ xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep) */ #define XFS_DIR2_DATA_UNUSED_TAG_P(dup) \ xfs_dir2_data_unused_tag_p(dup) -static inline xfs_dir2_data_off_t * +static inline __be16 * xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup) { - return (xfs_dir2_data_off_t *) \ - ((char *)(dup) + INT_GET((dup)->length, ARCH_CONVERT) \ - - (uint)sizeof(xfs_dir2_data_off_t)); + return (__be16 *)((char *)dup + + be16_to_cpu(dup->length) - sizeof(__be16)); } /* diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index d342b6b55239..08648b18265c 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -66,7 +66,7 @@ xfs_dir2_block_to_leaf( xfs_da_args_t *args, /* operation arguments */ xfs_dabuf_t *dbp) /* input block's buffer */ { - xfs_dir2_data_off_t *bestsp; /* leaf's bestsp entries */ + __be16 *bestsp; /* leaf's bestsp entries */ xfs_dablk_t blkno; /* leaf block's bno */ xfs_dir2_block_t *block; /* block structure */ xfs_dir2_leaf_entry_t *blp; /* block's leaf entries */ @@ -111,14 +111,14 @@ xfs_dir2_block_to_leaf( /* * Set the counts in the leaf header. */ - INT_COPY(leaf->hdr.count, btp->count, ARCH_CONVERT); /* INT_: type change */ - INT_COPY(leaf->hdr.stale, btp->stale, ARCH_CONVERT); /* INT_: type change */ + leaf->hdr.count = cpu_to_be16(be32_to_cpu(btp->count)); + leaf->hdr.stale = cpu_to_be16(be32_to_cpu(btp->stale)); /* * Could compact these but I think we always do the conversion * after squeezing out stale entries. */ - memcpy(leaf->ents, blp, INT_GET(btp->count, ARCH_CONVERT) * sizeof(xfs_dir2_leaf_entry_t)); - xfs_dir2_leaf_log_ents(tp, lbp, 0, INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1); + memcpy(leaf->ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); + xfs_dir2_leaf_log_ents(tp, lbp, 0, be16_to_cpu(leaf->hdr.count) - 1); needscan = 0; needlog = 1; /* @@ -133,7 +133,7 @@ xfs_dir2_block_to_leaf( /* * Fix up the block header, make it a data block. */ - INT_SET(block->hdr.magic, ARCH_CONVERT, XFS_DIR2_DATA_MAGIC); + block->hdr.magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); if (needscan) xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog, NULL); @@ -141,9 +141,9 @@ xfs_dir2_block_to_leaf( * Set up leaf tail and bests table. */ ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf); - INT_SET(ltp->bestcount, ARCH_CONVERT, 1); + ltp->bestcount = cpu_to_be32(1); bestsp = XFS_DIR2_LEAF_BESTS_P(ltp); - INT_COPY(bestsp[0], block->hdr.bestfree[0].length, ARCH_CONVERT); + bestsp[0] = block->hdr.bestfree[0].length; /* * Log the data header and leaf bests table. */ @@ -163,7 +163,7 @@ int /* error */ xfs_dir2_leaf_addname( xfs_da_args_t *args) /* operation arguments */ { - xfs_dir2_data_off_t *bestsp; /* freespace table in leaf */ + __be16 *bestsp; /* freespace table in leaf */ int compact; /* need to compact leaves */ xfs_dir2_data_t *data; /* data block structure */ xfs_dabuf_t *dbp; /* data block buffer */ @@ -187,7 +187,7 @@ xfs_dir2_leaf_addname( int needbytes; /* leaf block bytes needed */ int needlog; /* need to log data header */ int needscan; /* need to rescan data free */ - xfs_dir2_data_off_t *tagp; /* end of data entry */ + __be16 *tagp; /* end of data entry */ xfs_trans_t *tp; /* transaction pointer */ xfs_dir2_db_t use_block; /* data block number */ @@ -222,14 +222,14 @@ xfs_dir2_leaf_addname( * in a data block, improving the lookup of those entries. */ for (use_block = -1, lep = &leaf->ents[index]; - index < INT_GET(leaf->hdr.count, ARCH_CONVERT) && INT_GET(lep->hashval, ARCH_CONVERT) == args->hashval; + index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; index++, lep++) { - if (INT_GET(lep->address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) continue; - i = XFS_DIR2_DATAPTR_TO_DB(mp, INT_GET(lep->address, ARCH_CONVERT)); - ASSERT(i < INT_GET(ltp->bestcount, ARCH_CONVERT)); - ASSERT(INT_GET(bestsp[i], ARCH_CONVERT) != NULLDATAOFF); - if (INT_GET(bestsp[i], ARCH_CONVERT) >= length) { + i = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address)); + ASSERT(i < be32_to_cpu(ltp->bestcount)); + ASSERT(be16_to_cpu(bestsp[i]) != NULLDATAOFF); + if (be16_to_cpu(bestsp[i]) >= length) { use_block = i; break; } @@ -238,13 +238,13 @@ xfs_dir2_leaf_addname( * Didn't find a block yet, linear search all the data blocks. */ if (use_block == -1) { - for (i = 0; i < INT_GET(ltp->bestcount, ARCH_CONVERT); i++) { + for (i = 0; i < be32_to_cpu(ltp->bestcount); i++) { /* * Remember a block we see that's missing. */ - if (INT_GET(bestsp[i], ARCH_CONVERT) == NULLDATAOFF && use_block == -1) + if (be16_to_cpu(bestsp[i]) == NULLDATAOFF && use_block == -1) use_block = i; - else if (INT_GET(bestsp[i], ARCH_CONVERT) >= length) { + else if (be16_to_cpu(bestsp[i]) >= length) { use_block = i; break; } @@ -260,21 +260,21 @@ xfs_dir2_leaf_addname( * Now kill use_block if it refers to a missing block, so we * can use it as an indication of allocation needed. */ - if (use_block != -1 && INT_GET(bestsp[use_block], ARCH_CONVERT) == NULLDATAOFF) + if (use_block != -1 && be16_to_cpu(bestsp[use_block]) == NULLDATAOFF) use_block = -1; /* * If we don't have enough free bytes but we can make enough * by compacting out stale entries, we'll do that. */ - if ((char *)bestsp - (char *)&leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT)] < needbytes && - INT_GET(leaf->hdr.stale, ARCH_CONVERT) > 1) { + if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < needbytes && + be16_to_cpu(leaf->hdr.stale) > 1) { compact = 1; } /* * Otherwise if we don't have enough free bytes we need to * convert to node form. */ - else if ((char *)bestsp - (char *)&leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT)] < + else if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < needbytes) { /* * Just checking or no space reservation, give up. @@ -330,8 +330,8 @@ xfs_dir2_leaf_addname( * There are stale entries, so we'll need log-low and log-high * impossibly bad values later. */ - else if (INT_GET(leaf->hdr.stale, ARCH_CONVERT)) { - lfloglow = INT_GET(leaf->hdr.count, ARCH_CONVERT); + else if (be16_to_cpu(leaf->hdr.stale)) { + lfloglow = be16_to_cpu(leaf->hdr.count); lfloghigh = -1; } /* @@ -358,13 +358,13 @@ xfs_dir2_leaf_addname( * If we're adding a new data block on the end we need to * extend the bests table. Copy it up one entry. */ - if (use_block >= INT_GET(ltp->bestcount, ARCH_CONVERT)) { + if (use_block >= be32_to_cpu(ltp->bestcount)) { bestsp--; memmove(&bestsp[0], &bestsp[1], - INT_GET(ltp->bestcount, ARCH_CONVERT) * sizeof(bestsp[0])); - INT_MOD(ltp->bestcount, ARCH_CONVERT, +1); + be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0])); + be32_add(<p->bestcount, 1); xfs_dir2_leaf_log_tail(tp, lbp); - xfs_dir2_leaf_log_bests(tp, lbp, 0, INT_GET(ltp->bestcount, ARCH_CONVERT) - 1); + xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); } /* * If we're filling in a previously empty block just log it. @@ -372,7 +372,7 @@ xfs_dir2_leaf_addname( else xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); data = dbp->data; - INT_COPY(bestsp[use_block], data->hdr.bestfree[0].length, ARCH_CONVERT); + bestsp[use_block] = data->hdr.bestfree[0].length; grown = 1; } /* @@ -394,8 +394,8 @@ xfs_dir2_leaf_addname( * Point to the biggest freespace in our data block. */ dup = (xfs_dir2_data_unused_t *) - ((char *)data + INT_GET(data->hdr.bestfree[0].offset, ARCH_CONVERT)); - ASSERT(INT_GET(dup->length, ARCH_CONVERT) >= length); + ((char *)data + be16_to_cpu(data->hdr.bestfree[0].offset)); + ASSERT(be16_to_cpu(dup->length) >= length); needscan = needlog = 0; /* * Mark the initial part of our freespace in use for the new entry. @@ -411,7 +411,7 @@ xfs_dir2_leaf_addname( dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); - INT_SET(*tagp, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dep - (char *)data)); + *tagp = cpu_to_be16((char *)dep - (char *)data); /* * Need to scan fix up the bestfree table. */ @@ -427,8 +427,8 @@ xfs_dir2_leaf_addname( * If the bests table needs to be changed, do it. * Log the change unless we've already done that. */ - if (INT_GET(bestsp[use_block], ARCH_CONVERT) != INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT)) { - INT_COPY(bestsp[use_block], data->hdr.bestfree[0].length, ARCH_CONVERT); + if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(data->hdr.bestfree[0].length)) { + bestsp[use_block] = data->hdr.bestfree[0].length; if (!grown) xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); } @@ -440,15 +440,15 @@ xfs_dir2_leaf_addname( /* * lep is still good as the index leaf entry. */ - if (index < INT_GET(leaf->hdr.count, ARCH_CONVERT)) + if (index < be16_to_cpu(leaf->hdr.count)) memmove(lep + 1, lep, - (INT_GET(leaf->hdr.count, ARCH_CONVERT) - index) * sizeof(*lep)); + (be16_to_cpu(leaf->hdr.count) - index) * sizeof(*lep)); /* * Record low and high logging indices for the leaf. */ lfloglow = index; - lfloghigh = INT_GET(leaf->hdr.count, ARCH_CONVERT); - INT_MOD(leaf->hdr.count, ARCH_CONVERT, +1); + lfloghigh = be16_to_cpu(leaf->hdr.count); + be16_add(&leaf->hdr.count, 1); } /* * There are stale entries. @@ -468,7 +468,7 @@ xfs_dir2_leaf_addname( */ for (lowstale = index - 1; lowstale >= 0 && - INT_GET(leaf->ents[lowstale].address, ARCH_CONVERT) != + be32_to_cpu(leaf->ents[lowstale].address) != XFS_DIR2_NULL_DATAPTR; lowstale--) continue; @@ -478,8 +478,8 @@ xfs_dir2_leaf_addname( * lowstale entry would be better. */ for (highstale = index; - highstale < INT_GET(leaf->hdr.count, ARCH_CONVERT) && - INT_GET(leaf->ents[highstale].address, ARCH_CONVERT) != + highstale < be16_to_cpu(leaf->hdr.count) && + be32_to_cpu(leaf->ents[highstale].address) != XFS_DIR2_NULL_DATAPTR && (lowstale < 0 || index - lowstale - 1 >= highstale - index); @@ -490,10 +490,10 @@ xfs_dir2_leaf_addname( * If the low one is better, use it. */ if (lowstale >= 0 && - (highstale == INT_GET(leaf->hdr.count, ARCH_CONVERT) || + (highstale == be16_to_cpu(leaf->hdr.count) || index - lowstale - 1 < highstale - index)) { ASSERT(index - lowstale - 1 >= 0); - ASSERT(INT_GET(leaf->ents[lowstale].address, ARCH_CONVERT) == + ASSERT(be32_to_cpu(leaf->ents[lowstale].address) == XFS_DIR2_NULL_DATAPTR); /* * Copy entries up to cover the stale entry @@ -512,7 +512,7 @@ xfs_dir2_leaf_addname( */ else { ASSERT(highstale - index >= 0); - ASSERT(INT_GET(leaf->ents[highstale].address, ARCH_CONVERT) == + ASSERT(be32_to_cpu(leaf->ents[highstale].address) == XFS_DIR2_NULL_DATAPTR); /* * Copy entries down to copver the stale entry @@ -526,13 +526,14 @@ xfs_dir2_leaf_addname( lfloglow = MIN(index, lfloglow); lfloghigh = MAX(highstale, lfloghigh); } - INT_MOD(leaf->hdr.stale, ARCH_CONVERT, -1); + be16_add(&leaf->hdr.stale, -1); } /* * Fill in the new leaf entry. */ - INT_SET(lep->hashval, ARCH_CONVERT, args->hashval); - INT_SET(lep->address, ARCH_CONVERT, XFS_DIR2_DB_OFF_TO_DATAPTR(mp, use_block, INT_GET(*tagp, ARCH_CONVERT))); + lep->hashval = cpu_to_be32(args->hashval); + lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp, use_block, + be16_to_cpu(*tagp))); /* * Log the leaf fields and give up the buffers. */ @@ -563,30 +564,30 @@ xfs_dir2_leaf_check( leaf = bp->data; mp = dp->i_mount; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC); /* * This value is not restrictive enough. * Should factor in the size of the bests table as well. * We can deduce a value for that from di_size. */ - ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) <= XFS_DIR2_MAX_LEAF_ENTS(mp)); + ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp)); ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf); /* * Leaves and bests don't overlap. */ - ASSERT((char *)&leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT)] <= + ASSERT((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <= (char *)XFS_DIR2_LEAF_BESTS_P(ltp)); /* * Check hash value order, count stale entries. */ - for (i = stale = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); i++) { - if (i + 1 < INT_GET(leaf->hdr.count, ARCH_CONVERT)) - ASSERT(INT_GET(leaf->ents[i].hashval, ARCH_CONVERT) <= - INT_GET(leaf->ents[i + 1].hashval, ARCH_CONVERT)); - if (INT_GET(leaf->ents[i].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) { + if (i + 1 < be16_to_cpu(leaf->hdr.count)) + ASSERT(be32_to_cpu(leaf->ents[i].hashval) <= + be32_to_cpu(leaf->ents[i + 1].hashval)); + if (be32_to_cpu(leaf->ents[i].address) == XFS_DIR2_NULL_DATAPTR) stale++; } - ASSERT(INT_GET(leaf->hdr.stale, ARCH_CONVERT) == stale); + ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); } #endif /* DEBUG */ @@ -611,8 +612,8 @@ xfs_dir2_leaf_compact( /* * Compress out the stale entries in place. */ - for (from = to = 0, loglow = -1; from < INT_GET(leaf->hdr.count, ARCH_CONVERT); from++) { - if (INT_GET(leaf->ents[from].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + for (from = to = 0, loglow = -1; from < be16_to_cpu(leaf->hdr.count); from++) { + if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR) continue; /* * Only actually copy the entries that are different. @@ -627,8 +628,8 @@ xfs_dir2_leaf_compact( /* * Update and log the header, log the leaf entries. */ - ASSERT(INT_GET(leaf->hdr.stale, ARCH_CONVERT) == from - to); - INT_MOD(leaf->hdr.count, ARCH_CONVERT, -(INT_GET(leaf->hdr.stale, ARCH_CONVERT))); + ASSERT(be16_to_cpu(leaf->hdr.stale) == from - to); + be16_add(&leaf->hdr.count, -(be16_to_cpu(leaf->hdr.stale))); leaf->hdr.stale = 0; xfs_dir2_leaf_log_header(args->trans, bp); if (loglow != -1) @@ -662,14 +663,14 @@ xfs_dir2_leaf_compact_x1( int to; /* destination copy index */ leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.stale, ARCH_CONVERT) > 1); + ASSERT(be16_to_cpu(leaf->hdr.stale) > 1); index = *indexp; /* * Find the first stale entry before our index, if any. */ for (lowstale = index - 1; lowstale >= 0 && - INT_GET(leaf->ents[lowstale].address, ARCH_CONVERT) != XFS_DIR2_NULL_DATAPTR; + be32_to_cpu(leaf->ents[lowstale].address) != XFS_DIR2_NULL_DATAPTR; lowstale--) continue; /* @@ -677,8 +678,8 @@ xfs_dir2_leaf_compact_x1( * Stop if the answer would be worse than lowstale. */ for (highstale = index; - highstale < INT_GET(leaf->hdr.count, ARCH_CONVERT) && - INT_GET(leaf->ents[highstale].address, ARCH_CONVERT) != XFS_DIR2_NULL_DATAPTR && + highstale < be16_to_cpu(leaf->hdr.count) && + be32_to_cpu(leaf->ents[highstale].address) != XFS_DIR2_NULL_DATAPTR && (lowstale < 0 || index - lowstale > highstale - index); highstale++) continue; @@ -686,7 +687,7 @@ xfs_dir2_leaf_compact_x1( * Pick the better of lowstale and highstale. */ if (lowstale >= 0 && - (highstale == INT_GET(leaf->hdr.count, ARCH_CONVERT) || + (highstale == be16_to_cpu(leaf->hdr.count) || index - lowstale <= highstale - index)) keepstale = lowstale; else @@ -695,14 +696,14 @@ xfs_dir2_leaf_compact_x1( * Copy the entries in place, removing all the stale entries * except keepstale. */ - for (from = to = 0; from < INT_GET(leaf->hdr.count, ARCH_CONVERT); from++) { + for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) { /* * Notice the new value of index. */ if (index == from) newindex = to; if (from != keepstale && - INT_GET(leaf->ents[from].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) { + be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR) { if (from == to) *lowlogp = to; continue; @@ -730,8 +731,8 @@ xfs_dir2_leaf_compact_x1( /* * Adjust the leaf header values. */ - INT_MOD(leaf->hdr.count, ARCH_CONVERT, -(from - to)); - INT_SET(leaf->hdr.stale, ARCH_CONVERT, 1); + be16_add(&leaf->hdr.count, -(from - to)); + leaf->hdr.stale = cpu_to_be16(1); /* * Remember the low/high stale value only in the "right" * direction. @@ -739,8 +740,8 @@ xfs_dir2_leaf_compact_x1( if (lowstale >= newindex) lowstale = -1; else - highstale = INT_GET(leaf->hdr.count, ARCH_CONVERT); - *highlogp = INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1; + highstale = be16_to_cpu(leaf->hdr.count); + *highlogp = be16_to_cpu(leaf->hdr.count) - 1; *lowstalep = lowstale; *highstalep = highstale; } @@ -766,7 +767,7 @@ xfs_dir2_leaf_getdents( xfs_dir2_data_entry_t *dep; /* data entry */ xfs_dir2_data_unused_t *dup; /* unused entry */ int eof; /* reached end of directory */ - int error=0; /* error return value */ + int error = 0; /* error return value */ int i; /* temporary loop index */ int j; /* temporary loop index */ int length; /* temporary length value */ @@ -778,8 +779,8 @@ xfs_dir2_leaf_getdents( xfs_mount_t *mp; /* filesystem mount point */ xfs_dir2_off_t newoff; /* new curoff after new blk */ int nmap; /* mappings to ask xfs_bmapi */ - xfs_dir2_put_args_t p; /* formatting arg bundle */ - char *ptr=NULL; /* pointer to current data */ + xfs_dir2_put_args_t *p; /* formatting arg bundle */ + char *ptr = NULL; /* pointer to current data */ int ra_current; /* number of read-ahead blks */ int ra_index; /* *map index for read-ahead */ int ra_offset; /* map entry offset for ra */ @@ -797,9 +798,10 @@ xfs_dir2_leaf_getdents( /* * Setup formatting arguments. */ - p.dbp = dbp; - p.put = put; - p.uio = uio; + p = kmem_alloc(sizeof(*p), KM_SLEEP); + p->dbp = dbp; + p->put = put; + p->uio = uio; /* * Set up to bmap a number of blocks based on the caller's * buffer size, the directory block size, and the filesystem @@ -1046,11 +1048,10 @@ xfs_dir2_leaf_getdents( while ((char *)ptr - (char *)data < byteoff) { dup = (xfs_dir2_data_unused_t *)ptr; - if (INT_GET(dup->freetag, ARCH_CONVERT) + if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { - length = INT_GET(dup->length, - ARCH_CONVERT); + length = be16_to_cpu(dup->length); ptr += length; continue; } @@ -1079,9 +1080,8 @@ xfs_dir2_leaf_getdents( /* * No, it's unused, skip over it. */ - if (INT_GET(dup->freetag, ARCH_CONVERT) - == XFS_DIR2_DATA_FREE_TAG) { - length = INT_GET(dup->length, ARCH_CONVERT); + if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { + length = be16_to_cpu(dup->length); ptr += length; curoff += length; continue; @@ -1092,24 +1092,24 @@ xfs_dir2_leaf_getdents( */ dep = (xfs_dir2_data_entry_t *)ptr; - p.namelen = dep->namelen; + p->namelen = dep->namelen; - length = XFS_DIR2_DATA_ENTSIZE(p.namelen); + length = XFS_DIR2_DATA_ENTSIZE(p->namelen); - p.cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length); + p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length); - p.ino = INT_GET(dep->inumber, ARCH_CONVERT); + p->ino = INT_GET(dep->inumber, ARCH_CONVERT); #if XFS_BIG_INUMS - p.ino += mp->m_inoadd; + p->ino += mp->m_inoadd; #endif - p.name = (char *)dep->name; + p->name = (char *)dep->name; - error = p.put(&p); + error = p->put(p); /* * Won't fit. Return to caller. */ - if (!p.done) { + if (!p->done) { eof = 0; break; } @@ -1129,6 +1129,7 @@ xfs_dir2_leaf_getdents( else uio->uio_offset = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff); kmem_free(map, map_size * sizeof(*map)); + kmem_free(p, sizeof(*p)); if (bp) xfs_da_brelse(tp, bp); return error; @@ -1171,7 +1172,7 @@ xfs_dir2_leaf_init( /* * Initialize the header. */ - INT_SET(leaf->hdr.info.magic, ARCH_CONVERT, magic); + leaf->hdr.info.magic = cpu_to_be16(magic); leaf->hdr.info.forw = 0; leaf->hdr.info.back = 0; leaf->hdr.count = 0; @@ -1201,13 +1202,13 @@ xfs_dir2_leaf_log_bests( int first, /* first entry to log */ int last) /* last entry to log */ { - xfs_dir2_data_off_t *firstb; /* pointer to first entry */ - xfs_dir2_data_off_t *lastb; /* pointer to last entry */ + __be16 *firstb; /* pointer to first entry */ + __be16 *lastb; /* pointer to last entry */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC); ltp = XFS_DIR2_LEAF_TAIL_P(tp->t_mountp, leaf); firstb = XFS_DIR2_LEAF_BESTS_P(ltp) + first; lastb = XFS_DIR2_LEAF_BESTS_P(ltp) + last; @@ -1230,8 +1231,8 @@ xfs_dir2_leaf_log_ents( xfs_dir2_leaf_t *leaf; /* leaf structure */ leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC || - INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC || + be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); firstlep = &leaf->ents[first]; lastlep = &leaf->ents[last]; xfs_da_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), @@ -1249,8 +1250,8 @@ xfs_dir2_leaf_log_header( xfs_dir2_leaf_t *leaf; /* leaf structure */ leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC || - INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC || + be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); xfs_da_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), (uint)(sizeof(leaf->hdr) - 1)); } @@ -1269,7 +1270,7 @@ xfs_dir2_leaf_log_tail( mp = tp->t_mountp; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC); ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf); xfs_da_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf), (uint)(mp->m_dirblksize - 1)); @@ -1314,7 +1315,7 @@ xfs_dir2_leaf_lookup( */ dep = (xfs_dir2_data_entry_t *) ((char *)dbp->data + - XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, INT_GET(lep->address, ARCH_CONVERT))); + XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address))); /* * Return the found inode number. */ @@ -1373,17 +1374,17 @@ xfs_dir2_leaf_lookup_int( * looking to match the name. */ for (lep = &leaf->ents[index], dbp = NULL, curdb = -1; - index < INT_GET(leaf->hdr.count, ARCH_CONVERT) && INT_GET(lep->hashval, ARCH_CONVERT) == args->hashval; + index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; lep++, index++) { /* * Skip over stale leaf entries. */ - if (INT_GET(lep->address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) continue; /* * Get the new data block number. */ - newdb = XFS_DIR2_DATAPTR_TO_DB(mp, INT_GET(lep->address, ARCH_CONVERT)); + newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address)); /* * If it's not the same as the old data block number, * need to pitch the old one and read the new one. @@ -1406,7 +1407,7 @@ xfs_dir2_leaf_lookup_int( */ dep = (xfs_dir2_data_entry_t *) ((char *)dbp->data + - XFS_DIR2_DATAPTR_TO_OFF(mp, INT_GET(lep->address, ARCH_CONVERT))); + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address))); /* * If it matches then return it. */ @@ -1435,7 +1436,7 @@ int /* error */ xfs_dir2_leaf_removename( xfs_da_args_t *args) /* operation arguments */ { - xfs_dir2_data_off_t *bestsp; /* leaf block best freespace */ + __be16 *bestsp; /* leaf block best freespace */ xfs_dir2_data_t *data; /* data block structure */ xfs_dir2_db_t db; /* data block number */ xfs_dabuf_t *dbp; /* data block buffer */ @@ -1471,14 +1472,14 @@ xfs_dir2_leaf_removename( * Point to the leaf entry, use that to point to the data entry. */ lep = &leaf->ents[index]; - db = XFS_DIR2_DATAPTR_TO_DB(mp, INT_GET(lep->address, ARCH_CONVERT)); + db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address)); dep = (xfs_dir2_data_entry_t *) - ((char *)data + XFS_DIR2_DATAPTR_TO_OFF(mp, INT_GET(lep->address, ARCH_CONVERT))); + ((char *)data + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address))); needscan = needlog = 0; - oldbest = INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT); + oldbest = be16_to_cpu(data->hdr.bestfree[0].length); ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf); bestsp = XFS_DIR2_LEAF_BESTS_P(ltp); - ASSERT(INT_GET(bestsp[db], ARCH_CONVERT) == oldbest); + ASSERT(be16_to_cpu(bestsp[db]) == oldbest); /* * Mark the former data entry unused. */ @@ -1488,9 +1489,9 @@ xfs_dir2_leaf_removename( /* * We just mark the leaf entry stale by putting a null in it. */ - INT_MOD(leaf->hdr.stale, ARCH_CONVERT, +1); + be16_add(&leaf->hdr.stale, 1); xfs_dir2_leaf_log_header(tp, lbp); - INT_SET(lep->address, ARCH_CONVERT, XFS_DIR2_NULL_DATAPTR); + lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); xfs_dir2_leaf_log_ents(tp, lbp, index, index); /* * Scan the freespace in the data block again if necessary, @@ -1504,15 +1505,15 @@ xfs_dir2_leaf_removename( * If the longest freespace in the data block has changed, * put the new value in the bests table and log that. */ - if (INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT) != oldbest) { - INT_COPY(bestsp[db], data->hdr.bestfree[0].length, ARCH_CONVERT); + if (be16_to_cpu(data->hdr.bestfree[0].length) != oldbest) { + bestsp[db] = data->hdr.bestfree[0].length; xfs_dir2_leaf_log_bests(tp, lbp, db, db); } xfs_dir2_data_check(dp, dbp); /* * If the data block is now empty then get rid of the data block. */ - if (INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT) == + if (be16_to_cpu(data->hdr.bestfree[0].length) == mp->m_dirblksize - (uint)sizeof(data->hdr)) { ASSERT(db != mp->m_dirdatablk); if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { @@ -1535,12 +1536,12 @@ xfs_dir2_leaf_removename( * If this is the last data block then compact the * bests table by getting rid of entries. */ - if (db == INT_GET(ltp->bestcount, ARCH_CONVERT) - 1) { + if (db == be32_to_cpu(ltp->bestcount) - 1) { /* * Look for the last active entry (i). */ for (i = db - 1; i > 0; i--) { - if (INT_GET(bestsp[i], ARCH_CONVERT) != NULLDATAOFF) + if (be16_to_cpu(bestsp[i]) != NULLDATAOFF) break; } /* @@ -1548,12 +1549,12 @@ xfs_dir2_leaf_removename( * end are removed. */ memmove(&bestsp[db - i], bestsp, - (INT_GET(ltp->bestcount, ARCH_CONVERT) - (db - i)) * sizeof(*bestsp)); - INT_MOD(ltp->bestcount, ARCH_CONVERT, -(db - i)); + (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp)); + be32_add(<p->bestcount, -(db - i)); xfs_dir2_leaf_log_tail(tp, lbp); - xfs_dir2_leaf_log_bests(tp, lbp, 0, INT_GET(ltp->bestcount, ARCH_CONVERT) - 1); + xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); } else - INT_SET(bestsp[db], ARCH_CONVERT, NULLDATAOFF); + bestsp[db] = cpu_to_be16(NULLDATAOFF); } /* * If the data block was not the first one, drop it. @@ -1604,7 +1605,7 @@ xfs_dir2_leaf_replace( */ dep = (xfs_dir2_data_entry_t *) ((char *)dbp->data + - XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, INT_GET(lep->address, ARCH_CONVERT))); + XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address))); ASSERT(args->inumber != INT_GET(dep->inumber, ARCH_CONVERT)); /* * Put the new inode number in, log it. @@ -1645,11 +1646,11 @@ xfs_dir2_leaf_search_hash( * Note, the table cannot be empty, so we have to go through the loop. * Binary search the leaf entries looking for our hash value. */ - for (lep = leaf->ents, low = 0, high = INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1, + for (lep = leaf->ents, low = 0, high = be16_to_cpu(leaf->hdr.count) - 1, hashwant = args->hashval; low <= high; ) { mid = (low + high) >> 1; - if ((hash = INT_GET(lep[mid].hashval, ARCH_CONVERT)) == hashwant) + if ((hash = be32_to_cpu(lep[mid].hashval)) == hashwant) break; if (hash < hashwant) low = mid + 1; @@ -1660,7 +1661,7 @@ xfs_dir2_leaf_search_hash( * Found one, back up through all the equal hash values. */ if (hash == hashwant) { - while (mid > 0 && INT_GET(lep[mid - 1].hashval, ARCH_CONVERT) == hashwant) { + while (mid > 0 && be32_to_cpu(lep[mid - 1].hashval) == hashwant) { mid--; } } @@ -1682,7 +1683,7 @@ xfs_dir2_leaf_trim_data( xfs_dabuf_t *lbp, /* leaf buffer */ xfs_dir2_db_t db) /* data block number */ { - xfs_dir2_data_off_t *bestsp; /* leaf bests table */ + __be16 *bestsp; /* leaf bests table */ #ifdef DEBUG xfs_dir2_data_t *data; /* data block structure */ #endif @@ -1706,7 +1707,7 @@ xfs_dir2_leaf_trim_data( } #ifdef DEBUG data = dbp->data; - ASSERT(INT_GET(data->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC); + ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC); #endif /* this seems to be an error * data is only valid if DEBUG is defined? @@ -1715,9 +1716,9 @@ xfs_dir2_leaf_trim_data( leaf = lbp->data; ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf); - ASSERT(INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT) == + ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) == mp->m_dirblksize - (uint)sizeof(data->hdr)); - ASSERT(db == INT_GET(ltp->bestcount, ARCH_CONVERT) - 1); + ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); /* * Get rid of the data block. */ @@ -1730,10 +1731,10 @@ xfs_dir2_leaf_trim_data( * Eliminate the last bests entry from the table. */ bestsp = XFS_DIR2_LEAF_BESTS_P(ltp); - INT_MOD(ltp->bestcount, ARCH_CONVERT, -1); - memmove(&bestsp[1], &bestsp[0], INT_GET(ltp->bestcount, ARCH_CONVERT) * sizeof(*bestsp)); + be32_add(<p->bestcount, -1); + memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp)); xfs_dir2_leaf_log_tail(tp, lbp); - xfs_dir2_leaf_log_bests(tp, lbp, 0, INT_GET(ltp->bestcount, ARCH_CONVERT) - 1); + xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); return 0; } @@ -1805,7 +1806,7 @@ xfs_dir2_node_to_leaf( return 0; lbp = state->path.blk[0].bp; leaf = lbp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); /* * Read the freespace block. */ @@ -1814,15 +1815,15 @@ xfs_dir2_node_to_leaf( return error; } free = fbp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); ASSERT(!free->hdr.firstdb); /* * Now see if the leafn and free data will fit in a leaf1. * If not, release the buffer and give up. */ if ((uint)sizeof(leaf->hdr) + - (INT_GET(leaf->hdr.count, ARCH_CONVERT) - INT_GET(leaf->hdr.stale, ARCH_CONVERT)) * (uint)sizeof(leaf->ents[0]) + - INT_GET(free->hdr.nvalid, ARCH_CONVERT) * (uint)sizeof(leaf->bests[0]) + + (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)) * (uint)sizeof(leaf->ents[0]) + + be32_to_cpu(free->hdr.nvalid) * (uint)sizeof(leaf->bests[0]) + (uint)sizeof(leaf->tail) > mp->m_dirblksize) { xfs_da_brelse(tp, fbp); @@ -1832,22 +1833,22 @@ xfs_dir2_node_to_leaf( * If the leaf has any stale entries in it, compress them out. * The compact routine will log the header. */ - if (INT_GET(leaf->hdr.stale, ARCH_CONVERT)) + if (be16_to_cpu(leaf->hdr.stale)) xfs_dir2_leaf_compact(args, lbp); else xfs_dir2_leaf_log_header(tp, lbp); - INT_SET(leaf->hdr.info.magic, ARCH_CONVERT, XFS_DIR2_LEAF1_MAGIC); + leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAF1_MAGIC); /* * Set up the leaf tail from the freespace block. */ ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf); - INT_COPY(ltp->bestcount, free->hdr.nvalid, ARCH_CONVERT); + ltp->bestcount = free->hdr.nvalid; /* * Set up the leaf bests table. */ memcpy(XFS_DIR2_LEAF_BESTS_P(ltp), free->bests, - INT_GET(ltp->bestcount, ARCH_CONVERT) * sizeof(leaf->bests[0])); - xfs_dir2_leaf_log_bests(tp, lbp, 0, INT_GET(ltp->bestcount, ARCH_CONVERT) - 1); + be32_to_cpu(ltp->bestcount) * sizeof(leaf->bests[0])); + xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); xfs_dir2_leaf_log_tail(tp, lbp); xfs_dir2_leaf_check(dp, lbp); /* diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h index 1393993d61e9..f57ca1162412 100644 --- a/fs/xfs/xfs_dir2_leaf.h +++ b/fs/xfs/xfs_dir2_leaf.h @@ -46,23 +46,23 @@ typedef __uint32_t xfs_dir2_dataptr_t; */ typedef struct xfs_dir2_leaf_hdr { xfs_da_blkinfo_t info; /* header for da routines */ - __uint16_t count; /* count of entries */ - __uint16_t stale; /* count of stale entries */ + __be16 count; /* count of entries */ + __be16 stale; /* count of stale entries */ } xfs_dir2_leaf_hdr_t; /* * Leaf block entry. */ typedef struct xfs_dir2_leaf_entry { - xfs_dahash_t hashval; /* hash value of name */ - xfs_dir2_dataptr_t address; /* address of data entry */ + __be32 hashval; /* hash value of name */ + __be32 address; /* address of data entry */ } xfs_dir2_leaf_entry_t; /* * Leaf block tail. */ typedef struct xfs_dir2_leaf_tail { - __uint32_t bestcount; + __be32 bestcount; } xfs_dir2_leaf_tail_t; /* @@ -105,11 +105,10 @@ xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp) * Get address of the bests array in the single-leaf block. */ #define XFS_DIR2_LEAF_BESTS_P(ltp) xfs_dir2_leaf_bests_p(ltp) -static inline xfs_dir2_data_off_t * +static inline __be16 * xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp) { - return (xfs_dir2_data_off_t *) - (ltp) - INT_GET((ltp)->bestcount, ARCH_CONVERT); + return (__be16 *)ltp - be32_to_cpu(ltp->bestcount); } /* diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 641f8633d254..af556f16a0c7 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -76,7 +76,7 @@ xfs_dir2_free_log_bests( xfs_dir2_free_t *free; /* freespace structure */ free = bp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); xfs_da_log_buf(tp, bp, (uint)((char *)&free->bests[first] - (char *)free), (uint)((char *)&free->bests[last] - (char *)free + @@ -94,7 +94,7 @@ xfs_dir2_free_log_header( xfs_dir2_free_t *free; /* freespace structure */ free = bp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); xfs_da_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free), (uint)(sizeof(xfs_dir2_free_hdr_t) - 1)); } @@ -114,14 +114,14 @@ xfs_dir2_leaf_to_node( xfs_dabuf_t *fbp; /* freespace buffer */ xfs_dir2_db_t fdb; /* freespace block number */ xfs_dir2_free_t *free; /* freespace structure */ - xfs_dir2_data_off_t *from; /* pointer to freespace entry */ + __be16 *from; /* pointer to freespace entry */ int i; /* leaf freespace index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ xfs_mount_t *mp; /* filesystem mount point */ int n; /* count of live freespc ents */ xfs_dir2_data_off_t off; /* freespace entry value */ - xfs_dir2_data_off_t *to; /* pointer to freespace entry */ + __be16 *to; /* pointer to freespace entry */ xfs_trans_t *tp; /* transaction pointer */ xfs_dir2_trace_args_b("leaf_to_node", args, lbp); @@ -149,28 +149,28 @@ xfs_dir2_leaf_to_node( /* * Initialize the freespace block header. */ - INT_SET(free->hdr.magic, ARCH_CONVERT, XFS_DIR2_FREE_MAGIC); + free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC); free->hdr.firstdb = 0; - ASSERT(INT_GET(ltp->bestcount, ARCH_CONVERT) <= (uint)dp->i_d.di_size / mp->m_dirblksize); - INT_COPY(free->hdr.nvalid, ltp->bestcount, ARCH_CONVERT); + ASSERT(be32_to_cpu(ltp->bestcount) <= (uint)dp->i_d.di_size / mp->m_dirblksize); + free->hdr.nvalid = ltp->bestcount; /* * Copy freespace entries from the leaf block to the new block. * Count active entries. */ for (i = n = 0, from = XFS_DIR2_LEAF_BESTS_P(ltp), to = free->bests; - i < INT_GET(ltp->bestcount, ARCH_CONVERT); i++, from++, to++) { - if ((off = INT_GET(*from, ARCH_CONVERT)) != NULLDATAOFF) + i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { + if ((off = be16_to_cpu(*from)) != NULLDATAOFF) n++; - INT_SET(*to, ARCH_CONVERT, off); + *to = cpu_to_be16(off); } - INT_SET(free->hdr.nused, ARCH_CONVERT, n); - INT_SET(leaf->hdr.info.magic, ARCH_CONVERT, XFS_DIR2_LEAFN_MAGIC); + free->hdr.nused = cpu_to_be32(n); + leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); /* * Log everything. */ xfs_dir2_leaf_log_header(tp, lbp); xfs_dir2_free_log_header(tp, fbp); - xfs_dir2_free_log_bests(tp, fbp, 0, INT_GET(free->hdr.nvalid, ARCH_CONVERT) - 1); + xfs_dir2_free_log_bests(tp, fbp, 0, be32_to_cpu(free->hdr.nvalid) - 1); xfs_da_buf_done(fbp); xfs_dir2_leafn_check(dp, lbp); return 0; @@ -217,15 +217,15 @@ xfs_dir2_leafn_add( * a compact. */ - if (INT_GET(leaf->hdr.count, ARCH_CONVERT) == XFS_DIR2_MAX_LEAF_ENTS(mp)) { + if (be16_to_cpu(leaf->hdr.count) == XFS_DIR2_MAX_LEAF_ENTS(mp)) { if (!leaf->hdr.stale) return XFS_ERROR(ENOSPC); - compact = INT_GET(leaf->hdr.stale, ARCH_CONVERT) > 1; + compact = be16_to_cpu(leaf->hdr.stale) > 1; } else compact = 0; - ASSERT(index == 0 || INT_GET(leaf->ents[index - 1].hashval, ARCH_CONVERT) <= args->hashval); - ASSERT(index == INT_GET(leaf->hdr.count, ARCH_CONVERT) || - INT_GET(leaf->ents[index].hashval, ARCH_CONVERT) >= args->hashval); + ASSERT(index == 0 || be32_to_cpu(leaf->ents[index - 1].hashval) <= args->hashval); + ASSERT(index == be16_to_cpu(leaf->hdr.count) || + be32_to_cpu(leaf->ents[index].hashval) >= args->hashval); if (args->justcheck) return 0; @@ -242,7 +242,7 @@ xfs_dir2_leafn_add( * Set impossible logging indices for this case. */ else if (leaf->hdr.stale) { - lfloglow = INT_GET(leaf->hdr.count, ARCH_CONVERT); + lfloglow = be16_to_cpu(leaf->hdr.count); lfloghigh = -1; } /* @@ -250,12 +250,12 @@ xfs_dir2_leafn_add( */ if (!leaf->hdr.stale) { lep = &leaf->ents[index]; - if (index < INT_GET(leaf->hdr.count, ARCH_CONVERT)) + if (index < be16_to_cpu(leaf->hdr.count)) memmove(lep + 1, lep, - (INT_GET(leaf->hdr.count, ARCH_CONVERT) - index) * sizeof(*lep)); + (be16_to_cpu(leaf->hdr.count) - index) * sizeof(*lep)); lfloglow = index; - lfloghigh = INT_GET(leaf->hdr.count, ARCH_CONVERT); - INT_MOD(leaf->hdr.count, ARCH_CONVERT, +1); + lfloghigh = be16_to_cpu(leaf->hdr.count); + be16_add(&leaf->hdr.count, 1); } /* * There are stale entries. We'll use one for the new entry. @@ -271,7 +271,7 @@ xfs_dir2_leafn_add( */ for (lowstale = index - 1; lowstale >= 0 && - INT_GET(leaf->ents[lowstale].address, ARCH_CONVERT) != + be32_to_cpu(leaf->ents[lowstale].address) != XFS_DIR2_NULL_DATAPTR; lowstale--) continue; @@ -281,8 +281,8 @@ xfs_dir2_leafn_add( * lowstale already found. */ for (highstale = index; - highstale < INT_GET(leaf->hdr.count, ARCH_CONVERT) && - INT_GET(leaf->ents[highstale].address, ARCH_CONVERT) != + highstale < be16_to_cpu(leaf->hdr.count) && + be32_to_cpu(leaf->ents[highstale].address) != XFS_DIR2_NULL_DATAPTR && (lowstale < 0 || index - lowstale - 1 >= highstale - index); @@ -294,9 +294,9 @@ xfs_dir2_leafn_add( * Shift entries up toward the stale slot. */ if (lowstale >= 0 && - (highstale == INT_GET(leaf->hdr.count, ARCH_CONVERT) || + (highstale == be16_to_cpu(leaf->hdr.count) || index - lowstale - 1 < highstale - index)) { - ASSERT(INT_GET(leaf->ents[lowstale].address, ARCH_CONVERT) == + ASSERT(be32_to_cpu(leaf->ents[lowstale].address) == XFS_DIR2_NULL_DATAPTR); ASSERT(index - lowstale - 1 >= 0); if (index - lowstale - 1 > 0) @@ -312,7 +312,7 @@ xfs_dir2_leafn_add( * Shift entries down toward the stale slot. */ else { - ASSERT(INT_GET(leaf->ents[highstale].address, ARCH_CONVERT) == + ASSERT(be32_to_cpu(leaf->ents[highstale].address) == XFS_DIR2_NULL_DATAPTR); ASSERT(highstale - index >= 0); if (highstale - index > 0) @@ -323,13 +323,14 @@ xfs_dir2_leafn_add( lfloglow = MIN(index, lfloglow); lfloghigh = MAX(highstale, lfloghigh); } - INT_MOD(leaf->hdr.stale, ARCH_CONVERT, -1); + be16_add(&leaf->hdr.stale, -1); } /* * Insert the new entry, log everything. */ - INT_SET(lep->hashval, ARCH_CONVERT, args->hashval); - INT_SET(lep->address, ARCH_CONVERT, XFS_DIR2_DB_OFF_TO_DATAPTR(mp, args->blkno, args->index)); + lep->hashval = cpu_to_be32(args->hashval); + lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp, + args->blkno, args->index)); xfs_dir2_leaf_log_header(tp, bp); xfs_dir2_leaf_log_ents(tp, bp, lfloglow, lfloghigh); xfs_dir2_leafn_check(dp, bp); @@ -352,17 +353,17 @@ xfs_dir2_leafn_check( leaf = bp->data; mp = dp->i_mount; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); - ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) <= XFS_DIR2_MAX_LEAF_ENTS(mp)); - for (i = stale = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); i++) { - if (i + 1 < INT_GET(leaf->hdr.count, ARCH_CONVERT)) { - ASSERT(INT_GET(leaf->ents[i].hashval, ARCH_CONVERT) <= - INT_GET(leaf->ents[i + 1].hashval, ARCH_CONVERT)); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp)); + for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) { + if (i + 1 < be16_to_cpu(leaf->hdr.count)) { + ASSERT(be32_to_cpu(leaf->ents[i].hashval) <= + be32_to_cpu(leaf->ents[i + 1].hashval)); } - if (INT_GET(leaf->ents[i].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + if (be32_to_cpu(leaf->ents[i].address) == XFS_DIR2_NULL_DATAPTR) stale++; } - ASSERT(INT_GET(leaf->hdr.stale, ARCH_CONVERT) == stale); + ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); } #endif /* DEBUG */ @@ -378,12 +379,12 @@ xfs_dir2_leafn_lasthash( xfs_dir2_leaf_t *leaf; /* leaf structure */ leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); if (count) - *count = INT_GET(leaf->hdr.count, ARCH_CONVERT); + *count = be16_to_cpu(leaf->hdr.count); if (!leaf->hdr.count) return 0; - return INT_GET(leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT); + return be32_to_cpu(leaf->ents[be16_to_cpu(leaf->hdr.count) - 1].hashval); } /* @@ -419,9 +420,9 @@ xfs_dir2_leafn_lookup_int( tp = args->trans; mp = dp->i_mount; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); #ifdef __KERNEL__ - ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) > 0); + ASSERT(be16_to_cpu(leaf->hdr.count) > 0); #endif xfs_dir2_leafn_check(dp, bp); /* @@ -443,7 +444,7 @@ xfs_dir2_leafn_lookup_int( curdb = -1; length = XFS_DIR2_DATA_ENTSIZE(args->namelen); if ((free = (curbp ? curbp->data : NULL))) - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); } /* * For others, it's a data block buffer, get the block number. @@ -456,17 +457,17 @@ xfs_dir2_leafn_lookup_int( * Loop over leaf entries with the right hash value. */ for (lep = &leaf->ents[index]; - index < INT_GET(leaf->hdr.count, ARCH_CONVERT) && INT_GET(lep->hashval, ARCH_CONVERT) == args->hashval; + index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; lep++, index++) { /* * Skip stale leaf entries. */ - if (INT_GET(lep->address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) continue; /* * Pull the data block number from the entry. */ - newdb = XFS_DIR2_DATAPTR_TO_DB(mp, INT_GET(lep->address, ARCH_CONVERT)); + newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address)); /* * For addname, we're looking for a place to put the new entry. * We want to use a data block with an entry of equal @@ -506,15 +507,15 @@ xfs_dir2_leafn_lookup_int( } curfdb = newfdb; free = curbp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); - ASSERT((INT_GET(free->hdr.firstdb, ARCH_CONVERT) % + ASSERT((be32_to_cpu(free->hdr.firstdb) % XFS_DIR2_MAX_FREE_BESTS(mp)) == 0); - ASSERT(INT_GET(free->hdr.firstdb, ARCH_CONVERT) <= curdb); + ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb); ASSERT(curdb < - INT_GET(free->hdr.firstdb, ARCH_CONVERT) + - INT_GET(free->hdr.nvalid, ARCH_CONVERT)); + be32_to_cpu(free->hdr.firstdb) + + be32_to_cpu(free->hdr.nvalid)); } /* * Get the index for our entry. @@ -523,12 +524,12 @@ xfs_dir2_leafn_lookup_int( /* * If it has room, return it. */ - if (unlikely(INT_GET(free->bests[fi], ARCH_CONVERT) == NULLDATAOFF)) { + if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) { XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } - if (INT_GET(free->bests[fi], ARCH_CONVERT) >= length) { + if (be16_to_cpu(free->bests[fi]) >= length) { *indexp = index; state->extravalid = 1; state->extrablk.bp = curbp; @@ -572,7 +573,7 @@ xfs_dir2_leafn_lookup_int( */ dep = (xfs_dir2_data_entry_t *) ((char *)curbp->data + - XFS_DIR2_DATAPTR_TO_OFF(mp, INT_GET(lep->address, ARCH_CONVERT))); + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address))); /* * Compare the entry, return it if it matches. */ @@ -619,7 +620,7 @@ xfs_dir2_leafn_lookup_int( * Return the final index, that will be the insertion point. */ *indexp = index; - ASSERT(index == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent); + ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent); return XFS_ERROR(ENOENT); } @@ -657,12 +658,12 @@ xfs_dir2_leafn_moveents( * destination leaf entries, open up a hole in the destination * to hold the new entries. */ - if (start_d < INT_GET(leaf_d->hdr.count, ARCH_CONVERT)) { + if (start_d < be16_to_cpu(leaf_d->hdr.count)) { memmove(&leaf_d->ents[start_d + count], &leaf_d->ents[start_d], - (INT_GET(leaf_d->hdr.count, ARCH_CONVERT) - start_d) * + (be16_to_cpu(leaf_d->hdr.count) - start_d) * sizeof(xfs_dir2_leaf_entry_t)); xfs_dir2_leaf_log_ents(tp, bp_d, start_d + count, - count + INT_GET(leaf_d->hdr.count, ARCH_CONVERT) - 1); + count + be16_to_cpu(leaf_d->hdr.count) - 1); } /* * If the source has stale leaves, count the ones in the copy range @@ -672,7 +673,7 @@ xfs_dir2_leafn_moveents( int i; /* temp leaf index */ for (i = start_s, stale = 0; i < start_s + count; i++) { - if (INT_GET(leaf_s->ents[i].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) + if (be32_to_cpu(leaf_s->ents[i].address) == XFS_DIR2_NULL_DATAPTR) stale++; } } else @@ -687,7 +688,7 @@ xfs_dir2_leafn_moveents( * If there are source entries after the ones we copied, * delete the ones we copied by sliding the next ones down. */ - if (start_s + count < INT_GET(leaf_s->hdr.count, ARCH_CONVERT)) { + if (start_s + count < be16_to_cpu(leaf_s->hdr.count)) { memmove(&leaf_s->ents[start_s], &leaf_s->ents[start_s + count], count * sizeof(xfs_dir2_leaf_entry_t)); xfs_dir2_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1); @@ -695,10 +696,10 @@ xfs_dir2_leafn_moveents( /* * Update the headers and log them. */ - INT_MOD(leaf_s->hdr.count, ARCH_CONVERT, -(count)); - INT_MOD(leaf_s->hdr.stale, ARCH_CONVERT, -(stale)); - INT_MOD(leaf_d->hdr.count, ARCH_CONVERT, count); - INT_MOD(leaf_d->hdr.stale, ARCH_CONVERT, stale); + be16_add(&leaf_s->hdr.count, -(count)); + be16_add(&leaf_s->hdr.stale, -(stale)); + be16_add(&leaf_d->hdr.count, count); + be16_add(&leaf_d->hdr.stale, stale); xfs_dir2_leaf_log_header(tp, bp_s); xfs_dir2_leaf_log_header(tp, bp_d); xfs_dir2_leafn_check(args->dp, bp_s); @@ -719,13 +720,13 @@ xfs_dir2_leafn_order( leaf1 = leaf1_bp->data; leaf2 = leaf2_bp->data; - ASSERT(INT_GET(leaf1->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); - ASSERT(INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); - if (INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0 && - INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0 && - (INT_GET(leaf2->ents[0].hashval, ARCH_CONVERT) < INT_GET(leaf1->ents[0].hashval, ARCH_CONVERT) || - INT_GET(leaf2->ents[INT_GET(leaf2->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT) < - INT_GET(leaf1->ents[INT_GET(leaf1->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT))) + ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); + if (be16_to_cpu(leaf1->hdr.count) > 0 && + be16_to_cpu(leaf2->hdr.count) > 0 && + (be32_to_cpu(leaf2->ents[0].hashval) < be32_to_cpu(leaf1->ents[0].hashval) || + be32_to_cpu(leaf2->ents[be16_to_cpu(leaf2->hdr.count) - 1].hashval) < + be32_to_cpu(leaf1->ents[be16_to_cpu(leaf1->hdr.count) - 1].hashval))) return 1; return 0; } @@ -768,9 +769,9 @@ xfs_dir2_leafn_rebalance( } leaf1 = blk1->bp->data; leaf2 = blk2->bp->data; - oldsum = INT_GET(leaf1->hdr.count, ARCH_CONVERT) + INT_GET(leaf2->hdr.count, ARCH_CONVERT); + oldsum = be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count); #ifdef DEBUG - oldstale = INT_GET(leaf1->hdr.stale, ARCH_CONVERT) + INT_GET(leaf2->hdr.stale, ARCH_CONVERT); + oldstale = be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale); #endif mid = oldsum >> 1; /* @@ -780,10 +781,10 @@ xfs_dir2_leafn_rebalance( if (oldsum & 1) { xfs_dahash_t midhash; /* middle entry hash value */ - if (mid >= INT_GET(leaf1->hdr.count, ARCH_CONVERT)) - midhash = INT_GET(leaf2->ents[mid - INT_GET(leaf1->hdr.count, ARCH_CONVERT)].hashval, ARCH_CONVERT); + if (mid >= be16_to_cpu(leaf1->hdr.count)) + midhash = be32_to_cpu(leaf2->ents[mid - be16_to_cpu(leaf1->hdr.count)].hashval); else - midhash = INT_GET(leaf1->ents[mid].hashval, ARCH_CONVERT); + midhash = be32_to_cpu(leaf1->ents[mid].hashval); isleft = args->hashval <= midhash; } /* @@ -797,30 +798,30 @@ xfs_dir2_leafn_rebalance( * Calculate moved entry count. Positive means left-to-right, * negative means right-to-left. Then move the entries. */ - count = INT_GET(leaf1->hdr.count, ARCH_CONVERT) - mid + (isleft == 0); + count = be16_to_cpu(leaf1->hdr.count) - mid + (isleft == 0); if (count > 0) xfs_dir2_leafn_moveents(args, blk1->bp, - INT_GET(leaf1->hdr.count, ARCH_CONVERT) - count, blk2->bp, 0, count); + be16_to_cpu(leaf1->hdr.count) - count, blk2->bp, 0, count); else if (count < 0) xfs_dir2_leafn_moveents(args, blk2->bp, 0, blk1->bp, - INT_GET(leaf1->hdr.count, ARCH_CONVERT), count); - ASSERT(INT_GET(leaf1->hdr.count, ARCH_CONVERT) + INT_GET(leaf2->hdr.count, ARCH_CONVERT) == oldsum); - ASSERT(INT_GET(leaf1->hdr.stale, ARCH_CONVERT) + INT_GET(leaf2->hdr.stale, ARCH_CONVERT) == oldstale); + be16_to_cpu(leaf1->hdr.count), count); + ASSERT(be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count) == oldsum); + ASSERT(be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale) == oldstale); /* * Mark whether we're inserting into the old or new leaf. */ - if (INT_GET(leaf1->hdr.count, ARCH_CONVERT) < INT_GET(leaf2->hdr.count, ARCH_CONVERT)) + if (be16_to_cpu(leaf1->hdr.count) < be16_to_cpu(leaf2->hdr.count)) state->inleaf = swap; - else if (INT_GET(leaf1->hdr.count, ARCH_CONVERT) > INT_GET(leaf2->hdr.count, ARCH_CONVERT)) + else if (be16_to_cpu(leaf1->hdr.count) > be16_to_cpu(leaf2->hdr.count)) state->inleaf = !swap; else state->inleaf = - swap ^ (blk1->index <= INT_GET(leaf1->hdr.count, ARCH_CONVERT)); + swap ^ (blk1->index <= be16_to_cpu(leaf1->hdr.count)); /* * Adjust the expected index for insertion. */ if (!state->inleaf) - blk2->index = blk1->index - INT_GET(leaf1->hdr.count, ARCH_CONVERT); + blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); /* * Finally sanity check just to make sure we are not returning a negative index @@ -867,7 +868,7 @@ xfs_dir2_leafn_remove( tp = args->trans; mp = dp->i_mount; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); /* * Point to the entry we're removing. */ @@ -875,17 +876,17 @@ xfs_dir2_leafn_remove( /* * Extract the data block and offset from the entry. */ - db = XFS_DIR2_DATAPTR_TO_DB(mp, INT_GET(lep->address, ARCH_CONVERT)); + db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address)); ASSERT(dblk->blkno == db); - off = XFS_DIR2_DATAPTR_TO_OFF(mp, INT_GET(lep->address, ARCH_CONVERT)); + off = XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)); ASSERT(dblk->index == off); /* * Kill the leaf entry by marking it stale. * Log the leaf block changes. */ - INT_MOD(leaf->hdr.stale, ARCH_CONVERT, +1); + be16_add(&leaf->hdr.stale, 1); xfs_dir2_leaf_log_header(tp, bp); - INT_SET(lep->address, ARCH_CONVERT, XFS_DIR2_NULL_DATAPTR); + lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); xfs_dir2_leaf_log_ents(tp, bp, index, index); /* * Make the data entry free. Keep track of the longest freespace @@ -894,7 +895,7 @@ xfs_dir2_leafn_remove( dbp = dblk->bp; data = dbp->data; dep = (xfs_dir2_data_entry_t *)((char *)data + off); - longest = INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT); + longest = be16_to_cpu(data->hdr.bestfree[0].length); needlog = needscan = 0; xfs_dir2_data_make_free(tp, dbp, off, XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan); @@ -911,7 +912,7 @@ xfs_dir2_leafn_remove( * If the longest data block freespace changes, need to update * the corresponding freeblock entry. */ - if (longest < INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT)) { + if (longest < be16_to_cpu(data->hdr.bestfree[0].length)) { int error; /* error return value */ xfs_dabuf_t *fbp; /* freeblock buffer */ xfs_dir2_db_t fdb; /* freeblock block number */ @@ -929,15 +930,15 @@ xfs_dir2_leafn_remove( return error; } free = fbp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); - ASSERT(INT_GET(free->hdr.firstdb, ARCH_CONVERT) == + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.firstdb) == XFS_DIR2_MAX_FREE_BESTS(mp) * (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); /* * Calculate which entry we need to fix. */ findex = XFS_DIR2_DB_TO_FDINDEX(mp, db); - longest = INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT); + longest = be16_to_cpu(data->hdr.bestfree[0].length); /* * If the data block is now empty we can get rid of it * (usually). @@ -969,7 +970,7 @@ xfs_dir2_leafn_remove( /* * One less used entry in the free table. */ - INT_MOD(free->hdr.nused, ARCH_CONVERT, -1); + free->hdr.nused = cpu_to_be32(-1); xfs_dir2_free_log_header(tp, fbp); /* * If this was the last entry in the table, we can @@ -977,21 +978,21 @@ xfs_dir2_leafn_remove( * entries at the end referring to non-existent * data blocks, get those too. */ - if (findex == INT_GET(free->hdr.nvalid, ARCH_CONVERT) - 1) { + if (findex == be32_to_cpu(free->hdr.nvalid) - 1) { int i; /* free entry index */ for (i = findex - 1; - i >= 0 && INT_GET(free->bests[i], ARCH_CONVERT) == NULLDATAOFF; + i >= 0 && be16_to_cpu(free->bests[i]) == NULLDATAOFF; i--) continue; - INT_SET(free->hdr.nvalid, ARCH_CONVERT, i + 1); + free->hdr.nvalid = cpu_to_be32(i + 1); logfree = 0; } /* * Not the last entry, just punch it out. */ else { - INT_SET(free->bests[findex], ARCH_CONVERT, NULLDATAOFF); + free->bests[findex] = cpu_to_be16(NULLDATAOFF); logfree = 1; } /* @@ -1017,7 +1018,7 @@ xfs_dir2_leafn_remove( * the new value. */ else { - INT_SET(free->bests[findex], ARCH_CONVERT, longest); + free->bests[findex] = cpu_to_be16(longest); logfree = 1; } /* @@ -1039,7 +1040,7 @@ xfs_dir2_leafn_remove( *rval = ((uint)sizeof(leaf->hdr) + (uint)sizeof(leaf->ents[0]) * - (INT_GET(leaf->hdr.count, ARCH_CONVERT) - INT_GET(leaf->hdr.stale, ARCH_CONVERT))) < + (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale))) < mp->m_dir_magicpct; return 0; } @@ -1138,9 +1139,9 @@ xfs_dir2_leafn_toosmall( */ blk = &state->path.blk[state->path.active - 1]; info = blk->bp->data; - ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC); leaf = (xfs_dir2_leaf_t *)info; - count = INT_GET(leaf->hdr.count, ARCH_CONVERT) - INT_GET(leaf->hdr.stale, ARCH_CONVERT); + count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); bytes = (uint)sizeof(leaf->hdr) + count * (uint)sizeof(leaf->ents[0]); if (bytes > (state->blocksize >> 1)) { /* @@ -1160,7 +1161,7 @@ xfs_dir2_leafn_toosmall( * Make altpath point to the block we want to keep and * path point to the block we want to drop (this one). */ - forward = info->forw; + forward = (info->forw != 0); memcpy(&state->altpath, &state->path, sizeof(state->path)); error = xfs_da_path_shift(state, &state->altpath, forward, 0, &rval); @@ -1176,9 +1177,9 @@ xfs_dir2_leafn_toosmall( * We prefer coalescing with the lower numbered sibling so as * to shrink a directory over time. */ - forward = INT_GET(info->forw, ARCH_CONVERT) < INT_GET(info->back, ARCH_CONVERT); + forward = be32_to_cpu(info->forw) < be32_to_cpu(info->back); for (i = 0, bp = NULL; i < 2; forward = !forward, i++) { - blkno = forward ?INT_GET( info->forw, ARCH_CONVERT) : INT_GET(info->back, ARCH_CONVERT); + blkno = forward ? be32_to_cpu(info->forw) : be32_to_cpu(info->back); if (blkno == 0) continue; /* @@ -1194,11 +1195,11 @@ xfs_dir2_leafn_toosmall( * Count bytes in the two blocks combined. */ leaf = (xfs_dir2_leaf_t *)info; - count = INT_GET(leaf->hdr.count, ARCH_CONVERT) - INT_GET(leaf->hdr.stale, ARCH_CONVERT); + count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); bytes = state->blocksize - (state->blocksize >> 2); leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); - count += INT_GET(leaf->hdr.count, ARCH_CONVERT) - INT_GET(leaf->hdr.stale, ARCH_CONVERT); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); + count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); bytes -= count * (uint)sizeof(leaf->ents[0]); /* * Fits with at least 25% to spare. @@ -1256,27 +1257,27 @@ xfs_dir2_leafn_unbalance( ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC); drop_leaf = drop_blk->bp->data; save_leaf = save_blk->bp->data; - ASSERT(INT_GET(drop_leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); - ASSERT(INT_GET(save_leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); + ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); /* * If there are any stale leaf entries, take this opportunity * to purge them. */ - if (INT_GET(drop_leaf->hdr.stale, ARCH_CONVERT)) + if (drop_leaf->hdr.stale) xfs_dir2_leaf_compact(args, drop_blk->bp); - if (INT_GET(save_leaf->hdr.stale, ARCH_CONVERT)) + if (save_leaf->hdr.stale) xfs_dir2_leaf_compact(args, save_blk->bp); /* * Move the entries from drop to the appropriate end of save. */ - drop_blk->hashval = INT_GET(drop_leaf->ents[INT_GET(drop_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT); + drop_blk->hashval = be32_to_cpu(drop_leaf->ents[be16_to_cpu(drop_leaf->hdr.count) - 1].hashval); if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp)) xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp, 0, - INT_GET(drop_leaf->hdr.count, ARCH_CONVERT)); + be16_to_cpu(drop_leaf->hdr.count)); else xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp, - INT_GET(save_leaf->hdr.count, ARCH_CONVERT), INT_GET(drop_leaf->hdr.count, ARCH_CONVERT)); - save_blk->hashval = INT_GET(save_leaf->ents[INT_GET(save_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT); + be16_to_cpu(save_leaf->hdr.count), be16_to_cpu(drop_leaf->hdr.count)); + save_blk->hashval = be32_to_cpu(save_leaf->ents[be16_to_cpu(save_leaf->hdr.count) - 1].hashval); xfs_dir2_leafn_check(args->dp, save_blk->bp); } @@ -1378,7 +1379,7 @@ xfs_dir2_node_addname_int( xfs_mount_t *mp; /* filesystem mount point */ int needlog; /* need to log data header */ int needscan; /* need to rescan data frees */ - xfs_dir2_data_off_t *tagp; /* data entry tag pointer */ + __be16 *tagp; /* data entry tag pointer */ xfs_trans_t *tp; /* transaction pointer */ dp = args->dp; @@ -1397,7 +1398,7 @@ xfs_dir2_node_addname_int( */ ifbno = fblk->blkno; free = fbp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); findex = fblk->index; /* * This means the free entry showed that the data block had @@ -1405,10 +1406,10 @@ xfs_dir2_node_addname_int( * Use that data block. */ if (findex >= 0) { - ASSERT(findex < INT_GET(free->hdr.nvalid, ARCH_CONVERT)); - ASSERT(INT_GET(free->bests[findex], ARCH_CONVERT) != NULLDATAOFF); - ASSERT(INT_GET(free->bests[findex], ARCH_CONVERT) >= length); - dbno = INT_GET(free->hdr.firstdb, ARCH_CONVERT) + findex; + ASSERT(findex < be32_to_cpu(free->hdr.nvalid)); + ASSERT(be16_to_cpu(free->bests[findex]) != NULLDATAOFF); + ASSERT(be16_to_cpu(free->bests[findex]) >= length); + dbno = be32_to_cpu(free->hdr.firstdb) + findex; } /* * The data block looked at didn't have enough room. @@ -1481,20 +1482,20 @@ xfs_dir2_node_addname_int( continue; } free = fbp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); findex = 0; } /* * Look at the current free entry. Is it good enough? */ - if (INT_GET(free->bests[findex], ARCH_CONVERT) != NULLDATAOFF && - INT_GET(free->bests[findex], ARCH_CONVERT) >= length) - dbno = INT_GET(free->hdr.firstdb, ARCH_CONVERT) + findex; + if (be16_to_cpu(free->bests[findex]) != NULLDATAOFF && + be16_to_cpu(free->bests[findex]) >= length) + dbno = be32_to_cpu(free->hdr.firstdb) + findex; else { /* * Are we done with the freeblock? */ - if (++findex == INT_GET(free->hdr.nvalid, ARCH_CONVERT)) { + if (++findex == be32_to_cpu(free->hdr.nvalid)) { /* * Drop the block. */ @@ -1608,15 +1609,15 @@ xfs_dir2_node_addname_int( * its first slot as our empty slot. */ free = fbp->data; - INT_SET(free->hdr.magic, ARCH_CONVERT, XFS_DIR2_FREE_MAGIC); - INT_SET(free->hdr.firstdb, ARCH_CONVERT, + free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC); + free->hdr.firstdb = cpu_to_be32( (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * XFS_DIR2_MAX_FREE_BESTS(mp)); free->hdr.nvalid = 0; free->hdr.nused = 0; } else { free = fbp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); } /* @@ -1627,20 +1628,20 @@ xfs_dir2_node_addname_int( * If it's after the end of the current entries in the * freespace block, extend that table. */ - if (findex >= INT_GET(free->hdr.nvalid, ARCH_CONVERT)) { + if (findex >= be32_to_cpu(free->hdr.nvalid)) { ASSERT(findex < XFS_DIR2_MAX_FREE_BESTS(mp)); - INT_SET(free->hdr.nvalid, ARCH_CONVERT, findex + 1); + free->hdr.nvalid = cpu_to_be32(findex + 1); /* * Tag new entry so nused will go up. */ - INT_SET(free->bests[findex], ARCH_CONVERT, NULLDATAOFF); + free->bests[findex] = cpu_to_be16(NULLDATAOFF); } /* * If this entry was for an empty data block * (this should always be true) then update the header. */ - if (INT_GET(free->bests[findex], ARCH_CONVERT) == NULLDATAOFF) { - INT_MOD(free->hdr.nused, ARCH_CONVERT, +1); + if (be16_to_cpu(free->bests[findex]) == NULLDATAOFF) { + be32_add(&free->hdr.nused, 1); xfs_dir2_free_log_header(tp, fbp); } /* @@ -1649,7 +1650,7 @@ xfs_dir2_node_addname_int( * change again. */ data = dbp->data; - INT_COPY(free->bests[findex], data->hdr.bestfree[0].length, ARCH_CONVERT); + free->bests[findex] = data->hdr.bestfree[0].length; logfree = 1; } /* @@ -1677,12 +1678,12 @@ xfs_dir2_node_addname_int( data = dbp->data; logfree = 0; } - ASSERT(INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT) >= length); + ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) >= length); /* * Point to the existing unused space. */ dup = (xfs_dir2_data_unused_t *) - ((char *)data + INT_GET(data->hdr.bestfree[0].offset, ARCH_CONVERT)); + ((char *)data + be16_to_cpu(data->hdr.bestfree[0].offset)); needscan = needlog = 0; /* * Mark the first part of the unused space, inuse for us. @@ -1698,7 +1699,7 @@ xfs_dir2_node_addname_int( dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); - INT_SET(*tagp, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dep - (char *)data)); + *tagp = cpu_to_be16((char *)dep - (char *)data); xfs_dir2_data_log_entry(tp, dbp, dep); /* * Rescan the block for bestfree if needed. @@ -1713,8 +1714,8 @@ xfs_dir2_node_addname_int( /* * If the freespace entry is now wrong, update it. */ - if (INT_GET(free->bests[findex], ARCH_CONVERT) != INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT)) { - INT_COPY(free->bests[findex], data->hdr.bestfree[0].length, ARCH_CONVERT); + if (be16_to_cpu(free->bests[findex]) != be16_to_cpu(data->hdr.bestfree[0].length)) { + free->bests[findex] = data->hdr.bestfree[0].length; logfree = 1; } /* @@ -1731,7 +1732,7 @@ xfs_dir2_node_addname_int( * Return the data block and offset in args, then drop the data block. */ args->blkno = (xfs_dablk_t)dbno; - args->index = INT_GET(*tagp, ARCH_CONVERT); + args->index = be16_to_cpu(*tagp); xfs_da_buf_done(dbp); return 0; } @@ -1900,10 +1901,10 @@ xfs_dir2_node_replace( * Point to the data entry. */ data = state->extrablk.bp->data; - ASSERT(INT_GET(data->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC); + ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC); dep = (xfs_dir2_data_entry_t *) ((char *)data + - XFS_DIR2_DATAPTR_TO_OFF(state->mp, INT_GET(lep->address, ARCH_CONVERT))); + XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address))); ASSERT(inum != INT_GET(dep->inumber, ARCH_CONVERT)); /* * Fill in the new inode number and log the entry. @@ -1966,11 +1967,11 @@ xfs_dir2_node_trim_free( return 0; } free = bp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); /* * If there are used entries, there's nothing to do. */ - if (INT_GET(free->hdr.nused, ARCH_CONVERT) > 0) { + if (be32_to_cpu(free->hdr.nused) > 0) { xfs_da_brelse(tp, bp); *rvalp = 0; return 0; diff --git a/fs/xfs/xfs_dir2_node.h b/fs/xfs/xfs_dir2_node.h index 0ab8fbd59512..c7c870ee7857 100644 --- a/fs/xfs/xfs_dir2_node.h +++ b/fs/xfs/xfs_dir2_node.h @@ -41,15 +41,15 @@ struct xfs_trans; #define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F */ typedef struct xfs_dir2_free_hdr { - __uint32_t magic; /* XFS_DIR2_FREE_MAGIC */ - __int32_t firstdb; /* db of first entry */ - __int32_t nvalid; /* count of valid entries */ - __int32_t nused; /* count of used entries */ + __be32 magic; /* XFS_DIR2_FREE_MAGIC */ + __be32 firstdb; /* db of first entry */ + __be32 nvalid; /* count of valid entries */ + __be32 nused; /* count of used entries */ } xfs_dir2_free_hdr_t; typedef struct xfs_dir2_free { xfs_dir2_free_hdr_t hdr; /* block header */ - xfs_dir2_data_off_t bests[1]; /* best free counts */ + __be16 bests[1]; /* best free counts */ /* unused entries are -1 */ } xfs_dir2_free_t; diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index ec8e7476c8b7..d98a41d1fe63 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -98,8 +98,8 @@ xfs_dir2_block_sfsize( /* * Iterate over the block's data entries by using the leaf pointers. */ - for (i = 0; i < INT_GET(btp->count, ARCH_CONVERT); i++) { - if ((addr = INT_GET(blp[i].address, ARCH_CONVERT)) == XFS_DIR2_NULL_DATAPTR) + for (i = 0; i < be32_to_cpu(btp->count); i++) { + if ((addr = be32_to_cpu(blp[i].address)) == XFS_DIR2_NULL_DATAPTR) continue; /* * Calculate the pointer to the entry at hand. @@ -220,8 +220,8 @@ xfs_dir2_block_to_sf( * If it's unused, just skip over it. */ dup = (xfs_dir2_data_unused_t *)ptr; - if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) { - ptr += INT_GET(dup->length, ARCH_CONVERT); + if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { + ptr += be16_to_cpu(dup->length); continue; } dep = (xfs_dir2_data_entry_t *)ptr; diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c index e83074016abb..ee88751c3be6 100644 --- a/fs/xfs/xfs_dir_leaf.c +++ b/fs/xfs/xfs_dir_leaf.c @@ -176,7 +176,7 @@ xfs_dir_shortform_addname(xfs_da_args_t *args) ASSERT(dp->i_df.if_u1.if_data != NULL); sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; sfe = &sf->list[0]; - for (i = INT_GET(sf->hdr.count, ARCH_CONVERT)-1; i >= 0; i--) { + for (i = sf->hdr.count-1; i >= 0; i--) { if (sfe->namelen == args->namelen && args->name[0] == sfe->name[0] && memcmp(args->name, sfe->name, args->namelen) == 0) @@ -193,7 +193,7 @@ xfs_dir_shortform_addname(xfs_da_args_t *args) XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber); sfe->namelen = args->namelen; memcpy(sfe->name, args->name, sfe->namelen); - INT_MOD(sf->hdr.count, ARCH_CONVERT, +1); + sf->hdr.count++; dp->i_d.di_size += size; xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); @@ -227,7 +227,7 @@ xfs_dir_shortform_removename(xfs_da_args_t *args) base = sizeof(xfs_dir_sf_hdr_t); sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; sfe = &sf->list[0]; - for (i = INT_GET(sf->hdr.count, ARCH_CONVERT)-1; i >= 0; i--) { + for (i = sf->hdr.count-1; i >= 0; i--) { size = XFS_DIR_SF_ENTSIZE_BYENTRY(sfe); if (sfe->namelen == args->namelen && sfe->name[0] == args->name[0] && @@ -245,7 +245,7 @@ xfs_dir_shortform_removename(xfs_da_args_t *args) memmove(&((char *)sf)[base], &((char *)sf)[base+size], dp->i_d.di_size - (base+size)); } - INT_MOD(sf->hdr.count, ARCH_CONVERT, -1); + sf->hdr.count--; xfs_idata_realloc(dp, -size, XFS_DATA_FORK); dp->i_d.di_size -= size; @@ -288,7 +288,7 @@ xfs_dir_shortform_lookup(xfs_da_args_t *args) return(XFS_ERROR(EEXIST)); } sfe = &sf->list[0]; - for (i = INT_GET(sf->hdr.count, ARCH_CONVERT)-1; i >= 0; i--) { + for (i = sf->hdr.count-1; i >= 0; i--) { if (sfe->namelen == args->namelen && sfe->name[0] == args->name[0] && memcmp(args->name, sfe->name, args->namelen) == 0) { @@ -375,7 +375,7 @@ xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs) goto out; sfe = &sf->list[0]; - for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { + for (i = 0; i < sf->hdr.count; i++) { args.name = (char *)(sfe->name); args.namelen = sfe->namelen; args.hashval = xfs_da_hashname((char *)(sfe->name), @@ -428,7 +428,7 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp, sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset); - nsbuf = INT_GET(sf->hdr.count, ARCH_CONVERT) + 2; + nsbuf = sf->hdr.count + 2; sbsize = (nsbuf + 1) * sizeof(*sbuf); sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP); @@ -460,8 +460,7 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp, /* * Scan the directory data for the rest of the entries. */ - for (i = 0, sfe = &sf->list[0]; - i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { + for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { if (unlikely( ((char *)sfe < (char *)sf) || @@ -600,7 +599,7 @@ xfs_dir_shortform_replace(xfs_da_args_t *args) } ASSERT(args->namelen != 1 || args->name[0] != '.'); sfe = &sf->list[0]; - for (i = INT_GET(sf->hdr.count, ARCH_CONVERT)-1; i >= 0; i--) { + for (i = sf->hdr.count-1; i >= 0; i--) { if (sfe->namelen == args->namelen && sfe->name[0] == args->name[0] && memcmp(args->name, sfe->name, args->namelen) == 0) { @@ -644,7 +643,7 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) ASSERT(bp != NULL); memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount)); leaf = (xfs_dir_leafblock_t *)tmpbuffer; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); memset(bp->data, 0, XFS_LBSIZE(dp->i_mount)); /* @@ -742,11 +741,13 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args) } node = bp1->data; leaf = bp2->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); - INT_SET(node->btree[0].hashval, ARCH_CONVERT, INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); + node->btree[0].hashval = cpu_to_be32( + INT_GET(leaf->entries[ + INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); xfs_da_buf_done(bp2); - INT_SET(node->btree[0].before, ARCH_CONVERT, blkno); - INT_SET(node->hdr.count, ARCH_CONVERT, 1); + node->btree[0].before = cpu_to_be32(blkno); + node->hdr.count = cpu_to_be16(1); xfs_da_log_buf(args->trans, bp1, XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0]))); xfs_da_buf_done(bp1); @@ -781,7 +782,7 @@ xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) leaf = bp->data; memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); hdr = &leaf->hdr; - INT_SET(hdr->info.magic, ARCH_CONVERT, XFS_DIR_LEAF_MAGIC); + hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC); INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount)); if (!hdr->firstused) INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount) - 1); @@ -860,7 +861,7 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) int tablesize, entsize, sum, i, tmp, error; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); ASSERT((index >= 0) && (index <= INT_GET(leaf->hdr.count, ARCH_CONVERT))); hdr = &leaf->hdr; entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen); @@ -940,7 +941,7 @@ xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, int tmp, i; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); hdr = &leaf->hdr; ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE)); ASSERT((index >= 0) && (index <= INT_GET(hdr->count, ARCH_CONVERT))); @@ -1097,8 +1098,8 @@ xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, ASSERT(blk2->magic == XFS_DIR_LEAF_MAGIC); leaf1 = blk1->bp->data; leaf2 = blk2->bp->data; - ASSERT(INT_GET(leaf1->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); - ASSERT(INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); /* * Check ordering of blocks, reverse if it makes things simpler. @@ -1325,7 +1326,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) */ blk = &state->path.blk[ state->path.active-1 ]; info = blk->bp->data; - ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC); leaf = (xfs_dir_leafblock_t *)info; count = INT_GET(leaf->hdr.count, ARCH_CONVERT); bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) + @@ -1348,7 +1349,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) * Make altpath point to the block we want to keep and * path point to the block we want to drop (this one). */ - forward = info->forw; + forward = (info->forw != 0); memcpy(&state->altpath, &state->path, sizeof(state->path)); error = xfs_da_path_shift(state, &state->altpath, forward, 0, &retval); @@ -1369,12 +1370,12 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) * We prefer coalescing with the lower numbered sibling so as * to shrink a directory over time. */ - forward = (INT_GET(info->forw, ARCH_CONVERT) < INT_GET(info->back, ARCH_CONVERT)); /* start with smaller blk num */ + forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); /* start with smaller blk num */ for (i = 0; i < 2; forward = !forward, i++) { if (forward) - blkno = INT_GET(info->forw, ARCH_CONVERT); + blkno = be32_to_cpu(info->forw); else - blkno = INT_GET(info->back, ARCH_CONVERT); + blkno = be32_to_cpu(info->back); if (blkno == 0) continue; error = xfs_da_read_buf(state->args->trans, state->args->dp, @@ -1389,7 +1390,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) bytes = state->blocksize - (state->blocksize>>2); bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); count += INT_GET(leaf->hdr.count, ARCH_CONVERT); bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); @@ -1447,7 +1448,7 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) xfs_mount_t *mp; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); hdr = &leaf->hdr; mp = trans->t_mountp; ASSERT((INT_GET(hdr->count, ARCH_CONVERT) > 0) && (INT_GET(hdr->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); @@ -1599,8 +1600,8 @@ xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, ASSERT(save_blk->magic == XFS_DIR_LEAF_MAGIC); drop_leaf = drop_blk->bp->data; save_leaf = save_blk->bp->data; - ASSERT(INT_GET(drop_leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); - ASSERT(INT_GET(save_leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); drop_hdr = &drop_leaf->hdr; save_hdr = &save_leaf->hdr; @@ -1695,7 +1696,7 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) xfs_dahash_t hashval; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) < (XFS_LBSIZE(args->dp->i_mount)/8)); /* @@ -1782,8 +1783,8 @@ xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, /* * Set up environment. */ - ASSERT(INT_GET(leaf_s->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); - ASSERT(INT_GET(leaf_d->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); hdr_s = &leaf_s->hdr; hdr_d = &leaf_d->hdr; ASSERT((INT_GET(hdr_s->count, ARCH_CONVERT) > 0) && (INT_GET(hdr_s->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); @@ -1883,8 +1884,8 @@ xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) leaf1 = leaf1_bp->data; leaf2 = leaf2_bp->data; - ASSERT((INT_GET(leaf1->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC) && - (INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC)); + ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) && + (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC)); if ((INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0) && ((INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) < INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) || @@ -1904,7 +1905,7 @@ xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count) xfs_dir_leafblock_t *leaf; leaf = bp->data; - ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC); + ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); if (count) *count = INT_GET(leaf->hdr.count, ARCH_CONVERT); if (!leaf->hdr.count) @@ -1940,7 +1941,7 @@ xfs_dir_leaf_getdents_int( mp = dp->i_mount; leaf = bp->data; - if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) { + if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) { *eobp = 1; return XFS_ERROR(ENOENT); /* XXX wrong code */ } @@ -1992,7 +1993,7 @@ xfs_dir_leaf_getdents_int( if (i == INT_GET(leaf->hdr.count, ARCH_CONVERT)) { xfs_dir_trace_g_du("leaf: hash not found", dp, uio); - if (!INT_GET(leaf->hdr.info.forw, ARCH_CONVERT)) + if (!leaf->hdr.info.forw) uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH); /* @@ -2047,8 +2048,7 @@ xfs_dir_leaf_getdents_int( xfs_dir_trace_g_duc("leaf: middle cookie ", dp, uio, p.cook.o); - } else if ((thishash = INT_GET(leaf->hdr.info.forw, - ARCH_CONVERT))) { + } else if ((thishash = be32_to_cpu(leaf->hdr.info.forw))) { xfs_dabuf_t *bp2; xfs_dir_leafblock_t *leaf2; @@ -2064,9 +2064,9 @@ xfs_dir_leaf_getdents_int( leaf2 = bp2->data; if (unlikely( - (INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) + (be16_to_cpu(leaf2->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) - || (INT_GET(leaf2->hdr.info.back, ARCH_CONVERT) + || (be32_to_cpu(leaf2->hdr.info.back) != bno))) { /* GROT */ XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)", XFS_ERRLEVEL_LOW, mp, diff --git a/fs/xfs/xfs_dir_sf.h b/fs/xfs/xfs_dir_sf.h index fe44c6f4d560..5b20b4d3f57d 100644 --- a/fs/xfs/xfs_dir_sf.h +++ b/fs/xfs/xfs_dir_sf.h @@ -35,19 +35,21 @@ typedef struct { __uint8_t i[sizeof(xfs_ino_t)]; } xfs_dir_ino_t; * and the elements much be memcpy'd out into a work area to get correct * alignment for the inode number fields. */ +typedef struct xfs_dir_sf_hdr { /* constant-structure header block */ + xfs_dir_ino_t parent; /* parent dir inode number */ + __uint8_t count; /* count of active entries */ +} xfs_dir_sf_hdr_t; + +typedef struct xfs_dir_sf_entry { + xfs_dir_ino_t inumber; /* referenced inode number */ + __uint8_t namelen; /* actual length of name (no NULL) */ + __uint8_t name[1]; /* name */ +} xfs_dir_sf_entry_t; + typedef struct xfs_dir_shortform { - struct xfs_dir_sf_hdr { /* constant-structure header block */ - xfs_dir_ino_t parent; /* parent dir inode number */ - __uint8_t count; /* count of active entries */ - } hdr; - struct xfs_dir_sf_entry { - xfs_dir_ino_t inumber; /* referenced inode number */ - __uint8_t namelen; /* actual length of name (no NULL) */ - __uint8_t name[1]; /* name */ - } list[1]; /* variable sized array */ + xfs_dir_sf_hdr_t hdr; + xfs_dir_sf_entry_t list[1]; /* variable sized array */ } xfs_dir_shortform_t; -typedef struct xfs_dir_sf_hdr xfs_dir_sf_hdr_t; -typedef struct xfs_dir_sf_entry xfs_dir_sf_entry_t; /* * We generate this then sort it, so that readdirs are returned in diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index b4c7f2bc55a0..00b1540f8108 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -191,14 +191,4 @@ typedef enum { extern struct bhv_vfsops xfs_dmops; -#ifdef CONFIG_XFS_DMAPI -void xfs_dm_init(struct file_system_type *); -void xfs_dm_exit(struct file_system_type *); -#define XFS_DM_INIT(fstype) xfs_dm_init(fstype) -#define XFS_DM_EXIT(fstype) xfs_dm_exit(fstype) -#else -#define XFS_DM_INIT(fstype) -#define XFS_DM_EXIT(fstype) -#endif - #endif /* __XFS_DMAPI_H__ */ diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index b4d971b01588..56caa88713ab 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -462,6 +462,7 @@ xfs_fs_counts( { unsigned long s; + xfs_icsb_sync_counters_lazy(mp); s = XFS_SB_LOCK(mp); cnt->freedata = mp->m_sb.sb_fdblocks; cnt->freertx = mp->m_sb.sb_frextents; diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 8f3fae1aa98a..0024892841a3 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -138,8 +138,6 @@ xfs_ialloc_ag_alloc( int version; /* inode version number to use */ int isaligned; /* inode allocation at stripe unit */ /* boundary */ - xfs_dinode_core_t dic; /* a dinode_core to copy to new */ - /* inodes */ args.tp = tp; args.mp = tp->t_mountp; @@ -250,10 +248,6 @@ xfs_ialloc_ag_alloc( else version = XFS_DINODE_VERSION_1; - memset(&dic, 0, sizeof(xfs_dinode_core_t)); - INT_SET(dic.di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC); - INT_SET(dic.di_version, ARCH_CONVERT, version); - for (j = 0; j < nbufs; j++) { /* * Get the block. @@ -266,12 +260,13 @@ xfs_ialloc_ag_alloc( ASSERT(fbuf); ASSERT(!XFS_BUF_GETERROR(fbuf)); /* - * Loop over the inodes in this buffer. + * Set initial values for the inodes in this buffer. */ - + xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog); for (i = 0; i < ninodes; i++) { free = XFS_MAKE_IPTR(args.mp, fbuf, i); - memcpy(&(free->di_core), &dic, sizeof(xfs_dinode_core_t)); + INT_SET(free->di_core.di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC); + INT_SET(free->di_core.di_version, ARCH_CONVERT, version); INT_SET(free->di_next_unlinked, ARCH_CONVERT, NULLAGINO); xfs_ialloc_log_di(tp, fbuf, i, XFS_DI_CORE_BITS | XFS_DI_NEXT_UNLINKED); diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 8e380a1fb79b..3ce35a6f700b 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -258,7 +258,7 @@ again: goto finish_inode; } else if (vp != inode_vp) { - struct inode *inode = LINVFS_GET_IP(inode_vp); + struct inode *inode = vn_to_inode(inode_vp); /* The inode is being torn down, pause and * try again. @@ -495,7 +495,7 @@ retry: if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) { xfs_inode_t *ip; - vp = LINVFS_GET_VP(inode); + vp = vn_from_inode(inode); if (inode->i_state & I_NEW) { vn_initialize(inode); error = xfs_iget_core(vp, mp, tp, ino, flags, @@ -617,7 +617,7 @@ xfs_iput_new(xfs_inode_t *ip, uint lock_flags) { vnode_t *vp = XFS_ITOV(ip); - struct inode *inode = LINVFS_GET_IP(vp); + struct inode *inode = vn_to_inode(vp); vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 1d7f5a7e063e..88a517fad07b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -76,16 +76,18 @@ STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int); */ STATIC void xfs_validate_extents( - xfs_bmbt_rec_t *ep, + xfs_ifork_t *ifp, int nrecs, int disk, xfs_exntfmt_t fmt) { + xfs_bmbt_rec_t *ep; xfs_bmbt_irec_t irec; xfs_bmbt_rec_t rec; int i; for (i = 0; i < nrecs; i++) { + ep = xfs_iext_get_ext(ifp, i); rec.l0 = get_unaligned((__uint64_t*)&ep->l0); rec.l1 = get_unaligned((__uint64_t*)&ep->l1); if (disk) @@ -94,11 +96,10 @@ xfs_validate_extents( xfs_bmbt_get_all(&rec, &irec); if (fmt == XFS_EXTFMT_NOSTATE) ASSERT(irec.br_state == XFS_EXT_NORM); - ep++; } } #else /* DEBUG */ -#define xfs_validate_extents(ep, nrecs, disk, fmt) +#define xfs_validate_extents(ifp, nrecs, disk, fmt) #endif /* DEBUG */ /* @@ -252,7 +253,8 @@ xfs_itobp( xfs_inode_t *ip, xfs_dinode_t **dipp, xfs_buf_t **bpp, - xfs_daddr_t bno) + xfs_daddr_t bno, + uint imap_flags) { xfs_buf_t *bp; int error; @@ -268,10 +270,9 @@ xfs_itobp( * inode on disk. */ imap.im_blkno = bno; - error = xfs_imap(mp, tp, ip->i_ino, &imap, XFS_IMAP_LOOKUP); - if (error != 0) { + if ((error = xfs_imap(mp, tp, ip->i_ino, &imap, + XFS_IMAP_LOOKUP | imap_flags))) return error; - } /* * If the inode number maps to a block outside the bounds @@ -335,9 +336,10 @@ xfs_itobp( * (if DEBUG kernel) or the first inode in the buffer, otherwise. */ #ifdef DEBUG - ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog; + ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : + (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog); #else - ni = 1; + ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1; #endif for (i = 0; i < ni; i++) { int di_ok; @@ -504,7 +506,7 @@ xfs_iformat( switch (INT_GET(dip->di_core.di_aformat, ARCH_CONVERT)) { case XFS_DINODE_FMT_LOCAL: atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip); - size = (int)INT_GET(atp->hdr.totsize, ARCH_CONVERT); + size = be16_to_cpu(atp->hdr.totsize); error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size); break; case XFS_DINODE_FMT_EXTENTS: @@ -597,7 +599,6 @@ xfs_iformat_extents( xfs_bmbt_rec_t *ep, *dp; xfs_ifork_t *ifp; int nex; - int real_size; int size; int i; @@ -619,23 +620,20 @@ xfs_iformat_extents( return XFS_ERROR(EFSCORRUPTED); } - real_size = 0; + ifp->if_real_bytes = 0; if (nex == 0) ifp->if_u1.if_extents = NULL; else if (nex <= XFS_INLINE_EXTS) ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; - else { - ifp->if_u1.if_extents = kmem_alloc(size, KM_SLEEP); - ASSERT(ifp->if_u1.if_extents != NULL); - real_size = size; - } + else + xfs_iext_add(ifp, 0, nex); + ifp->if_bytes = size; - ifp->if_real_bytes = real_size; if (size) { dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork); - xfs_validate_extents(dp, nex, 1, XFS_EXTFMT_INODE(ip)); - ep = ifp->if_u1.if_extents; - for (i = 0; i < nex; i++, ep++, dp++) { + xfs_validate_extents(ifp, nex, 1, XFS_EXTFMT_INODE(ip)); + for (i = 0; i < nex; i++, dp++) { + ep = xfs_iext_get_ext(ifp, i); ep->l0 = INT_GET(get_unaligned((__uint64_t*)&dp->l0), ARCH_CONVERT); ep->l1 = INT_GET(get_unaligned((__uint64_t*)&dp->l1), @@ -646,7 +644,7 @@ xfs_iformat_extents( if (whichfork != XFS_DATA_FORK || XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE) if (unlikely(xfs_check_nostate_extents( - ifp->if_u1.if_extents, nex))) { + ifp, 0, nex))) { XFS_ERROR_REPORT("xfs_iformat_extents(2)", XFS_ERRLEVEL_LOW, ip->i_mount); @@ -871,9 +869,8 @@ xfs_iread( * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will * know that this is a new incore inode. */ - error = xfs_itobp(mp, tp, ip, &dip, &bp, bno); - - if (error != 0) { + error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0); + if (error) { kmem_zone_free(xfs_inode_zone, ip); return error; } @@ -1015,6 +1012,7 @@ xfs_iread_extents( { int error; xfs_ifork_t *ifp; + xfs_extnum_t nextents; size_t size; if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) { @@ -1022,26 +1020,24 @@ xfs_iread_extents( ip->i_mount); return XFS_ERROR(EFSCORRUPTED); } - size = XFS_IFORK_NEXTENTS(ip, whichfork) * (uint)sizeof(xfs_bmbt_rec_t); + nextents = XFS_IFORK_NEXTENTS(ip, whichfork); + size = nextents * sizeof(xfs_bmbt_rec_t); ifp = XFS_IFORK_PTR(ip, whichfork); + /* * We know that the size is valid (it's checked in iformat_btree) */ - ifp->if_u1.if_extents = kmem_alloc(size, KM_SLEEP); - ASSERT(ifp->if_u1.if_extents != NULL); ifp->if_lastex = NULLEXTNUM; - ifp->if_bytes = ifp->if_real_bytes = (int)size; + ifp->if_bytes = ifp->if_real_bytes = 0; ifp->if_flags |= XFS_IFEXTENTS; + xfs_iext_add(ifp, 0, nextents); error = xfs_bmap_read_extents(tp, ip, whichfork); if (error) { - kmem_free(ifp->if_u1.if_extents, size); - ifp->if_u1.if_extents = NULL; - ifp->if_bytes = ifp->if_real_bytes = 0; + xfs_iext_destroy(ifp); ifp->if_flags &= ~XFS_IFEXTENTS; return error; } - xfs_validate_extents((xfs_bmbt_rec_t *)ifp->if_u1.if_extents, - XFS_IFORK_NEXTENTS(ip, whichfork), 0, XFS_EXTFMT_INODE(ip)); + xfs_validate_extents(ifp, nextents, 0, XFS_EXTFMT_INODE(ip)); return 0; } @@ -1376,10 +1372,10 @@ xfs_itrunc_trace( (void*)(unsigned long)((toss_finish >> 32) & 0xffffffff), (void*)(unsigned long)(toss_finish & 0xffffffff), (void*)(unsigned long)current_cpu(), - (void*)0, - (void*)0, - (void*)0, - (void*)0); + (void*)(unsigned long)current_pid(), + (void*)NULL, + (void*)NULL, + (void*)NULL); } #else #define xfs_itrunc_trace(tag, ip, flag, new_size, toss_start, toss_finish) @@ -1397,6 +1393,16 @@ xfs_itrunc_trace( * calling into the buffer/page cache code and we can't hold the * inode lock when we do so. * + * We need to wait for any direct I/Os in flight to complete before we + * proceed with the truncate. This is needed to prevent the extents + * being read or written by the direct I/Os from being removed while the + * I/O is in flight as there is no other method of synchronising + * direct I/O with the truncate operation. Also, because we hold + * the IOLOCK in exclusive mode, we prevent new direct I/Os from being + * started until the truncate completes and drops the lock. Essentially, + * the vn_iowait() call forms an I/O barrier that provides strict ordering + * between direct I/Os and the truncate operation. + * * The flags parameter can have either the value XFS_ITRUNC_DEFINITE * or XFS_ITRUNC_MAYBE. The XFS_ITRUNC_MAYBE value should be used * in the case that the caller is locking things out of order and @@ -1424,6 +1430,9 @@ xfs_itruncate_start( mp = ip->i_mount; vp = XFS_ITOV(ip); + + vn_iowait(vp); /* wait for the completion of any pending DIOs */ + /* * Call VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES() to get rid of pages and buffers * overlapping the region being removed. We have to use @@ -1899,7 +1908,7 @@ xfs_iunlink( * Here we put the head pointer into our next pointer, * and then we fall through to point the head at us. */ - error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); + error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0); if (error) { return error; } @@ -2008,7 +2017,7 @@ xfs_iunlink_remove( * of dealing with the buffer when there is no need to * change it. */ - error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); + error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0); if (error) { cmn_err(CE_WARN, "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.", @@ -2070,7 +2079,7 @@ xfs_iunlink_remove( * Now last_ibp points to the buffer previous to us on * the unlinked list. Pull us from the list. */ - error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); + error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0); if (error) { cmn_err(CE_WARN, "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.", @@ -2476,92 +2485,6 @@ xfs_iroot_realloc( /* - * This is called when the amount of space needed for if_extents - * is increased or decreased. The change in size is indicated by - * the number of extents that need to be added or deleted in the - * ext_diff parameter. - * - * If the amount of space needed has decreased below the size of the - * inline buffer, then switch to using the inline buffer. Otherwise, - * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer - * to what is needed. - * - * ip -- the inode whose if_extents area is changing - * ext_diff -- the change in the number of extents, positive or negative, - * requested for the if_extents array. - */ -void -xfs_iext_realloc( - xfs_inode_t *ip, - int ext_diff, - int whichfork) -{ - int byte_diff; - xfs_ifork_t *ifp; - int new_size; - uint rnew_size; - - if (ext_diff == 0) { - return; - } - - ifp = XFS_IFORK_PTR(ip, whichfork); - byte_diff = ext_diff * (uint)sizeof(xfs_bmbt_rec_t); - new_size = (int)ifp->if_bytes + byte_diff; - ASSERT(new_size >= 0); - - if (new_size == 0) { - if (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext) { - ASSERT(ifp->if_real_bytes != 0); - kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); - } - ifp->if_u1.if_extents = NULL; - rnew_size = 0; - } else if (new_size <= sizeof(ifp->if_u2.if_inline_ext)) { - /* - * If the valid extents can fit in if_inline_ext, - * copy them from the malloc'd vector and free it. - */ - if (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext) { - /* - * For now, empty files are format EXTENTS, - * so the if_extents pointer is null. - */ - if (ifp->if_u1.if_extents) { - memcpy(ifp->if_u2.if_inline_ext, - ifp->if_u1.if_extents, new_size); - kmem_free(ifp->if_u1.if_extents, - ifp->if_real_bytes); - } - ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; - } - rnew_size = 0; - } else { - rnew_size = new_size; - if ((rnew_size & (rnew_size - 1)) != 0) - rnew_size = xfs_iroundup(rnew_size); - /* - * Stuck with malloc/realloc. - */ - if (ifp->if_u1.if_extents == ifp->if_u2.if_inline_ext) { - ifp->if_u1.if_extents = (xfs_bmbt_rec_t *) - kmem_alloc(rnew_size, KM_SLEEP); - memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext, - sizeof(ifp->if_u2.if_inline_ext)); - } else if (rnew_size != ifp->if_real_bytes) { - ifp->if_u1.if_extents = (xfs_bmbt_rec_t *) - kmem_realloc(ifp->if_u1.if_extents, - rnew_size, - ifp->if_real_bytes, - KM_NOFS); - } - } - ifp->if_real_bytes = rnew_size; - ifp->if_bytes = new_size; -} - - -/* * This is called when the amount of space needed for if_data * is increased or decreased. The change in size is indicated by * the number of bytes that need to be added or deleted in the @@ -2720,12 +2643,11 @@ xfs_idestroy_fork( ifp->if_real_bytes = 0; } } else if ((ifp->if_flags & XFS_IFEXTENTS) && - (ifp->if_u1.if_extents != NULL) && - (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext)) { + ((ifp->if_flags & XFS_IFEXTIREC) || + ((ifp->if_u1.if_extents != NULL) && + (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext)))) { ASSERT(ifp->if_real_bytes != 0); - kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); - ifp->if_u1.if_extents = NULL; - ifp->if_real_bytes = 0; + xfs_iext_destroy(ifp); } ASSERT(ifp->if_u1.if_extents == NULL || ifp->if_u1.if_extents == ifp->if_u2.if_inline_ext); @@ -2814,7 +2736,7 @@ xfs_iunpin( /* make sync come back and flush this inode */ if (vp) { - struct inode *inode = LINVFS_GET_IP(vp); + struct inode *inode = vn_to_inode(vp); if (!(inode->i_state & I_NEW)) mark_inode_dirty_sync(inode); @@ -2902,16 +2824,15 @@ xfs_iextents_copy( * the delayed ones. There must be at least one * non-delayed extent. */ - ep = ifp->if_u1.if_extents; dest_ep = buffer; copied = 0; for (i = 0; i < nrecs; i++) { + ep = xfs_iext_get_ext(ifp, i); start_block = xfs_bmbt_get_startblock(ep); if (ISNULLSTARTBLOCK(start_block)) { /* * It's a delayed allocation extent, so skip it. */ - ep++; continue; } @@ -2921,11 +2842,10 @@ xfs_iextents_copy( put_unaligned(INT_GET(ep->l1, ARCH_CONVERT), (__uint64_t*)&dest_ep->l1); dest_ep++; - ep++; copied++; } ASSERT(copied != 0); - xfs_validate_extents(buffer, copied, 1, XFS_EXTFMT_INODE(ip)); + xfs_validate_extents(ifp, copied, 1, XFS_EXTFMT_INODE(ip)); return (copied * (uint)sizeof(xfs_bmbt_rec_t)); } @@ -2995,8 +2915,10 @@ xfs_iflush_fork( case XFS_DINODE_FMT_EXTENTS: ASSERT((ifp->if_flags & XFS_IFEXTENTS) || !(iip->ili_format.ilf_fields & extflag[whichfork])); - ASSERT((ifp->if_u1.if_extents != NULL) || (ifp->if_bytes == 0)); - ASSERT((ifp->if_u1.if_extents == NULL) || (ifp->if_bytes > 0)); + ASSERT((xfs_iext_get_ext(ifp, 0) != NULL) || + (ifp->if_bytes == 0)); + ASSERT((xfs_iext_get_ext(ifp, 0) == NULL) || + (ifp->if_bytes > 0)); if ((iip->ili_format.ilf_fields & extflag[whichfork]) && (ifp->if_bytes > 0)) { ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0); @@ -3114,8 +3036,8 @@ xfs_iflush( /* * Get the buffer containing the on-disk inode. */ - error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0); - if (error != 0) { + error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0); + if (error) { xfs_ifunlock(ip); return error; } @@ -3610,7 +3532,7 @@ xfs_iaccess( { int error; mode_t orgmode = mode; - struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); + struct inode *inode = vn_to_inode(XFS_ITOV(ip)); if (mode & S_IWUSR) { umode_t imode = inode->i_mode; @@ -3704,3 +3626,1100 @@ xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra) NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); } #endif + +/* + * Return a pointer to the extent record at file index idx. + */ +xfs_bmbt_rec_t * +xfs_iext_get_ext( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t idx) /* index of target extent */ +{ + ASSERT(idx >= 0); + if ((ifp->if_flags & XFS_IFEXTIREC) && (idx == 0)) { + return ifp->if_u1.if_ext_irec->er_extbuf; + } else if (ifp->if_flags & XFS_IFEXTIREC) { + xfs_ext_irec_t *erp; /* irec pointer */ + int erp_idx = 0; /* irec index */ + xfs_extnum_t page_idx = idx; /* ext index in target list */ + + erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 0); + return &erp->er_extbuf[page_idx]; + } else if (ifp->if_bytes) { + return &ifp->if_u1.if_extents[idx]; + } else { + return NULL; + } +} + +/* + * Insert new item(s) into the extent records for incore inode + * fork 'ifp'. 'count' new items are inserted at index 'idx'. + */ +void +xfs_iext_insert( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t idx, /* starting index of new items */ + xfs_extnum_t count, /* number of inserted items */ + xfs_bmbt_irec_t *new) /* items to insert */ +{ + xfs_bmbt_rec_t *ep; /* extent record pointer */ + xfs_extnum_t i; /* extent record index */ + + ASSERT(ifp->if_flags & XFS_IFEXTENTS); + xfs_iext_add(ifp, idx, count); + for (i = idx; i < idx + count; i++, new++) { + ep = xfs_iext_get_ext(ifp, i); + xfs_bmbt_set_all(ep, new); + } +} + +/* + * This is called when the amount of space required for incore file + * extents needs to be increased. The ext_diff parameter stores the + * number of new extents being added and the idx parameter contains + * the extent index where the new extents will be added. If the new + * extents are being appended, then we just need to (re)allocate and + * initialize the space. Otherwise, if the new extents are being + * inserted into the middle of the existing entries, a bit more work + * is required to make room for the new extents to be inserted. The + * caller is responsible for filling in the new extent entries upon + * return. + */ +void +xfs_iext_add( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t idx, /* index to begin adding exts */ + int ext_diff) /* nubmer of extents to add */ +{ + int byte_diff; /* new bytes being added */ + int new_size; /* size of extents after adding */ + xfs_extnum_t nextents; /* number of extents in file */ + + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + ASSERT((idx >= 0) && (idx <= nextents)); + byte_diff = ext_diff * sizeof(xfs_bmbt_rec_t); + new_size = ifp->if_bytes + byte_diff; + /* + * If the new number of extents (nextents + ext_diff) + * fits inside the inode, then continue to use the inline + * extent buffer. + */ + if (nextents + ext_diff <= XFS_INLINE_EXTS) { + if (idx < nextents) { + memmove(&ifp->if_u2.if_inline_ext[idx + ext_diff], + &ifp->if_u2.if_inline_ext[idx], + (nextents - idx) * sizeof(xfs_bmbt_rec_t)); + memset(&ifp->if_u2.if_inline_ext[idx], 0, byte_diff); + } + ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; + ifp->if_real_bytes = 0; + ifp->if_lastex = nextents + ext_diff; + } + /* + * Otherwise use a linear (direct) extent list. + * If the extents are currently inside the inode, + * xfs_iext_realloc_direct will switch us from + * inline to direct extent allocation mode. + */ + else if (nextents + ext_diff <= XFS_LINEAR_EXTS) { + xfs_iext_realloc_direct(ifp, new_size); + if (idx < nextents) { + memmove(&ifp->if_u1.if_extents[idx + ext_diff], + &ifp->if_u1.if_extents[idx], + (nextents - idx) * sizeof(xfs_bmbt_rec_t)); + memset(&ifp->if_u1.if_extents[idx], 0, byte_diff); + } + } + /* Indirection array */ + else { + xfs_ext_irec_t *erp; + int erp_idx = 0; + int page_idx = idx; + + ASSERT(nextents + ext_diff > XFS_LINEAR_EXTS); + if (ifp->if_flags & XFS_IFEXTIREC) { + erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 1); + } else { + xfs_iext_irec_init(ifp); + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + erp = ifp->if_u1.if_ext_irec; + } + /* Extents fit in target extent page */ + if (erp && erp->er_extcount + ext_diff <= XFS_LINEAR_EXTS) { + if (page_idx < erp->er_extcount) { + memmove(&erp->er_extbuf[page_idx + ext_diff], + &erp->er_extbuf[page_idx], + (erp->er_extcount - page_idx) * + sizeof(xfs_bmbt_rec_t)); + memset(&erp->er_extbuf[page_idx], 0, byte_diff); + } + erp->er_extcount += ext_diff; + xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff); + } + /* Insert a new extent page */ + else if (erp) { + xfs_iext_add_indirect_multi(ifp, + erp_idx, page_idx, ext_diff); + } + /* + * If extent(s) are being appended to the last page in + * the indirection array and the new extent(s) don't fit + * in the page, then erp is NULL and erp_idx is set to + * the next index needed in the indirection array. + */ + else { + int count = ext_diff; + + while (count) { + erp = xfs_iext_irec_new(ifp, erp_idx); + erp->er_extcount = count; + count -= MIN(count, (int)XFS_LINEAR_EXTS); + if (count) { + erp_idx++; + } + } + } + } + ifp->if_bytes = new_size; +} + +/* + * This is called when incore extents are being added to the indirection + * array and the new extents do not fit in the target extent list. The + * erp_idx parameter contains the irec index for the target extent list + * in the indirection array, and the idx parameter contains the extent + * index within the list. The number of extents being added is stored + * in the count parameter. + * + * |-------| |-------| + * | | | | idx - number of extents before idx + * | idx | | count | + * | | | | count - number of extents being inserted at idx + * |-------| |-------| + * | count | | nex2 | nex2 - number of extents after idx + count + * |-------| |-------| + */ +void +xfs_iext_add_indirect_multi( + xfs_ifork_t *ifp, /* inode fork pointer */ + int erp_idx, /* target extent irec index */ + xfs_extnum_t idx, /* index within target list */ + int count) /* new extents being added */ +{ + int byte_diff; /* new bytes being added */ + xfs_ext_irec_t *erp; /* pointer to irec entry */ + xfs_extnum_t ext_diff; /* number of extents to add */ + xfs_extnum_t ext_cnt; /* new extents still needed */ + xfs_extnum_t nex2; /* extents after idx + count */ + xfs_bmbt_rec_t *nex2_ep = NULL; /* temp list for nex2 extents */ + int nlists; /* number of irec's (lists) */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + nex2 = erp->er_extcount - idx; + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + + /* + * Save second part of target extent list + * (all extents past */ + if (nex2) { + byte_diff = nex2 * sizeof(xfs_bmbt_rec_t); + nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_SLEEP); + memmove(nex2_ep, &erp->er_extbuf[idx], byte_diff); + erp->er_extcount -= nex2; + xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -nex2); + memset(&erp->er_extbuf[idx], 0, byte_diff); + } + + /* + * Add the new extents to the end of the target + * list, then allocate new irec record(s) and + * extent buffer(s) as needed to store the rest + * of the new extents. + */ + ext_cnt = count; + ext_diff = MIN(ext_cnt, (int)XFS_LINEAR_EXTS - erp->er_extcount); + if (ext_diff) { + erp->er_extcount += ext_diff; + xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff); + ext_cnt -= ext_diff; + } + while (ext_cnt) { + erp_idx++; + erp = xfs_iext_irec_new(ifp, erp_idx); + ext_diff = MIN(ext_cnt, (int)XFS_LINEAR_EXTS); + erp->er_extcount = ext_diff; + xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff); + ext_cnt -= ext_diff; + } + + /* Add nex2 extents back to indirection array */ + if (nex2) { + xfs_extnum_t ext_avail; + int i; + + byte_diff = nex2 * sizeof(xfs_bmbt_rec_t); + ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; + i = 0; + /* + * If nex2 extents fit in the current page, append + * nex2_ep after the new extents. + */ + if (nex2 <= ext_avail) { + i = erp->er_extcount; + } + /* + * Otherwise, check if space is available in the + * next page. + */ + else if ((erp_idx < nlists - 1) && + (nex2 <= (ext_avail = XFS_LINEAR_EXTS - + ifp->if_u1.if_ext_irec[erp_idx+1].er_extcount))) { + erp_idx++; + erp++; + /* Create a hole for nex2 extents */ + memmove(&erp->er_extbuf[nex2], erp->er_extbuf, + erp->er_extcount * sizeof(xfs_bmbt_rec_t)); + } + /* + * Final choice, create a new extent page for + * nex2 extents. + */ + else { + erp_idx++; + erp = xfs_iext_irec_new(ifp, erp_idx); + } + memmove(&erp->er_extbuf[i], nex2_ep, byte_diff); + kmem_free(nex2_ep, byte_diff); + erp->er_extcount += nex2; + xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, nex2); + } +} + +/* + * This is called when the amount of space required for incore file + * extents needs to be decreased. The ext_diff parameter stores the + * number of extents to be removed and the idx parameter contains + * the extent index where the extents will be removed from. + * + * If the amount of space needed has decreased below the linear + * limit, XFS_IEXT_BUFSZ, then switch to using the contiguous + * extent array. Otherwise, use kmem_realloc() to adjust the + * size to what is needed. + */ +void +xfs_iext_remove( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t idx, /* index to begin removing exts */ + int ext_diff) /* number of extents to remove */ +{ + xfs_extnum_t nextents; /* number of extents in file */ + int new_size; /* size of extents after removal */ + + ASSERT(ext_diff > 0); + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + new_size = (nextents - ext_diff) * sizeof(xfs_bmbt_rec_t); + + if (new_size == 0) { + xfs_iext_destroy(ifp); + } else if (ifp->if_flags & XFS_IFEXTIREC) { + xfs_iext_remove_indirect(ifp, idx, ext_diff); + } else if (ifp->if_real_bytes) { + xfs_iext_remove_direct(ifp, idx, ext_diff); + } else { + xfs_iext_remove_inline(ifp, idx, ext_diff); + } + ifp->if_bytes = new_size; +} + +/* + * This removes ext_diff extents from the inline buffer, beginning + * at extent index idx. + */ +void +xfs_iext_remove_inline( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t idx, /* index to begin removing exts */ + int ext_diff) /* number of extents to remove */ +{ + int nextents; /* number of extents in file */ + + ASSERT(!(ifp->if_flags & XFS_IFEXTIREC)); + ASSERT(idx < XFS_INLINE_EXTS); + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + ASSERT(((nextents - ext_diff) > 0) && + (nextents - ext_diff) < XFS_INLINE_EXTS); + + if (idx + ext_diff < nextents) { + memmove(&ifp->if_u2.if_inline_ext[idx], + &ifp->if_u2.if_inline_ext[idx + ext_diff], + (nextents - (idx + ext_diff)) * + sizeof(xfs_bmbt_rec_t)); + memset(&ifp->if_u2.if_inline_ext[nextents - ext_diff], + 0, ext_diff * sizeof(xfs_bmbt_rec_t)); + } else { + memset(&ifp->if_u2.if_inline_ext[idx], 0, + ext_diff * sizeof(xfs_bmbt_rec_t)); + } +} + +/* + * This removes ext_diff extents from a linear (direct) extent list, + * beginning at extent index idx. If the extents are being removed + * from the end of the list (ie. truncate) then we just need to re- + * allocate the list to remove the extra space. Otherwise, if the + * extents are being removed from the middle of the existing extent + * entries, then we first need to move the extent records beginning + * at idx + ext_diff up in the list to overwrite the records being + * removed, then remove the extra space via kmem_realloc. + */ +void +xfs_iext_remove_direct( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t idx, /* index to begin removing exts */ + int ext_diff) /* number of extents to remove */ +{ + xfs_extnum_t nextents; /* number of extents in file */ + int new_size; /* size of extents after removal */ + + ASSERT(!(ifp->if_flags & XFS_IFEXTIREC)); + new_size = ifp->if_bytes - + (ext_diff * sizeof(xfs_bmbt_rec_t)); + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + + if (new_size == 0) { + xfs_iext_destroy(ifp); + return; + } + /* Move extents up in the list (if needed) */ + if (idx + ext_diff < nextents) { + memmove(&ifp->if_u1.if_extents[idx], + &ifp->if_u1.if_extents[idx + ext_diff], + (nextents - (idx + ext_diff)) * + sizeof(xfs_bmbt_rec_t)); + } + memset(&ifp->if_u1.if_extents[nextents - ext_diff], + 0, ext_diff * sizeof(xfs_bmbt_rec_t)); + /* + * Reallocate the direct extent list. If the extents + * will fit inside the inode then xfs_iext_realloc_direct + * will switch from direct to inline extent allocation + * mode for us. + */ + xfs_iext_realloc_direct(ifp, new_size); + ifp->if_bytes = new_size; +} + +/* + * This is called when incore extents are being removed from the + * indirection array and the extents being removed span multiple extent + * buffers. The idx parameter contains the file extent index where we + * want to begin removing extents, and the count parameter contains + * how many extents need to be removed. + * + * |-------| |-------| + * | nex1 | | | nex1 - number of extents before idx + * |-------| | count | + * | | | | count - number of extents being removed at idx + * | count | |-------| + * | | | nex2 | nex2 - number of extents after idx + count + * |-------| |-------| + */ +void +xfs_iext_remove_indirect( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t idx, /* index to begin removing extents */ + int count) /* number of extents to remove */ +{ + xfs_ext_irec_t *erp; /* indirection array pointer */ + int erp_idx = 0; /* indirection array index */ + xfs_extnum_t ext_cnt; /* extents left to remove */ + xfs_extnum_t ext_diff; /* extents to remove in current list */ + xfs_extnum_t nex1; /* number of extents before idx */ + xfs_extnum_t nex2; /* extents after idx + count */ + int nlists; /* entries in indirecton array */ + int page_idx = idx; /* index in target extent list */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 0); + ASSERT(erp != NULL); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + nex1 = page_idx; + ext_cnt = count; + while (ext_cnt) { + nex2 = MAX((erp->er_extcount - (nex1 + ext_cnt)), 0); + ext_diff = MIN(ext_cnt, (erp->er_extcount - nex1)); + /* + * Check for deletion of entire list; + * xfs_iext_irec_remove() updates extent offsets. + */ + if (ext_diff == erp->er_extcount) { + xfs_iext_irec_remove(ifp, erp_idx); + ext_cnt -= ext_diff; + nex1 = 0; + if (ext_cnt) { + ASSERT(erp_idx < ifp->if_real_bytes / + XFS_IEXT_BUFSZ); + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + nex1 = 0; + continue; + } else { + break; + } + } + /* Move extents up (if needed) */ + if (nex2) { + memmove(&erp->er_extbuf[nex1], + &erp->er_extbuf[nex1 + ext_diff], + nex2 * sizeof(xfs_bmbt_rec_t)); + } + /* Zero out rest of page */ + memset(&erp->er_extbuf[nex1 + nex2], 0, (XFS_IEXT_BUFSZ - + ((nex1 + nex2) * sizeof(xfs_bmbt_rec_t)))); + /* Update remaining counters */ + erp->er_extcount -= ext_diff; + xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -ext_diff); + ext_cnt -= ext_diff; + nex1 = 0; + erp_idx++; + erp++; + } + ifp->if_bytes -= count * sizeof(xfs_bmbt_rec_t); + xfs_iext_irec_compact(ifp); +} + +/* + * Create, destroy, or resize a linear (direct) block of extents. + */ +void +xfs_iext_realloc_direct( + xfs_ifork_t *ifp, /* inode fork pointer */ + int new_size) /* new size of extents */ +{ + int rnew_size; /* real new size of extents */ + + rnew_size = new_size; + + ASSERT(!(ifp->if_flags & XFS_IFEXTIREC) || + ((new_size >= 0) && (new_size <= XFS_IEXT_BUFSZ) && + (new_size != ifp->if_real_bytes))); + + /* Free extent records */ + if (new_size == 0) { + xfs_iext_destroy(ifp); + } + /* Resize direct extent list and zero any new bytes */ + else if (ifp->if_real_bytes) { + /* Check if extents will fit inside the inode */ + if (new_size <= XFS_INLINE_EXTS * sizeof(xfs_bmbt_rec_t)) { + xfs_iext_direct_to_inline(ifp, new_size / + (uint)sizeof(xfs_bmbt_rec_t)); + ifp->if_bytes = new_size; + return; + } + if ((new_size & (new_size - 1)) != 0) { + rnew_size = xfs_iroundup(new_size); + } + if (rnew_size != ifp->if_real_bytes) { + ifp->if_u1.if_extents = (xfs_bmbt_rec_t *) + kmem_realloc(ifp->if_u1.if_extents, + rnew_size, + ifp->if_real_bytes, + KM_SLEEP); + } + if (rnew_size > ifp->if_real_bytes) { + memset(&ifp->if_u1.if_extents[ifp->if_bytes / + (uint)sizeof(xfs_bmbt_rec_t)], 0, + rnew_size - ifp->if_real_bytes); + } + } + /* + * Switch from the inline extent buffer to a direct + * extent list. Be sure to include the inline extent + * bytes in new_size. + */ + else { + new_size += ifp->if_bytes; + if ((new_size & (new_size - 1)) != 0) { + rnew_size = xfs_iroundup(new_size); + } + xfs_iext_inline_to_direct(ifp, rnew_size); + } + ifp->if_real_bytes = rnew_size; + ifp->if_bytes = new_size; +} + +/* + * Switch from linear (direct) extent records to inline buffer. + */ +void +xfs_iext_direct_to_inline( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t nextents) /* number of extents in file */ +{ + ASSERT(ifp->if_flags & XFS_IFEXTENTS); + ASSERT(nextents <= XFS_INLINE_EXTS); + /* + * The inline buffer was zeroed when we switched + * from inline to direct extent allocation mode, + * so we don't need to clear it here. + */ + memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, + nextents * sizeof(xfs_bmbt_rec_t)); + kmem_free(ifp->if_u1.if_extents, KM_SLEEP); + ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; + ifp->if_real_bytes = 0; +} + +/* + * Switch from inline buffer to linear (direct) extent records. + * new_size should already be rounded up to the next power of 2 + * by the caller (when appropriate), so use new_size as it is. + * However, since new_size may be rounded up, we can't update + * if_bytes here. It is the caller's responsibility to update + * if_bytes upon return. + */ +void +xfs_iext_inline_to_direct( + xfs_ifork_t *ifp, /* inode fork pointer */ + int new_size) /* number of extents in file */ +{ + ifp->if_u1.if_extents = (xfs_bmbt_rec_t *) + kmem_alloc(new_size, KM_SLEEP); + memset(ifp->if_u1.if_extents, 0, new_size); + if (ifp->if_bytes) { + memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext, + ifp->if_bytes); + memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS * + sizeof(xfs_bmbt_rec_t)); + } + ifp->if_real_bytes = new_size; +} + +/* + * Resize an extent indirection array to new_size bytes. + */ +void +xfs_iext_realloc_indirect( + xfs_ifork_t *ifp, /* inode fork pointer */ + int new_size) /* new indirection array size */ +{ + int nlists; /* number of irec's (ex lists) */ + int size; /* current indirection array size */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + size = nlists * sizeof(xfs_ext_irec_t); + ASSERT(ifp->if_real_bytes); + ASSERT((new_size >= 0) && (new_size != size)); + if (new_size == 0) { + xfs_iext_destroy(ifp); + } else { + ifp->if_u1.if_ext_irec = (xfs_ext_irec_t *) + kmem_realloc(ifp->if_u1.if_ext_irec, + new_size, size, KM_SLEEP); + } +} + +/* + * Switch from indirection array to linear (direct) extent allocations. + */ +void +xfs_iext_indirect_to_direct( + xfs_ifork_t *ifp) /* inode fork pointer */ +{ + xfs_bmbt_rec_t *ep; /* extent record pointer */ + xfs_extnum_t nextents; /* number of extents in file */ + int size; /* size of file extents */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + ASSERT(nextents <= XFS_LINEAR_EXTS); + size = nextents * sizeof(xfs_bmbt_rec_t); + + xfs_iext_irec_compact_full(ifp); + ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); + + ep = ifp->if_u1.if_ext_irec->er_extbuf; + kmem_free(ifp->if_u1.if_ext_irec, sizeof(xfs_ext_irec_t)); + ifp->if_flags &= ~XFS_IFEXTIREC; + ifp->if_u1.if_extents = ep; + ifp->if_bytes = size; + if (nextents < XFS_LINEAR_EXTS) { + xfs_iext_realloc_direct(ifp, size); + } +} + +/* + * Free incore file extents. + */ +void +xfs_iext_destroy( + xfs_ifork_t *ifp) /* inode fork pointer */ +{ + if (ifp->if_flags & XFS_IFEXTIREC) { + int erp_idx; + int nlists; + + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + for (erp_idx = nlists - 1; erp_idx >= 0 ; erp_idx--) { + xfs_iext_irec_remove(ifp, erp_idx); + } + ifp->if_flags &= ~XFS_IFEXTIREC; + } else if (ifp->if_real_bytes) { + kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); + } else if (ifp->if_bytes) { + memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS * + sizeof(xfs_bmbt_rec_t)); + } + ifp->if_u1.if_extents = NULL; + ifp->if_real_bytes = 0; + ifp->if_bytes = 0; +} + +/* + * Return a pointer to the extent record for file system block bno. + */ +xfs_bmbt_rec_t * /* pointer to found extent record */ +xfs_iext_bno_to_ext( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_fileoff_t bno, /* block number to search for */ + xfs_extnum_t *idxp) /* index of target extent */ +{ + xfs_bmbt_rec_t *base; /* pointer to first extent */ + xfs_filblks_t blockcount = 0; /* number of blocks in extent */ + xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */ + xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ + int high; /* upper boundry in search */ + xfs_extnum_t idx = 0; /* index of target extent */ + int low; /* lower boundry in search */ + xfs_extnum_t nextents; /* number of file extents */ + xfs_fileoff_t startoff = 0; /* start offset of extent */ + + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + if (nextents == 0) { + *idxp = 0; + return NULL; + } + low = 0; + if (ifp->if_flags & XFS_IFEXTIREC) { + /* Find target extent list */ + int erp_idx = 0; + erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx); + base = erp->er_extbuf; + high = erp->er_extcount - 1; + } else { + base = ifp->if_u1.if_extents; + high = nextents - 1; + } + /* Binary search extent records */ + while (low <= high) { + idx = (low + high) >> 1; + ep = base + idx; + startoff = xfs_bmbt_get_startoff(ep); + blockcount = xfs_bmbt_get_blockcount(ep); + if (bno < startoff) { + high = idx - 1; + } else if (bno >= startoff + blockcount) { + low = idx + 1; + } else { + /* Convert back to file-based extent index */ + if (ifp->if_flags & XFS_IFEXTIREC) { + idx += erp->er_extoff; + } + *idxp = idx; + return ep; + } + } + /* Convert back to file-based extent index */ + if (ifp->if_flags & XFS_IFEXTIREC) { + idx += erp->er_extoff; + } + if (bno >= startoff + blockcount) { + if (++idx == nextents) { + ep = NULL; + } else { + ep = xfs_iext_get_ext(ifp, idx); + } + } + *idxp = idx; + return ep; +} + +/* + * Return a pointer to the indirection array entry containing the + * extent record for filesystem block bno. Store the index of the + * target irec in *erp_idxp. + */ +xfs_ext_irec_t * /* pointer to found extent record */ +xfs_iext_bno_to_irec( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_fileoff_t bno, /* block number to search for */ + int *erp_idxp) /* irec index of target ext list */ +{ + xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ + xfs_ext_irec_t *erp_next; /* next indirection array entry */ + int erp_idx; /* indirection array index */ + int nlists; /* number of extent irec's (lists) */ + int high; /* binary search upper limit */ + int low; /* binary search lower limit */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + erp_idx = 0; + low = 0; + high = nlists - 1; + while (low <= high) { + erp_idx = (low + high) >> 1; + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + erp_next = erp_idx < nlists - 1 ? erp + 1 : NULL; + if (bno < xfs_bmbt_get_startoff(erp->er_extbuf)) { + high = erp_idx - 1; + } else if (erp_next && bno >= + xfs_bmbt_get_startoff(erp_next->er_extbuf)) { + low = erp_idx + 1; + } else { + break; + } + } + *erp_idxp = erp_idx; + return erp; +} + +/* + * Return a pointer to the indirection array entry containing the + * extent record at file extent index *idxp. Store the index of the + * target irec in *erp_idxp and store the page index of the target + * extent record in *idxp. + */ +xfs_ext_irec_t * +xfs_iext_idx_to_irec( + xfs_ifork_t *ifp, /* inode fork pointer */ + xfs_extnum_t *idxp, /* extent index (file -> page) */ + int *erp_idxp, /* pointer to target irec */ + int realloc) /* new bytes were just added */ +{ + xfs_ext_irec_t *prev; /* pointer to previous irec */ + xfs_ext_irec_t *erp = NULL; /* pointer to current irec */ + int erp_idx; /* indirection array index */ + int nlists; /* number of irec's (ex lists) */ + int high; /* binary search upper limit */ + int low; /* binary search lower limit */ + xfs_extnum_t page_idx = *idxp; /* extent index in target list */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + ASSERT(page_idx >= 0 && page_idx <= + ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + erp_idx = 0; + low = 0; + high = nlists - 1; + + /* Binary search extent irec's */ + while (low <= high) { + erp_idx = (low + high) >> 1; + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + prev = erp_idx > 0 ? erp - 1 : NULL; + if (page_idx < erp->er_extoff || (page_idx == erp->er_extoff && + realloc && prev && prev->er_extcount < XFS_LINEAR_EXTS)) { + high = erp_idx - 1; + } else if (page_idx > erp->er_extoff + erp->er_extcount || + (page_idx == erp->er_extoff + erp->er_extcount && + !realloc)) { + low = erp_idx + 1; + } else if (page_idx == erp->er_extoff + erp->er_extcount && + erp->er_extcount == XFS_LINEAR_EXTS) { + ASSERT(realloc); + page_idx = 0; + erp_idx++; + erp = erp_idx < nlists ? erp + 1 : NULL; + break; + } else { + page_idx -= erp->er_extoff; + break; + } + } + *idxp = page_idx; + *erp_idxp = erp_idx; + return(erp); +} + +/* + * Allocate and initialize an indirection array once the space needed + * for incore extents increases above XFS_IEXT_BUFSZ. + */ +void +xfs_iext_irec_init( + xfs_ifork_t *ifp) /* inode fork pointer */ +{ + xfs_ext_irec_t *erp; /* indirection array pointer */ + xfs_extnum_t nextents; /* number of extents in file */ + + ASSERT(!(ifp->if_flags & XFS_IFEXTIREC)); + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + ASSERT(nextents <= XFS_LINEAR_EXTS); + + erp = (xfs_ext_irec_t *) + kmem_alloc(sizeof(xfs_ext_irec_t), KM_SLEEP); + + if (nextents == 0) { + ifp->if_u1.if_extents = (xfs_bmbt_rec_t *) + kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP); + } else if (!ifp->if_real_bytes) { + xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ); + } else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) { + xfs_iext_realloc_direct(ifp, XFS_IEXT_BUFSZ); + } + erp->er_extbuf = ifp->if_u1.if_extents; + erp->er_extcount = nextents; + erp->er_extoff = 0; + + ifp->if_flags |= XFS_IFEXTIREC; + ifp->if_real_bytes = XFS_IEXT_BUFSZ; + ifp->if_bytes = nextents * sizeof(xfs_bmbt_rec_t); + ifp->if_u1.if_ext_irec = erp; + + return; +} + +/* + * Allocate and initialize a new entry in the indirection array. + */ +xfs_ext_irec_t * +xfs_iext_irec_new( + xfs_ifork_t *ifp, /* inode fork pointer */ + int erp_idx) /* index for new irec */ +{ + xfs_ext_irec_t *erp; /* indirection array pointer */ + int i; /* loop counter */ + int nlists; /* number of irec's (ex lists) */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + + /* Resize indirection array */ + xfs_iext_realloc_indirect(ifp, ++nlists * + sizeof(xfs_ext_irec_t)); + /* + * Move records down in the array so the + * new page can use erp_idx. + */ + erp = ifp->if_u1.if_ext_irec; + for (i = nlists - 1; i > erp_idx; i--) { + memmove(&erp[i], &erp[i-1], sizeof(xfs_ext_irec_t)); + } + ASSERT(i == erp_idx); + + /* Initialize new extent record */ + erp = ifp->if_u1.if_ext_irec; + erp[erp_idx].er_extbuf = (xfs_bmbt_rec_t *) + kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP); + ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; + memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ); + erp[erp_idx].er_extcount = 0; + erp[erp_idx].er_extoff = erp_idx > 0 ? + erp[erp_idx-1].er_extoff + erp[erp_idx-1].er_extcount : 0; + return (&erp[erp_idx]); +} + +/* + * Remove a record from the indirection array. + */ +void +xfs_iext_irec_remove( + xfs_ifork_t *ifp, /* inode fork pointer */ + int erp_idx) /* irec index to remove */ +{ + xfs_ext_irec_t *erp; /* indirection array pointer */ + int i; /* loop counter */ + int nlists; /* number of irec's (ex lists) */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + if (erp->er_extbuf) { + xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, + -erp->er_extcount); + kmem_free(erp->er_extbuf, XFS_IEXT_BUFSZ); + } + /* Compact extent records */ + erp = ifp->if_u1.if_ext_irec; + for (i = erp_idx; i < nlists - 1; i++) { + memmove(&erp[i], &erp[i+1], sizeof(xfs_ext_irec_t)); + } + /* + * Manually free the last extent record from the indirection + * array. A call to xfs_iext_realloc_indirect() with a size + * of zero would result in a call to xfs_iext_destroy() which + * would in turn call this function again, creating a nasty + * infinite loop. + */ + if (--nlists) { + xfs_iext_realloc_indirect(ifp, + nlists * sizeof(xfs_ext_irec_t)); + } else { + kmem_free(ifp->if_u1.if_ext_irec, + sizeof(xfs_ext_irec_t)); + } + ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; +} + +/* + * This is called to clean up large amounts of unused memory allocated + * by the indirection array. Before compacting anything though, verify + * that the indirection array is still needed and switch back to the + * linear extent list (or even the inline buffer) if possible. The + * compaction policy is as follows: + * + * Full Compaction: Extents fit into a single page (or inline buffer) + * Full Compaction: Extents occupy less than 10% of allocated space + * Partial Compaction: Extents occupy > 10% and < 50% of allocated space + * No Compaction: Extents occupy at least 50% of allocated space + */ +void +xfs_iext_irec_compact( + xfs_ifork_t *ifp) /* inode fork pointer */ +{ + xfs_extnum_t nextents; /* number of extents in file */ + int nlists; /* number of irec's (ex lists) */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); + + if (nextents == 0) { + xfs_iext_destroy(ifp); + } else if (nextents <= XFS_INLINE_EXTS) { + xfs_iext_indirect_to_direct(ifp); + xfs_iext_direct_to_inline(ifp, nextents); + } else if (nextents <= XFS_LINEAR_EXTS) { + xfs_iext_indirect_to_direct(ifp); + } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 3) { + xfs_iext_irec_compact_full(ifp); + } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) { + xfs_iext_irec_compact_pages(ifp); + } +} + +/* + * Combine extents from neighboring extent pages. + */ +void +xfs_iext_irec_compact_pages( + xfs_ifork_t *ifp) /* inode fork pointer */ +{ + xfs_ext_irec_t *erp, *erp_next;/* pointers to irec entries */ + int erp_idx = 0; /* indirection array index */ + int nlists; /* number of irec's (ex lists) */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + while (erp_idx < nlists - 1) { + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + erp_next = erp + 1; + if (erp_next->er_extcount <= + (XFS_LINEAR_EXTS - erp->er_extcount)) { + memmove(&erp->er_extbuf[erp->er_extcount], + erp_next->er_extbuf, erp_next->er_extcount * + sizeof(xfs_bmbt_rec_t)); + erp->er_extcount += erp_next->er_extcount; + /* + * Free page before removing extent record + * so er_extoffs don't get modified in + * xfs_iext_irec_remove. + */ + kmem_free(erp_next->er_extbuf, XFS_IEXT_BUFSZ); + erp_next->er_extbuf = NULL; + xfs_iext_irec_remove(ifp, erp_idx + 1); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + } else { + erp_idx++; + } + } +} + +/* + * Fully compact the extent records managed by the indirection array. + */ +void +xfs_iext_irec_compact_full( + xfs_ifork_t *ifp) /* inode fork pointer */ +{ + xfs_bmbt_rec_t *ep, *ep_next; /* extent record pointers */ + xfs_ext_irec_t *erp, *erp_next; /* extent irec pointers */ + int erp_idx = 0; /* extent irec index */ + int ext_avail; /* empty entries in ex list */ + int ext_diff; /* number of exts to add */ + int nlists; /* number of irec's (ex lists) */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + erp = ifp->if_u1.if_ext_irec; + ep = &erp->er_extbuf[erp->er_extcount]; + erp_next = erp + 1; + ep_next = erp_next->er_extbuf; + while (erp_idx < nlists - 1) { + ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; + ext_diff = MIN(ext_avail, erp_next->er_extcount); + memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); + erp->er_extcount += ext_diff; + erp_next->er_extcount -= ext_diff; + /* Remove next page */ + if (erp_next->er_extcount == 0) { + /* + * Free page before removing extent record + * so er_extoffs don't get modified in + * xfs_iext_irec_remove. + */ + kmem_free(erp_next->er_extbuf, + erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); + erp_next->er_extbuf = NULL; + xfs_iext_irec_remove(ifp, erp_idx + 1); + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + /* Update next page */ + } else { + /* Move rest of page up to become next new page */ + memmove(erp_next->er_extbuf, ep_next, + erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); + ep_next = erp_next->er_extbuf; + memset(&ep_next[erp_next->er_extcount], 0, + (XFS_LINEAR_EXTS - erp_next->er_extcount) * + sizeof(xfs_bmbt_rec_t)); + } + if (erp->er_extcount == XFS_LINEAR_EXTS) { + erp_idx++; + if (erp_idx < nlists) + erp = &ifp->if_u1.if_ext_irec[erp_idx]; + else + break; + } + ep = &erp->er_extbuf[erp->er_extcount]; + erp_next = erp + 1; + ep_next = erp_next->er_extbuf; + } +} + +/* + * This is called to update the er_extoff field in the indirection + * array when extents have been added or removed from one of the + * extent lists. erp_idx contains the irec index to begin updating + * at and ext_diff contains the number of extents that were added + * or removed. + */ +void +xfs_iext_irec_update_extoffs( + xfs_ifork_t *ifp, /* inode fork pointer */ + int erp_idx, /* irec index to update */ + int ext_diff) /* number of new extents */ +{ + int i; /* loop counter */ + int nlists; /* number of irec's (ex lists */ + + ASSERT(ifp->if_flags & XFS_IFEXTIREC); + nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; + for (i = erp_idx; i < nlists; i++) { + ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff; + } +} diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 1cfbcf18ce86..39ef9c36ea55 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -25,10 +25,37 @@ #define XFS_ATTR_FORK 1 /* + * The following xfs_ext_irec_t struct introduces a second (top) level + * to the in-core extent allocation scheme. These structs are allocated + * in a contiguous block, creating an indirection array where each entry + * (irec) contains a pointer to a buffer of in-core extent records which + * it manages. Each extent buffer is 4k in size, since 4k is the system + * page size on Linux i386 and systems with larger page sizes don't seem + * to gain much, if anything, by using their native page size as the + * extent buffer size. Also, using 4k extent buffers everywhere provides + * a consistent interface for CXFS across different platforms. + * + * There is currently no limit on the number of irec's (extent lists) + * allowed, so heavily fragmented files may require an indirection array + * which spans multiple system pages of memory. The number of extents + * which would require this amount of contiguous memory is very large + * and should not cause problems in the foreseeable future. However, + * if the memory needed for the contiguous array ever becomes a problem, + * it is possible that a third level of indirection may be required. + */ +typedef struct xfs_ext_irec { + xfs_bmbt_rec_t *er_extbuf; /* block of extent records */ + xfs_extnum_t er_extoff; /* extent offset in file */ + xfs_extnum_t er_extcount; /* number of extents in page/block */ +} xfs_ext_irec_t; + +/* * File incore extent information, present for each of data & attr forks. */ -#define XFS_INLINE_EXTS 2 -#define XFS_INLINE_DATA 32 +#define XFS_IEXT_BUFSZ 4096 +#define XFS_LINEAR_EXTS (XFS_IEXT_BUFSZ / (uint)sizeof(xfs_bmbt_rec_t)) +#define XFS_INLINE_EXTS 2 +#define XFS_INLINE_DATA 32 typedef struct xfs_ifork { int if_bytes; /* bytes in if_u1 */ int if_real_bytes; /* bytes allocated in if_u1 */ @@ -39,6 +66,7 @@ typedef struct xfs_ifork { xfs_extnum_t if_lastex; /* last if_extents used */ union { xfs_bmbt_rec_t *if_extents; /* linear map file exts */ + xfs_ext_irec_t *if_ext_irec; /* irec map file exts */ char *if_data; /* inline file data */ } if_u1; union { @@ -61,20 +89,16 @@ typedef struct xfs_ifork { /* * Per-fork incore inode flags. */ -#define XFS_IFINLINE 0x0001 /* Inline data is read in */ -#define XFS_IFEXTENTS 0x0002 /* All extent pointers are read in */ -#define XFS_IFBROOT 0x0004 /* i_broot points to the bmap b-tree root */ +#define XFS_IFINLINE 0x01 /* Inline data is read in */ +#define XFS_IFEXTENTS 0x02 /* All extent pointers are read in */ +#define XFS_IFBROOT 0x04 /* i_broot points to the bmap b-tree root */ +#define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */ /* - * Flags for xfs_imap() and xfs_dilocate(). + * Flags for xfs_itobp(), xfs_imap() and xfs_dilocate(). */ -#define XFS_IMAP_LOOKUP 0x1 - -/* - * Maximum number of extent pointers in if_u1.if_extents. - */ -#define XFS_MAX_INCORE_EXTENTS 32768 - +#define XFS_IMAP_LOOKUP 0x1 +#define XFS_IMAP_BULKSTAT 0x2 #ifdef __KERNEL__ struct bhv_desc; @@ -398,7 +422,7 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int); */ int xfs_itobp(struct xfs_mount *, struct xfs_trans *, xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **, - xfs_daddr_t); + xfs_daddr_t, uint); int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, xfs_inode_t **, xfs_daddr_t); int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int); @@ -440,6 +464,32 @@ xfs_inode_t *xfs_vtoi(struct vnode *vp); void xfs_synchronize_atime(xfs_inode_t *); +xfs_bmbt_rec_t *xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t); +void xfs_iext_insert(xfs_ifork_t *, xfs_extnum_t, xfs_extnum_t, + xfs_bmbt_irec_t *); +void xfs_iext_add(xfs_ifork_t *, xfs_extnum_t, int); +void xfs_iext_add_indirect_multi(xfs_ifork_t *, int, xfs_extnum_t, int); +void xfs_iext_remove(xfs_ifork_t *, xfs_extnum_t, int); +void xfs_iext_remove_inline(xfs_ifork_t *, xfs_extnum_t, int); +void xfs_iext_remove_direct(xfs_ifork_t *, xfs_extnum_t, int); +void xfs_iext_remove_indirect(xfs_ifork_t *, xfs_extnum_t, int); +void xfs_iext_realloc_direct(xfs_ifork_t *, int); +void xfs_iext_realloc_indirect(xfs_ifork_t *, int); +void xfs_iext_indirect_to_direct(xfs_ifork_t *); +void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t); +void xfs_iext_inline_to_direct(xfs_ifork_t *, int); +void xfs_iext_destroy(xfs_ifork_t *); +xfs_bmbt_rec_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *); +xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *); +xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int); +void xfs_iext_irec_init(xfs_ifork_t *); +xfs_ext_irec_t *xfs_iext_irec_new(xfs_ifork_t *, int); +void xfs_iext_irec_remove(xfs_ifork_t *, int); +void xfs_iext_irec_compact(xfs_ifork_t *); +void xfs_iext_irec_compact_pages(xfs_ifork_t *); +void xfs_iext_irec_compact_full(xfs_ifork_t *); +void xfs_iext_irec_update_extoffs(xfs_ifork_t *, int, int); + #define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount)) #ifdef DEBUG diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 788917f355c4..d5dfedcb8922 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -76,7 +76,7 @@ xfs_iomap_enter_trace( (void *)((unsigned long)count), (void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)), (void *)((unsigned long)(io->io_new_size & 0xffffffff)), - (void *)NULL, + (void *)((unsigned long)current_pid()), (void *)NULL, (void *)NULL, (void *)NULL, diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index c59450e1be40..32247b6bfee7 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -562,7 +562,8 @@ xfs_bulkstat( if (bp) xfs_buf_relse(bp); error = xfs_itobp(mp, NULL, ip, - &dip, &bp, bno); + &dip, &bp, bno, + XFS_IMAP_BULKSTAT); if (!error) clustidx = ip->i_boffset / mp->m_sb.sb_inodesize; kmem_zone_free(xfs_inode_zone, ip); @@ -570,6 +571,8 @@ xfs_bulkstat( mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK, XFS_RANDOM_BULKSTAT_READ_CHUNK)) { bp = NULL; + ubleft = 0; + rval = error; break; } } diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 7d46cbd6a07a..add13f507ed2 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3249,7 +3249,7 @@ xlog_recover_process_iunlinks( * next inode in the bucket. */ error = xfs_itobp(mp, NULL, ip, &dip, - &ibp, 0); + &ibp, 0, 0); ASSERT(error || (dip != NULL)); } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 62188ea392c7..20e8abc16d18 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -51,11 +51,32 @@ STATIC int xfs_uuid_mount(xfs_mount_t *); STATIC void xfs_uuid_unmount(xfs_mount_t *mp); STATIC void xfs_unmountfs_wait(xfs_mount_t *); + +#ifdef HAVE_PERCPU_SB +STATIC void xfs_icsb_destroy_counters(xfs_mount_t *); +STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, int); +STATIC void xfs_icsb_sync_counters(xfs_mount_t *); +STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t, + int, int); +STATIC int xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t, + int, int); +STATIC int xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t); + +#else + +#define xfs_icsb_destroy_counters(mp) do { } while (0) +#define xfs_icsb_balance_counter(mp, a, b) do { } while (0) +#define xfs_icsb_sync_counters(mp) do { } while (0) +#define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0) +#define xfs_icsb_modify_counters_locked(mp, a, b, c) do { } while (0) + +#endif + static const struct { - short offset; - short type; /* 0 = integer - * 1 = binary / string (no translation) - */ + short offset; + short type; /* 0 = integer + * 1 = binary / string (no translation) + */ } xfs_sb_info[] = { { offsetof(xfs_sb_t, sb_magicnum), 0 }, { offsetof(xfs_sb_t, sb_blocksize), 0 }, @@ -113,7 +134,11 @@ xfs_mount_init(void) { xfs_mount_t *mp; - mp = kmem_zalloc(sizeof(*mp), KM_SLEEP); + mp = kmem_zalloc(sizeof(xfs_mount_t), KM_SLEEP); + + if (xfs_icsb_init_counters(mp)) { + mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB; + } AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail"); spinlock_init(&mp->m_sb_lock, "xfs_sb"); @@ -136,8 +161,8 @@ xfs_mount_init(void) */ void xfs_mount_free( - xfs_mount_t *mp, - int remove_bhv) + xfs_mount_t *mp, + int remove_bhv) { if (mp->m_ihash) xfs_ihash_free(mp); @@ -177,6 +202,7 @@ xfs_mount_free( VFS_REMOVEBHV(vfsp, &mp->m_bhv); } + xfs_icsb_destroy_counters(mp); kmem_free(mp, sizeof(xfs_mount_t)); } @@ -242,9 +268,12 @@ xfs_mount_validate_sb( sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || + sbp->sb_inodelog < XFS_DINODE_MIN_LOG || + sbp->sb_inodelog > XFS_DINODE_MAX_LOG || + (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) || (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || - sbp->sb_imax_pct > 100)) { + (sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) { cmn_err(CE_WARN, "XFS: SB sanity check 1 failed"); XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)", XFS_ERRLEVEL_LOW, mp, sbp); @@ -527,6 +556,10 @@ xfs_readsb(xfs_mount_t *mp) ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); } + xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); + xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); + xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); + mp->m_sb_bp = bp; xfs_buf_relse(bp); ASSERT(XFS_BUF_VALUSEMA(bp) > 0); @@ -1154,6 +1187,9 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) sbp = xfs_getsb(mp, 0); if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY || XFS_FORCED_SHUTDOWN(mp))) { + + xfs_icsb_sync_counters(mp); + /* * mark shared-readonly if desired */ @@ -1227,7 +1263,6 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) xfs_trans_log_buf(tp, bp, first, last); } - /* * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply * a delta to a specified field in the in-core superblock. Simply @@ -1237,7 +1272,7 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) * * The SB_LOCK must be held when this routine is called. */ -STATIC int +int xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd) { @@ -1406,9 +1441,26 @@ xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd) unsigned long s; int status; - s = XFS_SB_LOCK(mp); - status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); - XFS_SB_UNLOCK(mp, s); + /* check for per-cpu counters */ + switch (field) { +#ifdef HAVE_PERCPU_SB + case XFS_SBS_ICOUNT: + case XFS_SBS_IFREE: + case XFS_SBS_FDBLOCKS: + if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { + status = xfs_icsb_modify_counters(mp, field, + delta, rsvd); + break; + } + /* FALLTHROUGH */ +#endif + default: + s = XFS_SB_LOCK(mp); + status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); + XFS_SB_UNLOCK(mp, s); + break; + } + return status; } @@ -1445,8 +1497,26 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) * from the loop so we'll fall into the undo loop * below. */ - status = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, - msbp->msb_delta, rsvd); + switch (msbp->msb_field) { +#ifdef HAVE_PERCPU_SB + case XFS_SBS_ICOUNT: + case XFS_SBS_IFREE: + case XFS_SBS_FDBLOCKS: + if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { + status = xfs_icsb_modify_counters_locked(mp, + msbp->msb_field, + msbp->msb_delta, rsvd); + break; + } + /* FALLTHROUGH */ +#endif + default: + status = xfs_mod_incore_sb_unlocked(mp, + msbp->msb_field, + msbp->msb_delta, rsvd); + break; + } + if (status != 0) { break; } @@ -1463,8 +1533,28 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) if (status != 0) { msbp--; while (msbp >= msb) { - status = xfs_mod_incore_sb_unlocked(mp, - msbp->msb_field, -(msbp->msb_delta), rsvd); + switch (msbp->msb_field) { +#ifdef HAVE_PERCPU_SB + case XFS_SBS_ICOUNT: + case XFS_SBS_IFREE: + case XFS_SBS_FDBLOCKS: + if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { + status = + xfs_icsb_modify_counters_locked(mp, + msbp->msb_field, + -(msbp->msb_delta), + rsvd); + break; + } + /* FALLTHROUGH */ +#endif + default: + status = xfs_mod_incore_sb_unlocked(mp, + msbp->msb_field, + -(msbp->msb_delta), + rsvd); + break; + } ASSERT(status == 0); msbp--; } @@ -1577,3 +1667,525 @@ xfs_mount_log_sbunit( xfs_mod_sb(tp, fields); xfs_trans_commit(tp, 0, NULL); } + + +#ifdef HAVE_PERCPU_SB +/* + * Per-cpu incore superblock counters + * + * Simple concept, difficult implementation + * + * Basically, replace the incore superblock counters with a distributed per cpu + * counter for contended fields (e.g. free block count). + * + * Difficulties arise in that the incore sb is used for ENOSPC checking, and + * hence needs to be accurately read when we are running low on space. Hence + * there is a method to enable and disable the per-cpu counters based on how + * much "stuff" is available in them. + * + * Basically, a counter is enabled if there is enough free resource to justify + * running a per-cpu fast-path. If the per-cpu counter runs out (i.e. a local + * ENOSPC), then we disable the counters to synchronise all callers and + * re-distribute the available resources. + * + * If, once we redistributed the available resources, we still get a failure, + * we disable the per-cpu counter and go through the slow path. + * + * The slow path is the current xfs_mod_incore_sb() function. This means that + * when we disable a per-cpu counter, we need to drain it's resources back to + * the global superblock. We do this after disabling the counter to prevent + * more threads from queueing up on the counter. + * + * Essentially, this means that we still need a lock in the fast path to enable + * synchronisation between the global counters and the per-cpu counters. This + * is not a problem because the lock will be local to a CPU almost all the time + * and have little contention except when we get to ENOSPC conditions. + * + * Basically, this lock becomes a barrier that enables us to lock out the fast + * path while we do things like enabling and disabling counters and + * synchronising the counters. + * + * Locking rules: + * + * 1. XFS_SB_LOCK() before picking up per-cpu locks + * 2. per-cpu locks always picked up via for_each_online_cpu() order + * 3. accurate counter sync requires XFS_SB_LOCK + per cpu locks + * 4. modifying per-cpu counters requires holding per-cpu lock + * 5. modifying global counters requires holding XFS_SB_LOCK + * 6. enabling or disabling a counter requires holding the XFS_SB_LOCK + * and _none_ of the per-cpu locks. + * + * Disabled counters are only ever re-enabled by a balance operation + * that results in more free resources per CPU than a given threshold. + * To ensure counters don't remain disabled, they are rebalanced when + * the global resource goes above a higher threshold (i.e. some hysteresis + * is present to prevent thrashing). + */ + +/* + * hot-plug CPU notifier support. + * + * We cannot use the hotcpu_register() function because it does + * not allow notifier instances. We need a notifier per filesystem + * as we need to be able to identify the filesystem to balance + * the counters out. This is acheived by having a notifier block + * embedded in the xfs_mount_t and doing pointer magic to get the + * mount pointer from the notifier block address. + */ +STATIC int +xfs_icsb_cpu_notify( + struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + xfs_icsb_cnts_t *cntp; + xfs_mount_t *mp; + int s; + + mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier); + cntp = (xfs_icsb_cnts_t *) + per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu); + switch (action) { + case CPU_UP_PREPARE: + /* Easy Case - initialize the area and locks, and + * then rebalance when online does everything else for us. */ + memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); + break; + case CPU_ONLINE: + xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); + xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); + xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); + break; + case CPU_DEAD: + /* Disable all the counters, then fold the dead cpu's + * count into the total on the global superblock and + * re-enable the counters. */ + s = XFS_SB_LOCK(mp); + xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT); + xfs_icsb_disable_counter(mp, XFS_SBS_IFREE); + xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS); + + mp->m_sb.sb_icount += cntp->icsb_icount; + mp->m_sb.sb_ifree += cntp->icsb_ifree; + mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks; + + memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); + + xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED); + xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED); + xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, XFS_ICSB_SB_LOCKED); + XFS_SB_UNLOCK(mp, s); + break; + } + + return NOTIFY_OK; +} + +int +xfs_icsb_init_counters( + xfs_mount_t *mp) +{ + xfs_icsb_cnts_t *cntp; + int i; + + mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t); + if (mp->m_sb_cnts == NULL) + return -ENOMEM; + + mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify; + mp->m_icsb_notifier.priority = 0; + register_cpu_notifier(&mp->m_icsb_notifier); + + for_each_online_cpu(i) { + cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); + memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); + } + /* + * start with all counters disabled so that the + * initial balance kicks us off correctly + */ + mp->m_icsb_counters = -1; + return 0; +} + +STATIC void +xfs_icsb_destroy_counters( + xfs_mount_t *mp) +{ + if (mp->m_sb_cnts) { + unregister_cpu_notifier(&mp->m_icsb_notifier); + free_percpu(mp->m_sb_cnts); + } +} + +STATIC inline void +xfs_icsb_lock_cntr( + xfs_icsb_cnts_t *icsbp) +{ + while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) { + ndelay(1000); + } +} + +STATIC inline void +xfs_icsb_unlock_cntr( + xfs_icsb_cnts_t *icsbp) +{ + clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags); +} + + +STATIC inline void +xfs_icsb_lock_all_counters( + xfs_mount_t *mp) +{ + xfs_icsb_cnts_t *cntp; + int i; + + for_each_online_cpu(i) { + cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); + xfs_icsb_lock_cntr(cntp); + } +} + +STATIC inline void +xfs_icsb_unlock_all_counters( + xfs_mount_t *mp) +{ + xfs_icsb_cnts_t *cntp; + int i; + + for_each_online_cpu(i) { + cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); + xfs_icsb_unlock_cntr(cntp); + } +} + +STATIC void +xfs_icsb_count( + xfs_mount_t *mp, + xfs_icsb_cnts_t *cnt, + int flags) +{ + xfs_icsb_cnts_t *cntp; + int i; + + memset(cnt, 0, sizeof(xfs_icsb_cnts_t)); + + if (!(flags & XFS_ICSB_LAZY_COUNT)) + xfs_icsb_lock_all_counters(mp); + + for_each_online_cpu(i) { + cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); + cnt->icsb_icount += cntp->icsb_icount; + cnt->icsb_ifree += cntp->icsb_ifree; + cnt->icsb_fdblocks += cntp->icsb_fdblocks; + } + + if (!(flags & XFS_ICSB_LAZY_COUNT)) + xfs_icsb_unlock_all_counters(mp); +} + +STATIC int +xfs_icsb_counter_disabled( + xfs_mount_t *mp, + xfs_sb_field_t field) +{ + ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); + return test_bit(field, &mp->m_icsb_counters); +} + +STATIC int +xfs_icsb_disable_counter( + xfs_mount_t *mp, + xfs_sb_field_t field) +{ + xfs_icsb_cnts_t cnt; + + ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); + + xfs_icsb_lock_all_counters(mp); + if (!test_and_set_bit(field, &mp->m_icsb_counters)) { + /* drain back to superblock */ + + xfs_icsb_count(mp, &cnt, XFS_ICSB_SB_LOCKED|XFS_ICSB_LAZY_COUNT); + switch(field) { + case XFS_SBS_ICOUNT: + mp->m_sb.sb_icount = cnt.icsb_icount; + break; + case XFS_SBS_IFREE: + mp->m_sb.sb_ifree = cnt.icsb_ifree; + break; + case XFS_SBS_FDBLOCKS: + mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks; + break; + default: + BUG(); + } + } + + xfs_icsb_unlock_all_counters(mp); + + return 0; +} + +STATIC void +xfs_icsb_enable_counter( + xfs_mount_t *mp, + xfs_sb_field_t field, + uint64_t count, + uint64_t resid) +{ + xfs_icsb_cnts_t *cntp; + int i; + + ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); + + xfs_icsb_lock_all_counters(mp); + for_each_online_cpu(i) { + cntp = per_cpu_ptr(mp->m_sb_cnts, i); + switch (field) { + case XFS_SBS_ICOUNT: + cntp->icsb_icount = count + resid; + break; + case XFS_SBS_IFREE: + cntp->icsb_ifree = count + resid; + break; + case XFS_SBS_FDBLOCKS: + cntp->icsb_fdblocks = count + resid; + break; + default: + BUG(); + break; + } + resid = 0; + } + clear_bit(field, &mp->m_icsb_counters); + xfs_icsb_unlock_all_counters(mp); +} + +STATIC void +xfs_icsb_sync_counters_int( + xfs_mount_t *mp, + int flags) +{ + xfs_icsb_cnts_t cnt; + int s; + + /* Pass 1: lock all counters */ + if ((flags & XFS_ICSB_SB_LOCKED) == 0) + s = XFS_SB_LOCK(mp); + + xfs_icsb_count(mp, &cnt, flags); + + /* Step 3: update mp->m_sb fields */ + if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT)) + mp->m_sb.sb_icount = cnt.icsb_icount; + if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE)) + mp->m_sb.sb_ifree = cnt.icsb_ifree; + if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS)) + mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks; + + if ((flags & XFS_ICSB_SB_LOCKED) == 0) + XFS_SB_UNLOCK(mp, s); +} + +/* + * Accurate update of per-cpu counters to incore superblock + */ +STATIC void +xfs_icsb_sync_counters( + xfs_mount_t *mp) +{ + xfs_icsb_sync_counters_int(mp, 0); +} + +/* + * lazy addition used for things like df, background sb syncs, etc + */ +void +xfs_icsb_sync_counters_lazy( + xfs_mount_t *mp) +{ + xfs_icsb_sync_counters_int(mp, XFS_ICSB_LAZY_COUNT); +} + +/* + * Balance and enable/disable counters as necessary. + * + * Thresholds for re-enabling counters are somewhat magic. + * inode counts are chosen to be the same number as single + * on disk allocation chunk per CPU, and free blocks is + * something far enough zero that we aren't going thrash + * when we get near ENOSPC. + */ +#define XFS_ICSB_INO_CNTR_REENABLE 64 +#define XFS_ICSB_FDBLK_CNTR_REENABLE 512 +STATIC void +xfs_icsb_balance_counter( + xfs_mount_t *mp, + xfs_sb_field_t field, + int flags) +{ + uint64_t count, resid = 0; + int weight = num_online_cpus(); + int s; + + if (!(flags & XFS_ICSB_SB_LOCKED)) + s = XFS_SB_LOCK(mp); + + /* disable counter and sync counter */ + xfs_icsb_disable_counter(mp, field); + + /* update counters - first CPU gets residual*/ + switch (field) { + case XFS_SBS_ICOUNT: + count = mp->m_sb.sb_icount; + resid = do_div(count, weight); + if (count < XFS_ICSB_INO_CNTR_REENABLE) + goto out; + break; + case XFS_SBS_IFREE: + count = mp->m_sb.sb_ifree; + resid = do_div(count, weight); + if (count < XFS_ICSB_INO_CNTR_REENABLE) + goto out; + break; + case XFS_SBS_FDBLOCKS: + count = mp->m_sb.sb_fdblocks; + resid = do_div(count, weight); + if (count < XFS_ICSB_FDBLK_CNTR_REENABLE) + goto out; + break; + default: + BUG(); + break; + } + + xfs_icsb_enable_counter(mp, field, count, resid); +out: + if (!(flags & XFS_ICSB_SB_LOCKED)) + XFS_SB_UNLOCK(mp, s); +} + +STATIC int +xfs_icsb_modify_counters_int( + xfs_mount_t *mp, + xfs_sb_field_t field, + int delta, + int rsvd, + int flags) +{ + xfs_icsb_cnts_t *icsbp; + long long lcounter; /* long counter for 64 bit fields */ + int cpu, s, locked = 0; + int ret = 0, balance_done = 0; + +again: + cpu = get_cpu(); + icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu), + xfs_icsb_lock_cntr(icsbp); + if (unlikely(xfs_icsb_counter_disabled(mp, field))) + goto slow_path; + + switch (field) { + case XFS_SBS_ICOUNT: + lcounter = icsbp->icsb_icount; + lcounter += delta; + if (unlikely(lcounter < 0)) + goto slow_path; + icsbp->icsb_icount = lcounter; + break; + + case XFS_SBS_IFREE: + lcounter = icsbp->icsb_ifree; + lcounter += delta; + if (unlikely(lcounter < 0)) + goto slow_path; + icsbp->icsb_ifree = lcounter; + break; + + case XFS_SBS_FDBLOCKS: + BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0); + + lcounter = icsbp->icsb_fdblocks; + lcounter += delta; + if (unlikely(lcounter < 0)) + goto slow_path; + icsbp->icsb_fdblocks = lcounter; + break; + default: + BUG(); + break; + } + xfs_icsb_unlock_cntr(icsbp); + put_cpu(); + if (locked) + XFS_SB_UNLOCK(mp, s); + return 0; + + /* + * The slow path needs to be run with the SBLOCK + * held so that we prevent other threads from + * attempting to run this path at the same time. + * this provides exclusion for the balancing code, + * and exclusive fallback if the balance does not + * provide enough resources to continue in an unlocked + * manner. + */ +slow_path: + xfs_icsb_unlock_cntr(icsbp); + put_cpu(); + + /* need to hold superblock incase we need + * to disable a counter */ + if (!(flags & XFS_ICSB_SB_LOCKED)) { + s = XFS_SB_LOCK(mp); + locked = 1; + flags |= XFS_ICSB_SB_LOCKED; + } + if (!balance_done) { + xfs_icsb_balance_counter(mp, field, flags); + balance_done = 1; + goto again; + } else { + /* + * we might not have enough on this local + * cpu to allocate for a bulk request. + * We need to drain this field from all CPUs + * and disable the counter fastpath + */ + xfs_icsb_disable_counter(mp, field); + } + + ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); + + if (locked) + XFS_SB_UNLOCK(mp, s); + return ret; +} + +STATIC int +xfs_icsb_modify_counters( + xfs_mount_t *mp, + xfs_sb_field_t field, + int delta, + int rsvd) +{ + return xfs_icsb_modify_counters_int(mp, field, delta, rsvd, 0); +} + +/* + * Called when superblock is already locked + */ +STATIC int +xfs_icsb_modify_counters_locked( + xfs_mount_t *mp, + xfs_sb_field_t field, + int delta, + int rsvd) +{ + return xfs_icsb_modify_counters_int(mp, field, delta, + rsvd, XFS_ICSB_SB_LOCKED); +} +#endif diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index cd3cf9613a00..ebd73960e9db 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -267,6 +267,34 @@ typedef struct xfs_ioops { #define XFS_IODONE(vfsp) \ (*(mp)->m_io_ops.xfs_iodone)(vfsp) +#ifdef HAVE_PERCPU_SB + +/* + * Valid per-cpu incore superblock counters. Note that if you add new counters, + * you may need to define new counter disabled bit field descriptors as there + * are more possible fields in the superblock that can fit in a bitfield on a + * 32 bit platform. The XFS_SBS_* values for the current current counters just + * fit. + */ +typedef struct xfs_icsb_cnts { + uint64_t icsb_fdblocks; + uint64_t icsb_ifree; + uint64_t icsb_icount; + unsigned long icsb_flags; +} xfs_icsb_cnts_t; + +#define XFS_ICSB_FLAG_LOCK (1 << 0) /* counter lock bit */ + +#define XFS_ICSB_SB_LOCKED (1 << 0) /* sb already locked */ +#define XFS_ICSB_LAZY_COUNT (1 << 1) /* accuracy not needed */ + +extern int xfs_icsb_init_counters(struct xfs_mount *); +extern void xfs_icsb_sync_counters_lazy(struct xfs_mount *); + +#else +#define xfs_icsb_init_counters(mp) (0) +#define xfs_icsb_sync_counters_lazy(mp) do { } while (0) +#endif typedef struct xfs_mount { bhv_desc_t m_bhv; /* vfs xfs behavior */ @@ -372,6 +400,11 @@ typedef struct xfs_mount { struct xfs_qmops m_qm_ops; /* vector of XQM ops */ struct xfs_ioops m_io_ops; /* vector of I/O ops */ atomic_t m_active_trans; /* number trans frozen */ +#ifdef HAVE_PERCPU_SB + xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */ + unsigned long m_icsb_counters; /* disabled per-cpu counters */ + struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */ +#endif } xfs_mount_t; /* @@ -386,8 +419,6 @@ typedef struct xfs_mount { #define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem operations, typically for disk errors in metadata */ -#define XFS_MOUNT_NOATIME (1ULL << 5) /* don't modify inode access - times on reads */ #define XFS_MOUNT_RETERR (1ULL << 6) /* return alignment errors to user */ #define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment @@ -411,6 +442,8 @@ typedef struct xfs_mount { #define XFS_MOUNT_DIRSYNC (1ULL << 21) /* synchronous directory ops */ #define XFS_MOUNT_COMPAT_IOSIZE (1ULL << 22) /* don't report large preferred * I/O size in stat() */ +#define XFS_MOUNT_NO_PERCPU_SB (1ULL << 23) /* don't use per-cpu superblock + counters */ /* @@ -473,11 +506,6 @@ xfs_preferred_iosize(xfs_mount_t *mp) #define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* Shutdown came from remote cell */ /* - * xflags for xfs_syncsub - */ -#define XFS_XSYNC_RELOC 0x01 - -/* * Flags for xfs_mountfs */ #define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */ @@ -548,6 +576,8 @@ extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *); extern int xfs_unmountfs_writesb(xfs_mount_t *); extern int xfs_unmount_flush(xfs_mount_t *, int); extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int); +extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t, + int, int); extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, uint, int); extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index de85eefb7966..e63795644478 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h @@ -89,6 +89,7 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp, */ extern int xfs_rwlock(bhv_desc_t *bdp, vrwlock_t write_lock); extern void xfs_rwunlock(bhv_desc_t *bdp, vrwlock_t write_lock); +extern int xfs_setattr(bhv_desc_t *bdp, vattr_t *vap, int flags, cred_t *credp); extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf, xfs_off_t offset, cred_t *credp, int flags); extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state, diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index d3d714e6b32a..2918956553a5 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -55,10 +55,141 @@ STATIC void xfs_trans_committed(xfs_trans_t *, int); STATIC void xfs_trans_chunk_committed(xfs_log_item_chunk_t *, xfs_lsn_t, int); STATIC void xfs_trans_free(xfs_trans_t *); -kmem_zone_t *xfs_trans_zone; +kmem_zone_t *xfs_trans_zone; /* + * Reservation functions here avoid a huge stack in xfs_trans_init + * due to register overflow from temporaries in the calculations. + */ + +STATIC uint +xfs_calc_write_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_WRITE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_itruncate_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_ITRUNCATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_rename_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_RENAME_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_link_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_LINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_remove_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_REMOVE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_symlink_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_SYMLINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_create_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_CREATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_mkdir_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_MKDIR_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_ifree_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_IFREE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_ichange_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_ICHANGE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_growdata_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_GROWDATA_LOG_RES(mp); +} + +STATIC uint +xfs_calc_growrtalloc_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_GROWRTALLOC_LOG_RES(mp); +} + +STATIC uint +xfs_calc_growrtzero_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_GROWRTZERO_LOG_RES(mp); +} + +STATIC uint +xfs_calc_growrtfree_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_GROWRTFREE_LOG_RES(mp); +} + +STATIC uint +xfs_calc_swrite_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_SWRITE_LOG_RES(mp); +} + +STATIC uint +xfs_calc_writeid_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_WRITEID_LOG_RES(mp); +} + +STATIC uint +xfs_calc_addafork_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_ADDAFORK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_attrinval_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_ATTRINVAL_LOG_RES(mp); +} + +STATIC uint +xfs_calc_attrset_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_ATTRSET_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_attrrm_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_ATTRRM_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); +} + +STATIC uint +xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp) +{ + return XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp); +} + +/* * Initialize the precomputed transaction reservation values * in the mount structure. */ @@ -69,39 +200,27 @@ xfs_trans_init( xfs_trans_reservations_t *resp; resp = &(mp->m_reservations); - resp->tr_write = - (uint)(XFS_CALC_WRITE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_itruncate = - (uint)(XFS_CALC_ITRUNCATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_rename = - (uint)(XFS_CALC_RENAME_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_link = (uint)XFS_CALC_LINK_LOG_RES(mp); - resp->tr_remove = - (uint)(XFS_CALC_REMOVE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_symlink = - (uint)(XFS_CALC_SYMLINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_create = - (uint)(XFS_CALC_CREATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_mkdir = - (uint)(XFS_CALC_MKDIR_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_ifree = - (uint)(XFS_CALC_IFREE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_ichange = - (uint)(XFS_CALC_ICHANGE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_growdata = (uint)XFS_CALC_GROWDATA_LOG_RES(mp); - resp->tr_swrite = (uint)XFS_CALC_SWRITE_LOG_RES(mp); - resp->tr_writeid = (uint)XFS_CALC_WRITEID_LOG_RES(mp); - resp->tr_addafork = - (uint)(XFS_CALC_ADDAFORK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_attrinval = (uint)XFS_CALC_ATTRINVAL_LOG_RES(mp); - resp->tr_attrset = - (uint)(XFS_CALC_ATTRSET_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_attrrm = - (uint)(XFS_CALC_ATTRRM_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp)); - resp->tr_clearagi = (uint)XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp); - resp->tr_growrtalloc = (uint)XFS_CALC_GROWRTALLOC_LOG_RES(mp); - resp->tr_growrtzero = (uint)XFS_CALC_GROWRTZERO_LOG_RES(mp); - resp->tr_growrtfree = (uint)XFS_CALC_GROWRTFREE_LOG_RES(mp); + resp->tr_write = xfs_calc_write_reservation(mp); + resp->tr_itruncate = xfs_calc_itruncate_reservation(mp); + resp->tr_rename = xfs_calc_rename_reservation(mp); + resp->tr_link = xfs_calc_link_reservation(mp); + resp->tr_remove = xfs_calc_remove_reservation(mp); + resp->tr_symlink = xfs_calc_symlink_reservation(mp); + resp->tr_create = xfs_calc_create_reservation(mp); + resp->tr_mkdir = xfs_calc_mkdir_reservation(mp); + resp->tr_ifree = xfs_calc_ifree_reservation(mp); + resp->tr_ichange = xfs_calc_ichange_reservation(mp); + resp->tr_growdata = xfs_calc_growdata_reservation(mp); + resp->tr_swrite = xfs_calc_swrite_reservation(mp); + resp->tr_writeid = xfs_calc_writeid_reservation(mp); + resp->tr_addafork = xfs_calc_addafork_reservation(mp); + resp->tr_attrinval = xfs_calc_attrinval_reservation(mp); + resp->tr_attrset = xfs_calc_attrset_reservation(mp); + resp->tr_attrrm = xfs_calc_attrrm_reservation(mp); + resp->tr_clearagi = xfs_calc_clear_agi_bucket_reservation(mp); + resp->tr_growrtalloc = xfs_calc_growrtalloc_reservation(mp); + resp->tr_growrtzero = xfs_calc_growrtzero_reservation(mp); + resp->tr_growrtfree = xfs_calc_growrtfree_reservation(mp); } /* diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index d77901c07f63..e48befa4e337 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -380,7 +380,7 @@ typedef struct xfs_trans { xfs_trans_header_t t_header; /* header for in-log trans */ unsigned int t_busy_free; /* busy descs free */ xfs_log_busy_chunk_t t_busy; /* busy/async free blocks */ - xfs_pflags_t t_pflags; /* saved pflags state */ + unsigned long t_pflags; /* saved process flags state */ } xfs_trans_t; #endif /* __KERNEL__ */ diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index b6ad370fab3d..d4ec4dfaf19c 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -55,7 +55,7 @@ #include "xfs_clnt.h" #include "xfs_fsops.h" -STATIC int xfs_sync(bhv_desc_t *, int, cred_t *); +STATIC int xfs_sync(bhv_desc_t *, int, cred_t *); int xfs_init(void) @@ -77,11 +77,12 @@ xfs_init(void) "xfs_bmap_free_item"); xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t), "xfs_btree_cur"); - xfs_inode_zone = kmem_zone_init(sizeof(xfs_inode_t), "xfs_inode"); xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans"); xfs_da_state_zone = kmem_zone_init(sizeof(xfs_da_state_t), "xfs_da_state"); xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf"); + xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork"); + xfs_acl_zone_init(xfs_acl_zone, "xfs_acl"); /* * The size of the zone allocated buf log item is the maximum @@ -93,17 +94,30 @@ xfs_init(void) (((XFS_MAX_BLOCKSIZE / XFS_BLI_CHUNK) / NBWORD) * sizeof(int))), "xfs_buf_item"); - xfs_efd_zone = kmem_zone_init((sizeof(xfs_efd_log_item_t) + - ((XFS_EFD_MAX_FAST_EXTENTS - 1) * sizeof(xfs_extent_t))), + xfs_efd_zone = + kmem_zone_init((sizeof(xfs_efd_log_item_t) + + ((XFS_EFD_MAX_FAST_EXTENTS - 1) * + sizeof(xfs_extent_t))), "xfs_efd_item"); - xfs_efi_zone = kmem_zone_init((sizeof(xfs_efi_log_item_t) + - ((XFS_EFI_MAX_FAST_EXTENTS - 1) * sizeof(xfs_extent_t))), + xfs_efi_zone = + kmem_zone_init((sizeof(xfs_efi_log_item_t) + + ((XFS_EFI_MAX_FAST_EXTENTS - 1) * + sizeof(xfs_extent_t))), "xfs_efi_item"); - xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork"); - xfs_ili_zone = kmem_zone_init(sizeof(xfs_inode_log_item_t), "xfs_ili"); - xfs_chashlist_zone = kmem_zone_init(sizeof(xfs_chashlist_t), - "xfs_chashlist"); - xfs_acl_zone_init(xfs_acl_zone, "xfs_acl"); + + /* + * These zones warrant special memory allocator hints + */ + xfs_inode_zone = + kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode", + KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | + KM_ZONE_SPREAD, NULL); + xfs_ili_zone = + kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili", + KM_ZONE_SPREAD, NULL); + xfs_chashlist_zone = + kmem_zone_init_flags(sizeof(xfs_chashlist_t), "xfs_chashlist", + KM_ZONE_SPREAD, NULL); /* * Allocate global trace buffers. @@ -176,18 +190,18 @@ xfs_cleanup(void) ktrace_free(xfs_alloc_trace_buf); #endif - kmem_cache_destroy(xfs_bmap_free_item_zone); - kmem_cache_destroy(xfs_btree_cur_zone); - kmem_cache_destroy(xfs_inode_zone); - kmem_cache_destroy(xfs_trans_zone); - kmem_cache_destroy(xfs_da_state_zone); - kmem_cache_destroy(xfs_dabuf_zone); - kmem_cache_destroy(xfs_buf_item_zone); - kmem_cache_destroy(xfs_efd_zone); - kmem_cache_destroy(xfs_efi_zone); - kmem_cache_destroy(xfs_ifork_zone); - kmem_cache_destroy(xfs_ili_zone); - kmem_cache_destroy(xfs_chashlist_zone); + kmem_zone_destroy(xfs_bmap_free_item_zone); + kmem_zone_destroy(xfs_btree_cur_zone); + kmem_zone_destroy(xfs_inode_zone); + kmem_zone_destroy(xfs_trans_zone); + kmem_zone_destroy(xfs_da_state_zone); + kmem_zone_destroy(xfs_dabuf_zone); + kmem_zone_destroy(xfs_buf_item_zone); + kmem_zone_destroy(xfs_efd_zone); + kmem_zone_destroy(xfs_efi_zone); + kmem_zone_destroy(xfs_ifork_zone); + kmem_zone_destroy(xfs_ili_zone); + kmem_zone_destroy(xfs_chashlist_zone); } /* @@ -258,8 +272,6 @@ xfs_start_flags( mp->m_inoadd = XFS_INO64_OFFSET; } #endif - if (ap->flags & XFSMNT_NOATIME) - mp->m_flags |= XFS_MOUNT_NOATIME; if (ap->flags & XFSMNT_RETERR) mp->m_flags |= XFS_MOUNT_RETERR; if (ap->flags & XFSMNT_NOALIGN) @@ -620,7 +632,7 @@ xfs_quiesce_fs( xfs_mount_t *mp) { int count = 0, pincount; - + xfs_refcache_purge_mp(mp); xfs_flush_buftarg(mp->m_ddev_targp, 0); xfs_finish_reclaim_all(mp, 0); @@ -631,7 +643,7 @@ xfs_quiesce_fs( * meta data (typically directory updates). * Which then must be flushed and logged before * we can write the unmount record. - */ + */ do { xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL); pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1); @@ -654,11 +666,6 @@ xfs_mntupdate( xfs_mount_t *mp = XFS_BHVTOM(bdp); int error; - if (args->flags & XFSMNT_NOATIME) - mp->m_flags |= XFS_MOUNT_NOATIME; - else - mp->m_flags &= ~XFS_MOUNT_NOATIME; - if (args->flags & XFSMNT_BARRIER) mp->m_flags |= XFS_MOUNT_BARRIER; else @@ -814,6 +821,7 @@ xfs_statvfs( statp->f_type = XFS_SB_MAGIC; + xfs_icsb_sync_counters_lazy(mp); s = XFS_SB_LOCK(mp); statp->f_bsize = sbp->sb_blocksize; lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0; @@ -1221,7 +1229,7 @@ xfs_sync_inodes( xfs_iunlock(ip, XFS_ILOCK_SHARED); error = xfs_itobp(mp, NULL, ip, - &dip, &bp, 0); + &dip, &bp, 0, 0); if (!error) { xfs_buf_relse(bp); } else { @@ -1690,10 +1698,7 @@ xfs_parseargs( int iosize; args->flags2 |= XFSMNT2_COMPAT_IOSIZE; - -#if 0 /* XXX: off by default, until some remaining issues ironed out */ - args->flags |= XFSMNT_IDELETE; /* default to on */ -#endif + args->flags |= XFSMNT_IDELETE; if (!options) goto done; @@ -1903,7 +1908,6 @@ xfs_showargs( { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY }, { XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC }, - { XFS_MOUNT_IDELETE, "," MNTOPT_NOIKEEP }, { 0, NULL } }; struct proc_xfs_info *xfs_infop; @@ -1939,6 +1943,8 @@ xfs_showargs( seq_printf(m, "," MNTOPT_SWIDTH "=%d", (int)XFS_FSB_TO_BB(mp, mp->m_swidth)); + if (!(mp->m_flags & XFS_MOUNT_IDELETE)) + seq_printf(m, "," MNTOPT_IKEEP); if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE)) seq_printf(m, "," MNTOPT_LARGEIO); if (mp->m_flags & XFS_MOUNT_BARRIER) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index eaab355f5a89..a478f42e63ff 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -615,6 +615,7 @@ xfs_setattr( code = xfs_igrow_start(ip, vap->va_size, credp); } xfs_iunlock(ip, XFS_ILOCK_EXCL); + vn_iowait(vp); /* wait for the completion of any pending DIOs */ if (!code) code = xfs_itruncate_data(ip, vap->va_size); if (code) { @@ -1556,7 +1557,7 @@ xfs_release( if ((error = xfs_inactive_free_eofblocks(mp, ip))) return error; /* Update linux inode block count after free above */ - LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp, + vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); } } @@ -1637,7 +1638,7 @@ xfs_inactive( if ((error = xfs_inactive_free_eofblocks(mp, ip))) return VN_INACTIVE_CACHE; /* Update linux inode block count after free above */ - LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp, + vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); } goto out; @@ -3186,7 +3187,7 @@ xfs_rmdir( /* Fall through to std_return with error = 0 or the errno * from xfs_trans_commit. */ -std_return: + std_return: if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_POSTREMOVE)) { (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dir_vp, DM_RIGHT_NULL, @@ -3196,12 +3197,12 @@ std_return: } return error; -error1: + error1: xfs_bmap_cancel(&free_list); cancel_flags |= XFS_TRANS_ABORT; /* FALLTHROUGH */ -error_return: + error_return: xfs_trans_cancel(tp, cancel_flags); goto std_return; } @@ -4310,8 +4311,10 @@ xfs_free_file_space( ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1); if (attr_flags & ATTR_NOLOCK) need_iolock = 0; - if (need_iolock) + if (need_iolock) { xfs_ilock(ip, XFS_IOLOCK_EXCL); + vn_iowait(vp); /* wait for the completion of any pending DIOs */ + } rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog), (__uint8_t)NBPP); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 0b54e9a4a8a1..e496fac860ac 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -330,6 +330,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver); int acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); +int acpi_bus_trim(struct acpi_device *start, int rmdevice); int acpi_bus_start(struct acpi_device *device); int acpi_match_ids(struct acpi_device *device, char *ids); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 56bb6a4e15f3..c179966f1a2f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -22,6 +22,7 @@ typedef struct request_queue request_queue_t; struct elevator_queue; typedef struct elevator_queue elevator_t; struct request_pm_state; +struct blk_trace; #define BLKDEV_MIN_RQ 4 #define BLKDEV_MAX_RQ 128 /* Default maximum */ @@ -416,6 +417,8 @@ struct request_queue unsigned int sg_reserved_size; int node; + struct blk_trace *blk_trace; + /* * reserved for flush operations */ diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h new file mode 100644 index 000000000000..b34d3e73d5ea --- /dev/null +++ b/include/linux/blktrace_api.h @@ -0,0 +1,277 @@ +#ifndef BLKTRACE_H +#define BLKTRACE_H + +#include <linux/config.h> +#include <linux/blkdev.h> +#include <linux/relay.h> + +/* + * Trace categories + */ +enum blktrace_cat { + BLK_TC_READ = 1 << 0, /* reads */ + BLK_TC_WRITE = 1 << 1, /* writes */ + BLK_TC_BARRIER = 1 << 2, /* barrier */ + BLK_TC_SYNC = 1 << 3, /* barrier */ + BLK_TC_QUEUE = 1 << 4, /* queueing/merging */ + BLK_TC_REQUEUE = 1 << 5, /* requeueing */ + BLK_TC_ISSUE = 1 << 6, /* issue */ + BLK_TC_COMPLETE = 1 << 7, /* completions */ + BLK_TC_FS = 1 << 8, /* fs requests */ + BLK_TC_PC = 1 << 9, /* pc requests */ + BLK_TC_NOTIFY = 1 << 10, /* special message */ + + BLK_TC_END = 1 << 15, /* only 16-bits, reminder */ +}; + +#define BLK_TC_SHIFT (16) +#define BLK_TC_ACT(act) ((act) << BLK_TC_SHIFT) + +/* + * Basic trace actions + */ +enum blktrace_act { + __BLK_TA_QUEUE = 1, /* queued */ + __BLK_TA_BACKMERGE, /* back merged to existing rq */ + __BLK_TA_FRONTMERGE, /* front merge to existing rq */ + __BLK_TA_GETRQ, /* allocated new request */ + __BLK_TA_SLEEPRQ, /* sleeping on rq allocation */ + __BLK_TA_REQUEUE, /* request requeued */ + __BLK_TA_ISSUE, /* sent to driver */ + __BLK_TA_COMPLETE, /* completed by driver */ + __BLK_TA_PLUG, /* queue was plugged */ + __BLK_TA_UNPLUG_IO, /* queue was unplugged by io */ + __BLK_TA_UNPLUG_TIMER, /* queue was unplugged by timer */ + __BLK_TA_INSERT, /* insert request */ + __BLK_TA_SPLIT, /* bio was split */ + __BLK_TA_BOUNCE, /* bio was bounced */ + __BLK_TA_REMAP, /* bio was remapped */ +}; + +/* + * Trace actions in full. Additionally, read or write is masked + */ +#define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_BACKMERGE (__BLK_TA_BACKMERGE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_FRONTMERGE (__BLK_TA_FRONTMERGE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_GETRQ (__BLK_TA_GETRQ | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_SLEEPRQ (__BLK_TA_SLEEPRQ | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_REQUEUE (__BLK_TA_REQUEUE | BLK_TC_ACT(BLK_TC_REQUEUE)) +#define BLK_TA_ISSUE (__BLK_TA_ISSUE | BLK_TC_ACT(BLK_TC_ISSUE)) +#define BLK_TA_COMPLETE (__BLK_TA_COMPLETE| BLK_TC_ACT(BLK_TC_COMPLETE)) +#define BLK_TA_PLUG (__BLK_TA_PLUG | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_UNPLUG_IO (__BLK_TA_UNPLUG_IO | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_UNPLUG_TIMER (__BLK_TA_UNPLUG_TIMER | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_INSERT (__BLK_TA_INSERT | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_SPLIT (__BLK_TA_SPLIT) +#define BLK_TA_BOUNCE (__BLK_TA_BOUNCE) +#define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE)) + +#define BLK_IO_TRACE_MAGIC 0x65617400 +#define BLK_IO_TRACE_VERSION 0x07 + +/* + * The trace itself + */ +struct blk_io_trace { + u32 magic; /* MAGIC << 8 | version */ + u32 sequence; /* event number */ + u64 time; /* in microseconds */ + u64 sector; /* disk offset */ + u32 bytes; /* transfer length */ + u32 action; /* what happened */ + u32 pid; /* who did it */ + u32 device; /* device number */ + u32 cpu; /* on what cpu did it happen */ + u16 error; /* completion error */ + u16 pdu_len; /* length of data after this trace */ +}; + +/* + * The remap event + */ +struct blk_io_trace_remap { + u32 device; + u32 __pad; + u64 sector; +}; + +enum { + Blktrace_setup = 1, + Blktrace_running, + Blktrace_stopped, +}; + +struct blk_trace { + int trace_state; + struct rchan *rchan; + unsigned long *sequence; + u16 act_mask; + u64 start_lba; + u64 end_lba; + u32 pid; + u32 dev; + struct dentry *dir; + struct dentry *dropped_file; + atomic_t dropped; +}; + +/* + * User setup structure passed with BLKTRACESTART + */ +struct blk_user_trace_setup { + char name[BDEVNAME_SIZE]; /* output */ + u16 act_mask; /* input */ + u32 buf_size; /* input */ + u32 buf_nr; /* input */ + u64 start_lba; + u64 end_lba; + u32 pid; +}; + +#if defined(CONFIG_BLK_DEV_IO_TRACE) +extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); +extern void blk_trace_shutdown(request_queue_t *); +extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); + +/** + * blk_add_trace_rq - Add a trace for a request oriented action + * @q: queue the io is for + * @rq: the source request + * @what: the action + * + * Description: + * Records an action against a request. Will log the bio offset + size. + * + **/ +static inline void blk_add_trace_rq(struct request_queue *q, struct request *rq, + u32 what) +{ + struct blk_trace *bt = q->blk_trace; + int rw = rq->flags & 0x07; + + if (likely(!bt)) + return; + + if (blk_pc_request(rq)) { + what |= BLK_TC_ACT(BLK_TC_PC); + __blk_add_trace(bt, 0, rq->data_len, rw, what, rq->errors, sizeof(rq->cmd), rq->cmd); + } else { + what |= BLK_TC_ACT(BLK_TC_FS); + __blk_add_trace(bt, rq->hard_sector, rq->hard_nr_sectors << 9, rw, what, rq->errors, 0, NULL); + } +} + +/** + * blk_add_trace_bio - Add a trace for a bio oriented action + * @q: queue the io is for + * @bio: the source bio + * @what: the action + * + * Description: + * Records an action against a bio. Will log the bio offset + size. + * + **/ +static inline void blk_add_trace_bio(struct request_queue *q, struct bio *bio, + u32 what) +{ + struct blk_trace *bt = q->blk_trace; + + if (likely(!bt)) + return; + + __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, !bio_flagged(bio, BIO_UPTODATE), 0, NULL); +} + +/** + * blk_add_trace_generic - Add a trace for a generic action + * @q: queue the io is for + * @bio: the source bio + * @rw: the data direction + * @what: the action + * + * Description: + * Records a simple trace + * + **/ +static inline void blk_add_trace_generic(struct request_queue *q, + struct bio *bio, int rw, u32 what) +{ + struct blk_trace *bt = q->blk_trace; + + if (likely(!bt)) + return; + + if (bio) + blk_add_trace_bio(q, bio, what); + else + __blk_add_trace(bt, 0, 0, rw, what, 0, 0, NULL); +} + +/** + * blk_add_trace_pdu_int - Add a trace for a bio with an integer payload + * @q: queue the io is for + * @what: the action + * @bio: the source bio + * @pdu: the integer payload + * + * Description: + * Adds a trace with some integer payload. This might be an unplug + * option given as the action, with the depth at unplug time given + * as the payload + * + **/ +static inline void blk_add_trace_pdu_int(struct request_queue *q, u32 what, + struct bio *bio, unsigned int pdu) +{ + struct blk_trace *bt = q->blk_trace; + u64 rpdu = cpu_to_be64(pdu); + + if (likely(!bt)) + return; + + if (bio) + __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, !bio_flagged(bio, BIO_UPTODATE), sizeof(rpdu), &rpdu); + else + __blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu); +} + +/** + * blk_add_trace_remap - Add a trace for a remap operation + * @q: queue the io is for + * @bio: the source bio + * @dev: target device + * @from: source sector + * @to: target sector + * + * Description: + * Device mapper or raid target sometimes need to split a bio because + * it spans a stripe (or similar). Add a trace for that action. + * + **/ +static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, + dev_t dev, sector_t from, sector_t to) +{ + struct blk_trace *bt = q->blk_trace; + struct blk_io_trace_remap r; + + if (likely(!bt)) + return; + + r.device = cpu_to_be32(dev); + r.sector = cpu_to_be64(to); + + __blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r); +} + +#else /* !CONFIG_BLK_DEV_IO_TRACE */ +#define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY) +#define blk_trace_shutdown(q) do { } while (0) +#define blk_add_trace_rq(q, rq, what) do { } while (0) +#define blk_add_trace_bio(q, rq, what) do { } while (0) +#define blk_add_trace_generic(q, rq, rw, what) do { } while (0) +#define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) +#define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) +#endif /* CONFIG_BLK_DEV_IO_TRACE */ + +#endif diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index ae7dfb790df3..efb518f16bb3 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -97,6 +97,10 @@ COMPATIBLE_IOCTL(BLKRRPART) COMPATIBLE_IOCTL(BLKFLSBUF) COMPATIBLE_IOCTL(BLKSECTSET) COMPATIBLE_IOCTL(BLKSSZGET) +COMPATIBLE_IOCTL(BLKTRACESTART) +COMPATIBLE_IOCTL(BLKTRACESTOP) +COMPATIBLE_IOCTL(BLKTRACESETUP) +COMPATIBLE_IOCTL(BLKTRACETEARDOWN) ULONG_IOCTL(BLKRASET) ULONG_IOCTL(BLKFRASET) /* RAID */ diff --git a/include/linux/fs.h b/include/linux/fs.h index f9c9dea636d0..9b34a1b03455 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -197,6 +197,10 @@ extern int dir_notify_enable; #define BLKBSZGET _IOR(0x12,112,size_t) #define BLKBSZSET _IOW(0x12,113,size_t) #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ +#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup) +#define BLKTRACESTART _IO(0x12,116) +#define BLKTRACESTOP _IO(0x12,117) +#define BLKTRACETEARDOWN _IO(0x12,118) #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ #define FIBMAP _IO(0x00,1) /* bmap access */ diff --git a/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h index 7eb4004b3601..a90c09d331c1 100644 --- a/include/linux/hwmon-sysfs.h +++ b/include/linux/hwmon-sysfs.h @@ -27,11 +27,13 @@ struct sensor_device_attribute{ #define to_sensor_dev_attr(_dev_attr) \ container_of(_dev_attr, struct sensor_device_attribute, dev_attr) -#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index) \ -struct sensor_device_attribute sensor_dev_attr_##_name = { \ - .dev_attr = __ATTR(_name,_mode,_show,_store), \ - .index = _index, \ -} +#define SENSOR_ATTR(_name, _mode, _show, _store, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index } + +#define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ +struct sensor_device_attribute sensor_dev_attr_##_name \ + = SENSOR_ATTR(_name, _mode, _show, _store, _index) struct sensor_device_attribute_2 { struct device_attribute dev_attr; @@ -41,11 +43,13 @@ struct sensor_device_attribute_2 { #define to_sensor_dev_attr_2(_dev_attr) \ container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr) +#define SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .index = _index, \ + .nr = _nr } + #define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index) \ -struct sensor_device_attribute_2 sensor_dev_attr_##_name = { \ - .dev_attr = __ATTR(_name,_mode,_show,_store), \ - .index = _index, \ - .nr = _nr, \ -} +struct sensor_device_attribute_2 sensor_dev_attr_##_name \ + = SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) #endif /* _LINUX_HWMON_SYSFS_H */ diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 474c8f4f5d4f..ec311bc89439 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -172,7 +172,6 @@ #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ #define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ #define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */ -#define I2C_HW_B_FRODO 0x010013 /* 2d3D SA-1110 Development Board */ #define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */ #define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */ #define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 63f1d63cc1d8..1635ee25918f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -32,7 +32,7 @@ #include <linux/mod_devicetable.h> #include <linux/device.h> /* for struct device */ #include <linux/sched.h> /* for completion */ -#include <asm/semaphore.h> +#include <linux/mutex.h> /* --- For i2c-isa ---------------------------------------------------- */ @@ -225,8 +225,8 @@ struct i2c_adapter { int (*client_unregister)(struct i2c_client *); /* data fields that are valid for all devices */ - struct semaphore bus_lock; - struct semaphore clist_lock; + struct mutex bus_lock; + struct mutex clist_lock; int timeout; int retries; diff --git a/include/linux/pci.h b/include/linux/pci.h index fe1a2b02fc55..0aad5a378e95 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -95,6 +95,11 @@ enum pci_channel_state { pci_channel_io_perm_failure = (__force pci_channel_state_t) 3, }; +typedef unsigned short __bitwise pci_bus_flags_t; +enum pci_bus_flags { + PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1, +}; + /* * The pci_dev structure is used to describe PCI devices. */ @@ -203,7 +208,7 @@ struct pci_bus { char name[48]; unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */ - unsigned short pad2; + pci_bus_flags_t bus_flags; /* Inherited by child busses */ struct device *bridge; struct class_device class_dev; struct bin_attribute *legacy_io; /* legacy I/O for this bus */ @@ -485,9 +490,9 @@ void pdev_sort_resources(struct pci_dev *, struct resource_list *); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(struct pci_dev *, u8, u8)); #define HAVE_PCI_REQ_REGIONS 2 -int pci_request_regions(struct pci_dev *, char *); +int pci_request_regions(struct pci_dev *, const char *); void pci_release_regions(struct pci_dev *); -int pci_request_region(struct pci_dev *, int, char *); +int pci_request_region(struct pci_dev *, int, const char *); void pci_release_region(struct pci_dev *, int); /* drivers/pci/bus.c */ @@ -516,6 +521,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), void *userdata); int pci_cfg_space_size(struct pci_dev *dev); +unsigned char pci_bus_max_busnr(struct pci_bus* bus); /* kmem_cache style wrapper around pci_alloc_consistent() */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ec3c32932620..f3dcf89d5232 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1371,6 +1371,7 @@ #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 #define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 @@ -1864,11 +1865,13 @@ #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e #define PCI_DEVICE_ID_TIGON3_5754M 0x1672 +#define PCI_DEVICE_ID_TIGON3_5755M 0x1673 #define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 #define PCI_DEVICE_ID_TIGON3_5715S 0x1679 #define PCI_DEVICE_ID_TIGON3_5754 0x167a +#define PCI_DEVICE_ID_TIGON3_5755 0x167b #define PCI_DEVICE_ID_TIGON3_5750M 0x167c #define PCI_DEVICE_ID_TIGON3_5751M 0x167d #define PCI_DEVICE_ID_TIGON3_5751F 0x167e diff --git a/include/linux/relay.h b/include/linux/relay.h new file mode 100644 index 000000000000..4bcc1531d6a9 --- /dev/null +++ b/include/linux/relay.h @@ -0,0 +1,281 @@ +/* + * linux/include/linux/relay.h + * + * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp + * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com) + * + * CONFIG_RELAY definitions and declarations + */ + +#ifndef _LINUX_RELAY_H +#define _LINUX_RELAY_H + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/wait.h> +#include <linux/list.h> +#include <linux/fs.h> +#include <linux/poll.h> +#include <linux/kref.h> + +/* Needs a _much_ better name... */ +#define FIX_SIZE(x) ((((x) - 1) & PAGE_MASK) + PAGE_SIZE) + +/* + * Tracks changes to rchan/rchan_buf structs + */ +#define RELAYFS_CHANNEL_VERSION 6 + +/* + * Per-cpu relay channel buffer + */ +struct rchan_buf +{ + void *start; /* start of channel buffer */ + void *data; /* start of current sub-buffer */ + size_t offset; /* current offset into sub-buffer */ + size_t subbufs_produced; /* count of sub-buffers produced */ + size_t subbufs_consumed; /* count of sub-buffers consumed */ + struct rchan *chan; /* associated channel */ + wait_queue_head_t read_wait; /* reader wait queue */ + struct work_struct wake_readers; /* reader wake-up work struct */ + struct dentry *dentry; /* channel file dentry */ + struct kref kref; /* channel buffer refcount */ + struct page **page_array; /* array of current buffer pages */ + unsigned int page_count; /* number of current buffer pages */ + unsigned int finalized; /* buffer has been finalized */ + size_t *padding; /* padding counts per sub-buffer */ + size_t prev_padding; /* temporary variable */ + size_t bytes_consumed; /* bytes consumed in cur read subbuf */ + unsigned int cpu; /* this buf's cpu */ +} ____cacheline_aligned; + +/* + * Relay channel data structure + */ +struct rchan +{ + u32 version; /* the version of this struct */ + size_t subbuf_size; /* sub-buffer size */ + size_t n_subbufs; /* number of sub-buffers per buffer */ + size_t alloc_size; /* total buffer size allocated */ + struct rchan_callbacks *cb; /* client callbacks */ + struct kref kref; /* channel refcount */ + void *private_data; /* for user-defined data */ + size_t last_toobig; /* tried to log event > subbuf size */ + struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */ +}; + +/* + * Relay channel client callbacks + */ +struct rchan_callbacks +{ + /* + * subbuf_start - called on buffer-switch to a new sub-buffer + * @buf: the channel buffer containing the new sub-buffer + * @subbuf: the start of the new sub-buffer + * @prev_subbuf: the start of the previous sub-buffer + * @prev_padding: unused space at the end of previous sub-buffer + * + * The client should return 1 to continue logging, 0 to stop + * logging. + * + * NOTE: subbuf_start will also be invoked when the buffer is + * created, so that the first sub-buffer can be initialized + * if necessary. In this case, prev_subbuf will be NULL. + * + * NOTE: the client can reserve bytes at the beginning of the new + * sub-buffer by calling subbuf_start_reserve() in this callback. + */ + int (*subbuf_start) (struct rchan_buf *buf, + void *subbuf, + void *prev_subbuf, + size_t prev_padding); + + /* + * buf_mapped - relay buffer mmap notification + * @buf: the channel buffer + * @filp: relay file pointer + * + * Called when a relay file is successfully mmapped + */ + void (*buf_mapped)(struct rchan_buf *buf, + struct file *filp); + + /* + * buf_unmapped - relay buffer unmap notification + * @buf: the channel buffer + * @filp: relay file pointer + * + * Called when a relay file is successfully unmapped + */ + void (*buf_unmapped)(struct rchan_buf *buf, + struct file *filp); + /* + * create_buf_file - create file to represent a relay channel buffer + * @filename: the name of the file to create + * @parent: the parent of the file to create + * @mode: the mode of the file to create + * @buf: the channel buffer + * @is_global: outparam - set non-zero if the buffer should be global + * + * Called during relay_open(), once for each per-cpu buffer, + * to allow the client to create a file to be used to + * represent the corresponding channel buffer. If the file is + * created outside of relay, the parent must also exist in + * that filesystem. + * + * The callback should return the dentry of the file created + * to represent the relay buffer. + * + * Setting the is_global outparam to a non-zero value will + * cause relay_open() to create a single global buffer rather + * than the default set of per-cpu buffers. + * + * See Documentation/filesystems/relayfs.txt for more info. + */ + struct dentry *(*create_buf_file)(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global); + + /* + * remove_buf_file - remove file representing a relay channel buffer + * @dentry: the dentry of the file to remove + * + * Called during relay_close(), once for each per-cpu buffer, + * to allow the client to remove a file used to represent a + * channel buffer. + * + * The callback should return 0 if successful, negative if not. + */ + int (*remove_buf_file)(struct dentry *dentry); +}; + +/* + * CONFIG_RELAY kernel API, kernel/relay.c + */ + +struct rchan *relay_open(const char *base_filename, + struct dentry *parent, + size_t subbuf_size, + size_t n_subbufs, + struct rchan_callbacks *cb); +extern void relay_close(struct rchan *chan); +extern void relay_flush(struct rchan *chan); +extern void relay_subbufs_consumed(struct rchan *chan, + unsigned int cpu, + size_t consumed); +extern void relay_reset(struct rchan *chan); +extern int relay_buf_full(struct rchan_buf *buf); + +extern size_t relay_switch_subbuf(struct rchan_buf *buf, + size_t length); + +/** + * relay_write - write data into the channel + * @chan: relay channel + * @data: data to be written + * @length: number of bytes to write + * + * Writes data into the current cpu's channel buffer. + * + * Protects the buffer by disabling interrupts. Use this + * if you might be logging from interrupt context. Try + * __relay_write() if you know you won't be logging from + * interrupt context. + */ +static inline void relay_write(struct rchan *chan, + const void *data, + size_t length) +{ + unsigned long flags; + struct rchan_buf *buf; + + local_irq_save(flags); + buf = chan->buf[smp_processor_id()]; + if (unlikely(buf->offset + length > chan->subbuf_size)) + length = relay_switch_subbuf(buf, length); + memcpy(buf->data + buf->offset, data, length); + buf->offset += length; + local_irq_restore(flags); +} + +/** + * __relay_write - write data into the channel + * @chan: relay channel + * @data: data to be written + * @length: number of bytes to write + * + * Writes data into the current cpu's channel buffer. + * + * Protects the buffer by disabling preemption. Use + * relay_write() if you might be logging from interrupt + * context. + */ +static inline void __relay_write(struct rchan *chan, + const void *data, + size_t length) +{ + struct rchan_buf *buf; + + buf = chan->buf[get_cpu()]; + if (unlikely(buf->offset + length > buf->chan->subbuf_size)) + length = relay_switch_subbuf(buf, length); + memcpy(buf->data + buf->offset, data, length); + buf->offset += length; + put_cpu(); +} + +/** + * relay_reserve - reserve slot in channel buffer + * @chan: relay channel + * @length: number of bytes to reserve + * + * Returns pointer to reserved slot, NULL if full. + * + * Reserves a slot in the current cpu's channel buffer. + * Does not protect the buffer at all - caller must provide + * appropriate synchronization. + */ +static inline void *relay_reserve(struct rchan *chan, size_t length) +{ + void *reserved; + struct rchan_buf *buf = chan->buf[smp_processor_id()]; + + if (unlikely(buf->offset + length > buf->chan->subbuf_size)) { + length = relay_switch_subbuf(buf, length); + if (!length) + return NULL; + } + reserved = buf->data + buf->offset; + buf->offset += length; + + return reserved; +} + +/** + * subbuf_start_reserve - reserve bytes at the start of a sub-buffer + * @buf: relay channel buffer + * @length: number of bytes to reserve + * + * Helper function used to reserve bytes at the beginning of + * a sub-buffer in the subbuf_start() callback. + */ +static inline void subbuf_start_reserve(struct rchan_buf *buf, + size_t length) +{ + BUG_ON(length >= buf->chan->subbuf_size - 1); + buf->offset = length; +} + +/* + * exported relay file operations, kernel/relay.c + */ +extern struct file_operations relay_file_operations; + +#endif /* _LINUX_RELAY_H */ + diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index d572d5376319..df0cdd41085c 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -839,6 +839,7 @@ enum #define RTMGRP_IPV4_IFADDR 0x10 #define RTMGRP_IPV4_MROUTE 0x20 #define RTMGRP_IPV4_ROUTE 0x40 +#define RTMGRP_IPV4_RULE 0x80 #define RTMGRP_IPV6_IFADDR 0x100 #define RTMGRP_IPV6_MROUTE 0x200 @@ -869,7 +870,8 @@ enum rtnetlink_groups { #define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_ROUTE, #define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE - RTNLGRP_NOP1, + RTNLGRP_IPV4_RULE, +#define RTNLGRP_IPV4_RULE RTNLGRP_IPV4_RULE RTNLGRP_IPV6_IFADDR, #define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_MROUTE, diff --git a/include/linux/sched.h b/include/linux/sched.h index 62e6314382f0..e60a91d5b369 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -706,6 +706,7 @@ struct task_struct { prio_array_t *array; unsigned short ioprio; + unsigned int btrace_seq; unsigned long sleep_avg; unsigned long long timestamp, last_ran; diff --git a/include/linux/wireless.h b/include/linux/wireless.h index a555a0f7a7b4..13588564b42b 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -1,10 +1,10 @@ /* * This file define a set of standard wireless extensions * - * Version : 19 18.3.05 + * Version : 20 17.2.06 * * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H @@ -80,7 +80,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 19 +#define WIRELESS_EXT 20 /* * Changes : @@ -204,6 +204,10 @@ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros + * + * V19 to V20 + * ---------- + * - RtNetlink requests support (SET/GET) */ /**************************** CONSTANTS ****************************/ diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h new file mode 100644 index 000000000000..b971d8c82bdd --- /dev/null +++ b/include/net/ieee80211softmac.h @@ -0,0 +1,292 @@ +/* + * ieee80211softmac.h - public interface to the softmac + * + * Copyright (c) 2005 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#ifndef IEEE80211SOFTMAC_H_ +#define IEEE80211SOFTMAC_H_ + +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/list.h> +#include <net/ieee80211.h> + +/* Once the API is considered more or less stable, + * this should be incremented on API incompatible changes. + */ +#define IEEE80211SOFTMAC_API 0 + +#define IEEE80211SOFTMAC_MAX_RATES_LEN 8 +#define IEEE80211SOFTMAC_MAX_EX_RATES_LEN 255 + +struct ieee80211softmac_ratesinfo { + u8 count; + u8 rates[IEEE80211SOFTMAC_MAX_RATES_LEN + IEEE80211SOFTMAC_MAX_EX_RATES_LEN]; +}; + +/* internal structures */ +struct ieee80211softmac_network; +struct ieee80211softmac_scaninfo; + +struct ieee80211softmac_essid { + u8 len; + char data[IW_ESSID_MAX_SIZE+1]; +}; + +struct ieee80211softmac_wpa { + char *IE; + int IElen; + int IEbuflen; +}; + +/* + * Information about association + * + * Do we need a lock for this? + * We only ever use this structure inlined + * into our global struct. I've used its lock, + * but maybe we need a local one here? + */ +struct ieee80211softmac_assoc_info { + /* + * This is the requested ESSID. It is written + * only by the WX handlers. + * + */ + struct ieee80211softmac_essid req_essid; + /* + * the ESSID of the network we're currently + * associated (or trying) to. This is + * updated to the network's actual ESSID + * even if the requested ESSID was 'ANY' + */ + struct ieee80211softmac_essid associate_essid; + + /* BSSID we're trying to associate to */ + char bssid[ETH_ALEN]; + + /* some flags. + * static_essid is valid if the essid is constant, + * this is for use by the wx handlers only. + * + * associating is true, if the network has been + * auth'ed on and we are in the process of associating. + * + * bssvalid is true if we found a matching network + * and saved it's BSSID into the bssid above. + */ + u8 static_essid:1, + associating:1, + bssvalid:1; + + /* Scan retries remaining */ + int scan_retry; + + struct work_struct work; + struct work_struct timeout; +}; + +enum { + IEEE80211SOFTMAC_AUTH_OPEN_REQUEST = 1, + IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE = 2, +}; + +enum { + IEEE80211SOFTMAC_AUTH_SHARED_REQUEST = 1, + IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE = 2, + IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE = 3, + IEEE80211SOFTMAC_AUTH_SHARED_PASS = 4, +}; + +/* We should make these tunable + * AUTH_TIMEOUT seems really long, but that's what it is in BSD */ +#define IEEE80211SOFTMAC_AUTH_TIMEOUT (12 * HZ) +#define IEEE80211SOFTMAC_AUTH_RETRY_LIMIT 5 +#define IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT 3 + +struct ieee80211softmac_txrates { + /* The Bit-Rate to be used for multicast frames. */ + u8 mcast_rate; + /* The Bit-Rate to be used for multicast fallback + * (If the device supports fallback and hardware-retry) + */ + u8 mcast_fallback; + /* The Bit-Rate to be used for any other (normal) data packet. */ + u8 default_rate; + /* The Bit-Rate to be used for default fallback + * (If the device supports fallback and hardware-retry) + */ + u8 default_fallback; +}; + +/* Bits for txrates_change callback. */ +#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */ +#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */ +#define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */ +#define IEEE80211SOFTMAC_TXRATECHG_MCAST_FBACK (1 << 3) /* mcast_fallback */ + +struct ieee80211softmac_device { + /* 802.11 structure for data stuff */ + struct ieee80211_device *ieee; + struct net_device *dev; + + /* only valid if associated, then holds the Association ID */ + u16 association_id; + + /* the following methods are callbacks that the driver + * using this framework has to assign + */ + + /* always assign these */ + void (*set_bssid_filter)(struct net_device *dev, const u8 *bssid); + void (*set_channel)(struct net_device *dev, u8 channel); + + /* assign if you need it, informational only */ + void (*link_change)(struct net_device *dev); + + /* If the hardware can do scanning, assign _all_ three of these callbacks. + * When the scan finishes, call ieee80211softmac_scan_finished(). + */ + + /* when called, start_scan is guaranteed to not be called again + * until you call ieee80211softmac_scan_finished. + * Return 0 if scanning could start, error otherwise. + * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_start_scan */ + int (*start_scan)(struct net_device *dev); + /* this should block until after ieee80211softmac_scan_finished was called + * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_wait_for_scan */ + void (*wait_for_scan)(struct net_device *dev); + /* stop_scan aborts a scan, but is asynchronous. + * if you want to wait for it too, use wait_for_scan + * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_stop_scan */ + void (*stop_scan)(struct net_device *dev); + + /* we'll need something about beacons here too, for AP or ad-hoc modes */ + + /* Transmission rates to be used by the driver. + * The SoftMAC figures out the best possible rates. + * The driver just needs to read them. + */ + struct ieee80211softmac_txrates txrates; + /* If the driver needs to do stuff on TX rate changes, assign this callback. */ + void (*txrates_change)(struct net_device *dev, + u32 changes, /* see IEEE80211SOFTMAC_TXRATECHG flags */ + const struct ieee80211softmac_txrates *rates_before_change); + + /* private stuff follows */ + /* this lock protects this structure */ + spinlock_t lock; + + /* couple of flags */ + u8 scanning:1, /* protects scanning from being done multiple times at once */ + associated:1; + + struct ieee80211softmac_scaninfo *scaninfo; + struct ieee80211softmac_assoc_info associnfo; + + struct list_head auth_queue; + struct list_head events; + + struct ieee80211softmac_ratesinfo ratesinfo; + int txrate_badness; + + /* WPA stuff */ + struct ieee80211softmac_wpa wpa; + + /* we need to keep a list of network structs we copied */ + struct list_head network_list; + + /* This must be the last item so that it points to the data + * allocated beyond this structure by alloc_ieee80211 */ + u8 priv[0]; +}; + +extern void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm); + +static inline void * ieee80211softmac_priv(struct net_device *dev) +{ + return ((struct ieee80211softmac_device *)ieee80211_priv(dev))->priv; +} + +extern struct net_device * alloc_ieee80211softmac(int sizeof_priv); +extern void free_ieee80211softmac(struct net_device *dev); + +/* Call this function if you detect a lost TX fragment. + * (If the device indicates failure of ACK RX, for example.) + * It is wise to call this function if you are able to detect lost packets, + * because it contributes to the TX Rates auto adjustment. + */ +extern void ieee80211softmac_fragment_lost(struct net_device *dev, + u16 wireless_sequence_number); +/* Call this function before _start to tell the softmac what rates + * the hw supports. The rates parameter is copied, so you can + * free it right after calling this function. + * Note that the rates need to be sorted. */ +extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates); + +/* Start the SoftMAC. Call this after you initialized the device + * and it is ready to run. + */ +extern void ieee80211softmac_start(struct net_device *dev); +/* Stop the SoftMAC. Call this before you shutdown the device. */ +extern void ieee80211softmac_stop(struct net_device *dev); + +/* + * Event system + */ + +/* valid event types */ +#define IEEE80211SOFTMAC_EVENT_ANY -1 /*private use only*/ +#define IEEE80211SOFTMAC_EVENT_SCAN_FINISHED 0 +#define IEEE80211SOFTMAC_EVENT_ASSOCIATED 1 +#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED 2 +#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT 3 +#define IEEE80211SOFTMAC_EVENT_AUTHENTICATED 4 +#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5 +#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6 +#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7 +/* keep this updated! */ +#define IEEE80211SOFTMAC_EVENT_LAST 7 +/* + * If you want to be notified of certain events, you can call + * ieee80211softmac_notify[_atomic] with + * - event set to one of the constants below + * - fun set to a function pointer of the appropriate type + * - context set to the context data you want passed + * The return value is 0, or an error. + */ +typedef void (*notify_function_ptr)(struct net_device *dev, void *context); + +#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL); +#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC); + +extern int ieee80211softmac_notify_gfp(struct net_device *dev, + int event, notify_function_ptr fun, void *context, gfp_t gfp_mask); + +/* To clear pending work (for ifconfig down, etc.) */ +extern void +ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm); + +#endif /* IEEE80211SOFTMAC_H_ */ diff --git a/include/net/ieee80211softmac_wx.h b/include/net/ieee80211softmac_wx.h new file mode 100644 index 000000000000..3e0be453ecea --- /dev/null +++ b/include/net/ieee80211softmac_wx.h @@ -0,0 +1,94 @@ +/* + * This file contains the prototypes for the wireless extension + * handlers that the softmac API provides. Include this file to + * use the wx handlers, you can assign these directly. + * + * Copyright (c) 2005 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#ifndef _IEEE80211SOFTMAC_WX_H +#define _IEEE80211SOFTMAC_WX_H + +#include <net/ieee80211softmac.h> +#include <net/iw_handler.h> + +extern int +ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_set_essid(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_get_essid(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_set_rate(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_get_rate(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_get_wap(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_set_wap(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra); + +extern int +ieee80211softmac_wx_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra); + +extern int +ieee80211softmac_wx_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra); +#endif /* _IEEE80211SOFTMAC_WX */ diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index a2c5e0b88422..10559e937d27 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -4,7 +4,7 @@ * Version : 7 18.3.05 * * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> - * Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved. */ #ifndef _IW_HANDLER_H @@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, /* Handle IOCTLs, called in net/core/dev.c */ extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); +/* Handle RtNetlink requests, called in net/core/rtnetlink.c */ +extern int wireless_rtnetlink_set(struct net_device * dev, + char * data, + int len); +extern int wireless_rtnetlink_get(struct net_device * dev, + char * data, + int len, + char ** p_buf, + int * p_len); + /* Second : functions that may be called by driver modules */ /* Send a single event to user space */ diff --git a/init/Kconfig b/init/Kconfig index 38416a199def..1d19fd25204b 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -214,6 +214,17 @@ config CPUSETS Say N if unsure. +config RELAY + bool "Kernel->user space relay support (formerly relayfs)" + help + This option enables support for relay interface support in + certain file systems (such as debugfs). + It is designed to provide an efficient mechanism for tools and + facilities to relay large amounts of data from kernel space to + user space. + + If unsure, say N. + source "usr/Kconfig" config UID16 diff --git a/kernel/Makefile b/kernel/Makefile index 4ae0fbde815d..aebd7a78984e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ obj-$(CONFIG_SECCOMP) += seccomp.o obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o +obj-$(CONFIG_RELAY) += relay.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is diff --git a/kernel/fork.c b/kernel/fork.c index c79ae0b19a49..c21bae8c93b9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -181,6 +181,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); atomic_set(&tsk->fs_excl, 0); + tsk->btrace_seq = 0; return tsk; } diff --git a/kernel/relay.c b/kernel/relay.c new file mode 100644 index 000000000000..33345e73485c --- /dev/null +++ b/kernel/relay.c @@ -0,0 +1,1012 @@ +/* + * Public API and common code for kernel->userspace relay file support. + * + * See Documentation/filesystems/relayfs.txt for an overview of relayfs. + * + * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp + * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com) + * + * Moved to kernel/relay.c by Paul Mundt, 2006. + * + * This file is released under the GPL. + */ +#include <linux/errno.h> +#include <linux/stddef.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/relay.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> + +/* + * close() vm_op implementation for relay file mapping. + */ +static void relay_file_mmap_close(struct vm_area_struct *vma) +{ + struct rchan_buf *buf = vma->vm_private_data; + buf->chan->cb->buf_unmapped(buf, vma->vm_file); +} + +/* + * nopage() vm_op implementation for relay file mapping. + */ +static struct page *relay_buf_nopage(struct vm_area_struct *vma, + unsigned long address, + int *type) +{ + struct page *page; + struct rchan_buf *buf = vma->vm_private_data; + unsigned long offset = address - vma->vm_start; + + if (address > vma->vm_end) + return NOPAGE_SIGBUS; /* Disallow mremap */ + if (!buf) + return NOPAGE_OOM; + + page = vmalloc_to_page(buf->start + offset); + if (!page) + return NOPAGE_OOM; + get_page(page); + + if (type) + *type = VM_FAULT_MINOR; + + return page; +} + +/* + * vm_ops for relay file mappings. + */ +static struct vm_operations_struct relay_file_mmap_ops = { + .nopage = relay_buf_nopage, + .close = relay_file_mmap_close, +}; + +/** + * relay_mmap_buf: - mmap channel buffer to process address space + * @buf: relay channel buffer + * @vma: vm_area_struct describing memory to be mapped + * + * Returns 0 if ok, negative on error + * + * Caller should already have grabbed mmap_sem. + */ +int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma) +{ + unsigned long length = vma->vm_end - vma->vm_start; + struct file *filp = vma->vm_file; + + if (!buf) + return -EBADF; + + if (length != (unsigned long)buf->chan->alloc_size) + return -EINVAL; + + vma->vm_ops = &relay_file_mmap_ops; + vma->vm_private_data = buf; + buf->chan->cb->buf_mapped(buf, filp); + + return 0; +} + +/** + * relay_alloc_buf - allocate a channel buffer + * @buf: the buffer struct + * @size: total size of the buffer + * + * Returns a pointer to the resulting buffer, NULL if unsuccessful. The + * passed in size will get page aligned, if it isn't already. + */ +static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size) +{ + void *mem; + unsigned int i, j, n_pages; + + *size = PAGE_ALIGN(*size); + n_pages = *size >> PAGE_SHIFT; + + buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL); + if (!buf->page_array) + return NULL; + + for (i = 0; i < n_pages; i++) { + buf->page_array[i] = alloc_page(GFP_KERNEL); + if (unlikely(!buf->page_array[i])) + goto depopulate; + } + mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL); + if (!mem) + goto depopulate; + + memset(mem, 0, *size); + buf->page_count = n_pages; + return mem; + +depopulate: + for (j = 0; j < i; j++) + __free_page(buf->page_array[j]); + kfree(buf->page_array); + return NULL; +} + +/** + * relay_create_buf - allocate and initialize a channel buffer + * @alloc_size: size of the buffer to allocate + * @n_subbufs: number of sub-buffers in the channel + * + * Returns channel buffer if successful, NULL otherwise + */ +struct rchan_buf *relay_create_buf(struct rchan *chan) +{ + struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL); + if (!buf) + return NULL; + + buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL); + if (!buf->padding) + goto free_buf; + + buf->start = relay_alloc_buf(buf, &chan->alloc_size); + if (!buf->start) + goto free_buf; + + buf->chan = chan; + kref_get(&buf->chan->kref); + return buf; + +free_buf: + kfree(buf->padding); + kfree(buf); + return NULL; +} + +/** + * relay_destroy_channel - free the channel struct + * + * Should only be called from kref_put(). + */ +void relay_destroy_channel(struct kref *kref) +{ + struct rchan *chan = container_of(kref, struct rchan, kref); + kfree(chan); +} + +/** + * relay_destroy_buf - destroy an rchan_buf struct and associated buffer + * @buf: the buffer struct + */ +void relay_destroy_buf(struct rchan_buf *buf) +{ + struct rchan *chan = buf->chan; + unsigned int i; + + if (likely(buf->start)) { + vunmap(buf->start); + for (i = 0; i < buf->page_count; i++) + __free_page(buf->page_array[i]); + kfree(buf->page_array); + } + kfree(buf->padding); + kfree(buf); + kref_put(&chan->kref, relay_destroy_channel); +} + +/** + * relay_remove_buf - remove a channel buffer + * + * Removes the file from the fileystem, which also frees the + * rchan_buf_struct and the channel buffer. Should only be called from + * kref_put(). + */ +void relay_remove_buf(struct kref *kref) +{ + struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref); + buf->chan->cb->remove_buf_file(buf->dentry); + relay_destroy_buf(buf); +} + +/** + * relay_buf_empty - boolean, is the channel buffer empty? + * @buf: channel buffer + * + * Returns 1 if the buffer is empty, 0 otherwise. + */ +int relay_buf_empty(struct rchan_buf *buf) +{ + return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1; +} +EXPORT_SYMBOL_GPL(relay_buf_empty); + +/** + * relay_buf_full - boolean, is the channel buffer full? + * @buf: channel buffer + * + * Returns 1 if the buffer is full, 0 otherwise. + */ +int relay_buf_full(struct rchan_buf *buf) +{ + size_t ready = buf->subbufs_produced - buf->subbufs_consumed; + return (ready >= buf->chan->n_subbufs) ? 1 : 0; +} +EXPORT_SYMBOL_GPL(relay_buf_full); + +/* + * High-level relay kernel API and associated functions. + */ + +/* + * rchan_callback implementations defining default channel behavior. Used + * in place of corresponding NULL values in client callback struct. + */ + +/* + * subbuf_start() default callback. Does nothing. + */ +static int subbuf_start_default_callback (struct rchan_buf *buf, + void *subbuf, + void *prev_subbuf, + size_t prev_padding) +{ + if (relay_buf_full(buf)) + return 0; + + return 1; +} + +/* + * buf_mapped() default callback. Does nothing. + */ +static void buf_mapped_default_callback(struct rchan_buf *buf, + struct file *filp) +{ +} + +/* + * buf_unmapped() default callback. Does nothing. + */ +static void buf_unmapped_default_callback(struct rchan_buf *buf, + struct file *filp) +{ +} + +/* + * create_buf_file_create() default callback. Does nothing. + */ +static struct dentry *create_buf_file_default_callback(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global) +{ + return NULL; +} + +/* + * remove_buf_file() default callback. Does nothing. + */ +static int remove_buf_file_default_callback(struct dentry *dentry) +{ + return -EINVAL; +} + +/* relay channel default callbacks */ +static struct rchan_callbacks default_channel_callbacks = { + .subbuf_start = subbuf_start_default_callback, + .buf_mapped = buf_mapped_default_callback, + .buf_unmapped = buf_unmapped_default_callback, + .create_buf_file = create_buf_file_default_callback, + .remove_buf_file = remove_buf_file_default_callback, +}; + +/** + * wakeup_readers - wake up readers waiting on a channel + * @private: the channel buffer + * + * This is the work function used to defer reader waking. The + * reason waking is deferred is that calling directly from write + * causes problems if you're writing from say the scheduler. + */ +static void wakeup_readers(void *private) +{ + struct rchan_buf *buf = private; + wake_up_interruptible(&buf->read_wait); +} + +/** + * __relay_reset - reset a channel buffer + * @buf: the channel buffer + * @init: 1 if this is a first-time initialization + * + * See relay_reset for description of effect. + */ +static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) +{ + size_t i; + + if (init) { + init_waitqueue_head(&buf->read_wait); + kref_init(&buf->kref); + INIT_WORK(&buf->wake_readers, NULL, NULL); + } else { + cancel_delayed_work(&buf->wake_readers); + flush_scheduled_work(); + } + + buf->subbufs_produced = 0; + buf->subbufs_consumed = 0; + buf->bytes_consumed = 0; + buf->finalized = 0; + buf->data = buf->start; + buf->offset = 0; + + for (i = 0; i < buf->chan->n_subbufs; i++) + buf->padding[i] = 0; + + buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0); +} + +/** + * relay_reset - reset the channel + * @chan: the channel + * + * This has the effect of erasing all data from all channel buffers + * and restarting the channel in its initial state. The buffers + * are not freed, so any mappings are still in effect. + * + * NOTE: Care should be taken that the channel isn't actually + * being used by anything when this call is made. + */ +void relay_reset(struct rchan *chan) +{ + unsigned int i; + struct rchan_buf *prev = NULL; + + if (!chan) + return; + + for (i = 0; i < NR_CPUS; i++) { + if (!chan->buf[i] || chan->buf[i] == prev) + break; + __relay_reset(chan->buf[i], 0); + prev = chan->buf[i]; + } +} +EXPORT_SYMBOL_GPL(relay_reset); + +/** + * relay_open_buf - create a new relay channel buffer + * + * Internal - used by relay_open(). + */ +static struct rchan_buf *relay_open_buf(struct rchan *chan, + const char *filename, + struct dentry *parent, + int *is_global) +{ + struct rchan_buf *buf; + struct dentry *dentry; + + if (*is_global) + return chan->buf[0]; + + buf = relay_create_buf(chan); + if (!buf) + return NULL; + + /* Create file in fs */ + dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR, + buf, is_global); + if (!dentry) { + relay_destroy_buf(buf); + return NULL; + } + + buf->dentry = dentry; + __relay_reset(buf, 1); + + return buf; +} + +/** + * relay_close_buf - close a channel buffer + * @buf: channel buffer + * + * Marks the buffer finalized and restores the default callbacks. + * The channel buffer and channel buffer data structure are then freed + * automatically when the last reference is given up. + */ +static inline void relay_close_buf(struct rchan_buf *buf) +{ + buf->finalized = 1; + cancel_delayed_work(&buf->wake_readers); + flush_scheduled_work(); + kref_put(&buf->kref, relay_remove_buf); +} + +static inline void setup_callbacks(struct rchan *chan, + struct rchan_callbacks *cb) +{ + if (!cb) { + chan->cb = &default_channel_callbacks; + return; + } + + if (!cb->subbuf_start) + cb->subbuf_start = subbuf_start_default_callback; + if (!cb->buf_mapped) + cb->buf_mapped = buf_mapped_default_callback; + if (!cb->buf_unmapped) + cb->buf_unmapped = buf_unmapped_default_callback; + if (!cb->create_buf_file) + cb->create_buf_file = create_buf_file_default_callback; + if (!cb->remove_buf_file) + cb->remove_buf_file = remove_buf_file_default_callback; + chan->cb = cb; +} + +/** + * relay_open - create a new relay channel + * @base_filename: base name of files to create + * @parent: dentry of parent directory, NULL for root directory + * @subbuf_size: size of sub-buffers + * @n_subbufs: number of sub-buffers + * @cb: client callback functions + * + * Returns channel pointer if successful, NULL otherwise. + * + * Creates a channel buffer for each cpu using the sizes and + * attributes specified. The created channel buffer files + * will be named base_filename0...base_filenameN-1. File + * permissions will be S_IRUSR. + */ +struct rchan *relay_open(const char *base_filename, + struct dentry *parent, + size_t subbuf_size, + size_t n_subbufs, + struct rchan_callbacks *cb) +{ + unsigned int i; + struct rchan *chan; + char *tmpname; + int is_global = 0; + + if (!base_filename) + return NULL; + + if (!(subbuf_size && n_subbufs)) + return NULL; + + chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL); + if (!chan) + return NULL; + + chan->version = RELAYFS_CHANNEL_VERSION; + chan->n_subbufs = n_subbufs; + chan->subbuf_size = subbuf_size; + chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs); + setup_callbacks(chan, cb); + kref_init(&chan->kref); + + tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL); + if (!tmpname) + goto free_chan; + + for_each_online_cpu(i) { + sprintf(tmpname, "%s%d", base_filename, i); + chan->buf[i] = relay_open_buf(chan, tmpname, parent, + &is_global); + if (!chan->buf[i]) + goto free_bufs; + + chan->buf[i]->cpu = i; + } + + kfree(tmpname); + return chan; + +free_bufs: + for (i = 0; i < NR_CPUS; i++) { + if (!chan->buf[i]) + break; + relay_close_buf(chan->buf[i]); + if (is_global) + break; + } + kfree(tmpname); + +free_chan: + kref_put(&chan->kref, relay_destroy_channel); + return NULL; +} +EXPORT_SYMBOL_GPL(relay_open); + +/** + * relay_switch_subbuf - switch to a new sub-buffer + * @buf: channel buffer + * @length: size of current event + * + * Returns either the length passed in or 0 if full. + * + * Performs sub-buffer-switch tasks such as invoking callbacks, + * updating padding counts, waking up readers, etc. + */ +size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) +{ + void *old, *new; + size_t old_subbuf, new_subbuf; + + if (unlikely(length > buf->chan->subbuf_size)) + goto toobig; + + if (buf->offset != buf->chan->subbuf_size + 1) { + buf->prev_padding = buf->chan->subbuf_size - buf->offset; + old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; + buf->padding[old_subbuf] = buf->prev_padding; + buf->subbufs_produced++; + buf->dentry->d_inode->i_size += buf->chan->subbuf_size - + buf->padding[old_subbuf]; + smp_mb(); + if (waitqueue_active(&buf->read_wait)) { + PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf); + schedule_delayed_work(&buf->wake_readers, 1); + } + } + + old = buf->data; + new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs; + new = buf->start + new_subbuf * buf->chan->subbuf_size; + buf->offset = 0; + if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) { + buf->offset = buf->chan->subbuf_size + 1; + return 0; + } + buf->data = new; + buf->padding[new_subbuf] = 0; + + if (unlikely(length + buf->offset > buf->chan->subbuf_size)) + goto toobig; + + return length; + +toobig: + buf->chan->last_toobig = length; + return 0; +} +EXPORT_SYMBOL_GPL(relay_switch_subbuf); + +/** + * relay_subbufs_consumed - update the buffer's sub-buffers-consumed count + * @chan: the channel + * @cpu: the cpu associated with the channel buffer to update + * @subbufs_consumed: number of sub-buffers to add to current buf's count + * + * Adds to the channel buffer's consumed sub-buffer count. + * subbufs_consumed should be the number of sub-buffers newly consumed, + * not the total consumed. + * + * NOTE: kernel clients don't need to call this function if the channel + * mode is 'overwrite'. + */ +void relay_subbufs_consumed(struct rchan *chan, + unsigned int cpu, + size_t subbufs_consumed) +{ + struct rchan_buf *buf; + + if (!chan) + return; + + if (cpu >= NR_CPUS || !chan->buf[cpu]) + return; + + buf = chan->buf[cpu]; + buf->subbufs_consumed += subbufs_consumed; + if (buf->subbufs_consumed > buf->subbufs_produced) + buf->subbufs_consumed = buf->subbufs_produced; +} +EXPORT_SYMBOL_GPL(relay_subbufs_consumed); + +/** + * relay_close - close the channel + * @chan: the channel + * + * Closes all channel buffers and frees the channel. + */ +void relay_close(struct rchan *chan) +{ + unsigned int i; + struct rchan_buf *prev = NULL; + + if (!chan) + return; + + for (i = 0; i < NR_CPUS; i++) { + if (!chan->buf[i] || chan->buf[i] == prev) + break; + relay_close_buf(chan->buf[i]); + prev = chan->buf[i]; + } + + if (chan->last_toobig) + printk(KERN_WARNING "relay: one or more items not logged " + "[item size (%Zd) > sub-buffer size (%Zd)]\n", + chan->last_toobig, chan->subbuf_size); + + kref_put(&chan->kref, relay_destroy_channel); +} +EXPORT_SYMBOL_GPL(relay_close); + +/** + * relay_flush - close the channel + * @chan: the channel + * + * Flushes all channel buffers i.e. forces buffer switch. + */ +void relay_flush(struct rchan *chan) +{ + unsigned int i; + struct rchan_buf *prev = NULL; + + if (!chan) + return; + + for (i = 0; i < NR_CPUS; i++) { + if (!chan->buf[i] || chan->buf[i] == prev) + break; + relay_switch_subbuf(chan->buf[i], 0); + prev = chan->buf[i]; + } +} +EXPORT_SYMBOL_GPL(relay_flush); + +/** + * relay_file_open - open file op for relay files + * @inode: the inode + * @filp: the file + * + * Increments the channel buffer refcount. + */ +static int relay_file_open(struct inode *inode, struct file *filp) +{ + struct rchan_buf *buf = inode->u.generic_ip; + kref_get(&buf->kref); + filp->private_data = buf; + + return 0; +} + +/** + * relay_file_mmap - mmap file op for relay files + * @filp: the file + * @vma: the vma describing what to map + * + * Calls upon relay_mmap_buf to map the file into user space. + */ +static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct rchan_buf *buf = filp->private_data; + return relay_mmap_buf(buf, vma); +} + +/** + * relay_file_poll - poll file op for relay files + * @filp: the file + * @wait: poll table + * + * Poll implemention. + */ +static unsigned int relay_file_poll(struct file *filp, poll_table *wait) +{ + unsigned int mask = 0; + struct rchan_buf *buf = filp->private_data; + + if (buf->finalized) + return POLLERR; + + if (filp->f_mode & FMODE_READ) { + poll_wait(filp, &buf->read_wait, wait); + if (!relay_buf_empty(buf)) + mask |= POLLIN | POLLRDNORM; + } + + return mask; +} + +/** + * relay_file_release - release file op for relay files + * @inode: the inode + * @filp: the file + * + * Decrements the channel refcount, as the filesystem is + * no longer using it. + */ +static int relay_file_release(struct inode *inode, struct file *filp) +{ + struct rchan_buf *buf = filp->private_data; + kref_put(&buf->kref, relay_remove_buf); + + return 0; +} + +/** + * relay_file_read_consume - update the consumed count for the buffer + */ +static void relay_file_read_consume(struct rchan_buf *buf, + size_t read_pos, + size_t bytes_consumed) +{ + size_t subbuf_size = buf->chan->subbuf_size; + size_t n_subbufs = buf->chan->n_subbufs; + size_t read_subbuf; + + if (buf->bytes_consumed + bytes_consumed > subbuf_size) { + relay_subbufs_consumed(buf->chan, buf->cpu, 1); + buf->bytes_consumed = 0; + } + + buf->bytes_consumed += bytes_consumed; + read_subbuf = read_pos / buf->chan->subbuf_size; + if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) { + if ((read_subbuf == buf->subbufs_produced % n_subbufs) && + (buf->offset == subbuf_size)) + return; + relay_subbufs_consumed(buf->chan, buf->cpu, 1); + buf->bytes_consumed = 0; + } +} + +/** + * relay_file_read_avail - boolean, are there unconsumed bytes available? + */ +static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos) +{ + size_t subbuf_size = buf->chan->subbuf_size; + size_t n_subbufs = buf->chan->n_subbufs; + size_t produced = buf->subbufs_produced; + size_t consumed = buf->subbufs_consumed; + + relay_file_read_consume(buf, read_pos, 0); + + if (unlikely(buf->offset > subbuf_size)) { + if (produced == consumed) + return 0; + return 1; + } + + if (unlikely(produced - consumed >= n_subbufs)) { + consumed = (produced / n_subbufs) * n_subbufs; + buf->subbufs_consumed = consumed; + } + + produced = (produced % n_subbufs) * subbuf_size + buf->offset; + consumed = (consumed % n_subbufs) * subbuf_size + buf->bytes_consumed; + + if (consumed > produced) + produced += n_subbufs * subbuf_size; + + if (consumed == produced) + return 0; + + return 1; +} + +/** + * relay_file_read_subbuf_avail - return bytes available in sub-buffer + */ +static size_t relay_file_read_subbuf_avail(size_t read_pos, + struct rchan_buf *buf) +{ + size_t padding, avail = 0; + size_t read_subbuf, read_offset, write_subbuf, write_offset; + size_t subbuf_size = buf->chan->subbuf_size; + + write_subbuf = (buf->data - buf->start) / subbuf_size; + write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset; + read_subbuf = read_pos / subbuf_size; + read_offset = read_pos % subbuf_size; + padding = buf->padding[read_subbuf]; + + if (read_subbuf == write_subbuf) { + if (read_offset + padding < write_offset) + avail = write_offset - (read_offset + padding); + } else + avail = (subbuf_size - padding) - read_offset; + + return avail; +} + +/** + * relay_file_read_start_pos - find the first available byte to read + * + * If the read_pos is in the middle of padding, return the + * position of the first actually available byte, otherwise + * return the original value. + */ +static size_t relay_file_read_start_pos(size_t read_pos, + struct rchan_buf *buf) +{ + size_t read_subbuf, padding, padding_start, padding_end; + size_t subbuf_size = buf->chan->subbuf_size; + size_t n_subbufs = buf->chan->n_subbufs; + + read_subbuf = read_pos / subbuf_size; + padding = buf->padding[read_subbuf]; + padding_start = (read_subbuf + 1) * subbuf_size - padding; + padding_end = (read_subbuf + 1) * subbuf_size; + if (read_pos >= padding_start && read_pos < padding_end) { + read_subbuf = (read_subbuf + 1) % n_subbufs; + read_pos = read_subbuf * subbuf_size; + } + + return read_pos; +} + +/** + * relay_file_read_end_pos - return the new read position + */ +static size_t relay_file_read_end_pos(struct rchan_buf *buf, + size_t read_pos, + size_t count) +{ + size_t read_subbuf, padding, end_pos; + size_t subbuf_size = buf->chan->subbuf_size; + size_t n_subbufs = buf->chan->n_subbufs; + + read_subbuf = read_pos / subbuf_size; + padding = buf->padding[read_subbuf]; + if (read_pos % subbuf_size + count + padding == subbuf_size) + end_pos = (read_subbuf + 1) * subbuf_size; + else + end_pos = read_pos + count; + if (end_pos >= subbuf_size * n_subbufs) + end_pos = 0; + + return end_pos; +} + +/** + * subbuf_read_actor - read up to one subbuf's worth of data + */ +static int subbuf_read_actor(size_t read_start, + struct rchan_buf *buf, + size_t avail, + read_descriptor_t *desc, + read_actor_t actor) +{ + void *from; + int ret = 0; + + from = buf->start + read_start; + ret = avail; + if (copy_to_user(desc->arg.data, from, avail)) { + desc->error = -EFAULT; + ret = 0; + } + desc->arg.data += ret; + desc->written += ret; + desc->count -= ret; + + return ret; +} + +/** + * subbuf_send_actor - send up to one subbuf's worth of data + */ +static int subbuf_send_actor(size_t read_start, + struct rchan_buf *buf, + size_t avail, + read_descriptor_t *desc, + read_actor_t actor) +{ + unsigned long pidx, poff; + unsigned int subbuf_pages; + int ret = 0; + + subbuf_pages = buf->chan->alloc_size >> PAGE_SHIFT; + pidx = (read_start / PAGE_SIZE) % subbuf_pages; + poff = read_start & ~PAGE_MASK; + while (avail) { + struct page *p = buf->page_array[pidx]; + unsigned int len; + + len = PAGE_SIZE - poff; + if (len > avail) + len = avail; + + len = actor(desc, p, poff, len); + if (desc->error) + break; + + avail -= len; + ret += len; + poff = 0; + pidx = (pidx + 1) % subbuf_pages; + } + + return ret; +} + +typedef int (*subbuf_actor_t) (size_t read_start, + struct rchan_buf *buf, + size_t avail, + read_descriptor_t *desc, + read_actor_t actor); + +/** + * relay_file_read_subbufs - read count bytes, bridging subbuf boundaries + */ +static inline ssize_t relay_file_read_subbufs(struct file *filp, + loff_t *ppos, + size_t count, + subbuf_actor_t subbuf_actor, + read_actor_t actor, + void *target) +{ + struct rchan_buf *buf = filp->private_data; + size_t read_start, avail; + read_descriptor_t desc; + int ret; + + if (!count) + return 0; + + desc.written = 0; + desc.count = count; + desc.arg.data = target; + desc.error = 0; + + mutex_lock(&filp->f_dentry->d_inode->i_mutex); + do { + if (!relay_file_read_avail(buf, *ppos)) + break; + + read_start = relay_file_read_start_pos(*ppos, buf); + avail = relay_file_read_subbuf_avail(read_start, buf); + if (!avail) + break; + + avail = min(desc.count, avail); + ret = subbuf_actor(read_start, buf, avail, &desc, actor); + if (desc.error < 0) + break; + + if (ret) { + relay_file_read_consume(buf, read_start, ret); + *ppos = relay_file_read_end_pos(buf, read_start, ret); + } + } while (desc.count && ret); + mutex_unlock(&filp->f_dentry->d_inode->i_mutex); + + return desc.written; +} + +static ssize_t relay_file_read(struct file *filp, + char __user *buffer, + size_t count, + loff_t *ppos) +{ + return relay_file_read_subbufs(filp, ppos, count, subbuf_read_actor, + NULL, buffer); +} + +static ssize_t relay_file_sendfile(struct file *filp, + loff_t *ppos, + size_t count, + read_actor_t actor, + void *target) +{ + return relay_file_read_subbufs(filp, ppos, count, subbuf_send_actor, + actor, target); +} + +struct file_operations relay_file_operations = { + .open = relay_file_open, + .poll = relay_file_poll, + .mmap = relay_file_mmap, + .read = relay_file_read, + .llseek = no_llseek, + .release = relay_file_release, + .sendfile = relay_file_sendfile, +}; +EXPORT_SYMBOL_GPL(relay_file_operations); diff --git a/mm/highmem.c b/mm/highmem.c index ce2e7e8bbfa7..d0ea1eec6a9a 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/hash.h> #include <linux/highmem.h> +#include <linux/blktrace_api.h> #include <asm/tlbflush.h> static mempool_t *page_pool, *isa_page_pool; @@ -483,6 +484,8 @@ void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig) pool = isa_page_pool; } + blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE); + /* * slow path */ diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 8eedaedba743..c23e9c06ee23 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -106,6 +106,9 @@ * * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com> * 050103 + * + * MPLS support by Steven Whitehouse <steve@chygwyn.com> + * */ #include <linux/sys.h> #include <linux/types.h> @@ -154,7 +157,7 @@ #include <asm/div64.h> /* do_div */ #include <asm/timex.h> -#define VERSION "pktgen v2.66: Packet Generator for packet performance testing.\n" +#define VERSION "pktgen v2.67: Packet Generator for packet performance testing.\n" /* #define PG_DEBUG(a) a */ #define PG_DEBUG(a) @@ -162,6 +165,8 @@ /* The buckets are exponential in 'width' */ #define LAT_BUCKETS_MAX 32 #define IP_NAME_SZ 32 +#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ +#define MPLS_STACK_BOTTOM __constant_htonl(0x00000100) /* Device flag bits */ #define F_IPSRC_RND (1<<0) /* IP-Src Random */ @@ -172,6 +177,7 @@ #define F_MACDST_RND (1<<5) /* MAC-Dst Random */ #define F_TXSIZE_RND (1<<6) /* Transmit size is random */ #define F_IPV6 (1<<7) /* Interface in IPV6 Mode */ +#define F_MPLS_RND (1<<8) /* Random MPLS labels */ /* Thread control flag bits */ #define T_TERMINATE (1<<0) @@ -278,6 +284,10 @@ struct pktgen_dev { __u16 udp_dst_min; /* inclusive, dest UDP port */ __u16 udp_dst_max; /* exclusive, dest UDP port */ + /* MPLS */ + unsigned nr_labels; /* Depth of stack, 0 = no MPLS */ + __be32 labels[MAX_MPLS_LABELS]; + __u32 src_mac_count; /* How many MACs to iterate through */ __u32 dst_mac_count; /* How many MACs to iterate through */ @@ -623,9 +633,19 @@ static int pktgen_if_show(struct seq_file *seq, void *v) pkt_dev->udp_dst_min, pkt_dev->udp_dst_max); seq_printf(seq, - " src_mac_count: %d dst_mac_count: %d \n Flags: ", + " src_mac_count: %d dst_mac_count: %d\n", pkt_dev->src_mac_count, pkt_dev->dst_mac_count); + if (pkt_dev->nr_labels) { + unsigned i; + seq_printf(seq, " mpls: "); + for(i = 0; i < pkt_dev->nr_labels; i++) + seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]), + i == pkt_dev->nr_labels-1 ? "\n" : ", "); + } + + seq_printf(seq, " Flags: "); + if (pkt_dev->flags & F_IPV6) seq_printf(seq, "IPV6 "); @@ -644,6 +664,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) if (pkt_dev->flags & F_UDPDST_RND) seq_printf(seq, "UDPDST_RND "); + if (pkt_dev->flags & F_MPLS_RND) + seq_printf(seq, "MPLS_RND "); + if (pkt_dev->flags & F_MACSRC_RND) seq_printf(seq, "MACSRC_RND "); @@ -691,6 +714,29 @@ static int pktgen_if_show(struct seq_file *seq, void *v) return 0; } + +static int hex32_arg(const char __user *user_buffer, __u32 *num) +{ + int i = 0; + *num = 0; + + for(; i < 8; i++) { + char c; + *num <<= 4; + if (get_user(c, &user_buffer[i])) + return -EFAULT; + if ((c >= '0') && (c <= '9')) + *num |= c - '0'; + else if ((c >= 'a') && (c <= 'f')) + *num |= c - 'a' + 10; + else if ((c >= 'A') && (c <= 'F')) + *num |= c - 'A' + 10; + else + break; + } + return i; +} + static int count_trail_chars(const char __user * user_buffer, unsigned int maxlen) { @@ -759,6 +805,35 @@ done_str: return i; } +static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) +{ + unsigned n = 0; + char c; + ssize_t i = 0; + int len; + + pkt_dev->nr_labels = 0; + do { + __u32 tmp; + len = hex32_arg(&buffer[i], &tmp); + if (len <= 0) + return len; + pkt_dev->labels[n] = htonl(tmp); + if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM) + pkt_dev->flags |= F_MPLS_RND; + i += len; + if (get_user(c, &buffer[i])) + return -EFAULT; + i++; + n++; + if (n >= MAX_MPLS_LABELS) + return -E2BIG; + } while(c == ','); + + pkt_dev->nr_labels = n; + return i; +} + static ssize_t pktgen_if_write(struct file *file, const char __user * user_buffer, size_t count, loff_t * offset) @@ -1059,6 +1134,12 @@ static ssize_t pktgen_if_write(struct file *file, else if (strcmp(f, "!MACDST_RND") == 0) pkt_dev->flags &= ~F_MACDST_RND; + else if (strcmp(f, "MPLS_RND") == 0) + pkt_dev->flags |= F_MPLS_RND; + + else if (strcmp(f, "!MPLS_RND") == 0) + pkt_dev->flags &= ~F_MPLS_RND; + else { sprintf(pg_result, "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", @@ -1354,6 +1435,19 @@ static ssize_t pktgen_if_write(struct file *file, return count; } + if (!strcmp(name, "mpls")) { + unsigned n, offset; + len = get_labels(&user_buffer[i], pkt_dev); + if (len < 0) { return len; } + i += len; + offset = sprintf(pg_result, "OK: mpls="); + for(n = 0; n < pkt_dev->nr_labels; n++) + offset += sprintf(pg_result + offset, + "%08x%s", ntohl(pkt_dev->labels[n]), + n == pkt_dev->nr_labels-1 ? "" : ","); + return count; + } + sprintf(pkt_dev->result, "No such parameter \"%s\"", name); return -EINVAL; } @@ -1846,6 +1940,15 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->hh[1] = tmp; } + if (pkt_dev->flags & F_MPLS_RND) { + unsigned i; + for(i = 0; i < pkt_dev->nr_labels; i++) + if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM) + pkt_dev->labels[i] = MPLS_STACK_BOTTOM | + (pktgen_random() & + htonl(0x000fffff)); + } + if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) { if (pkt_dev->flags & F_UDPSRC_RND) pkt_dev->cur_udp_src = @@ -1968,6 +2071,16 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->flows[flow].count++; } +static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev) +{ + unsigned i; + for(i = 0; i < pkt_dev->nr_labels; i++) { + *mpls++ = pkt_dev->labels[i] & ~MPLS_STACK_BOTTOM; + } + mpls--; + *mpls |= MPLS_STACK_BOTTOM; +} + static struct sk_buff *fill_packet_ipv4(struct net_device *odev, struct pktgen_dev *pkt_dev) { @@ -1977,6 +2090,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, int datalen, iplen; struct iphdr *iph; struct pktgen_hdr *pgh = NULL; + __be16 protocol = __constant_htons(ETH_P_IP); + __be32 *mpls; + + if (pkt_dev->nr_labels) + protocol = __constant_htons(ETH_P_MPLS_UC); /* Update any of the values, used when we're incrementing various * fields. @@ -1984,7 +2102,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, mod_cur_headers(pkt_dev); datalen = (odev->hard_header_len + 16) & ~0xf; - skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC); + skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen + + pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; @@ -1994,13 +2113,18 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, /* Reserve for ethernet and IP header */ eth = (__u8 *) skb_push(skb, 14); + mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32)); + if (pkt_dev->nr_labels) + mpls_push(mpls, pkt_dev); iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr)); udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); memcpy(eth, pkt_dev->hh, 12); - *(u16 *) & eth[12] = __constant_htons(ETH_P_IP); + *(u16 *) & eth[12] = protocol; - datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */ + /* Eth + IPh + UDPh + mpls */ + datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - + pkt_dev->nr_labels*sizeof(u32); if (datalen < sizeof(struct pktgen_hdr)) datalen = sizeof(struct pktgen_hdr); @@ -2021,8 +2145,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, iph->tot_len = htons(iplen); iph->check = 0; iph->check = ip_fast_csum((void *)iph, iph->ihl); - skb->protocol = __constant_htons(ETH_P_IP); - skb->mac.raw = ((u8 *) iph) - 14; + skb->protocol = protocol; + skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32); skb->dev = odev; skb->pkt_type = PACKET_HOST; @@ -2274,13 +2398,19 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, int datalen; struct ipv6hdr *iph; struct pktgen_hdr *pgh = NULL; + __be16 protocol = __constant_htons(ETH_P_IPV6); + __be32 *mpls; + + if (pkt_dev->nr_labels) + protocol = __constant_htons(ETH_P_MPLS_UC); /* Update any of the values, used when we're incrementing various * fields. */ mod_cur_headers(pkt_dev); - skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC); + skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 + + pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; @@ -2290,13 +2420,19 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, /* Reserve for ethernet and IP header */ eth = (__u8 *) skb_push(skb, 14); + mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32)); + if (pkt_dev->nr_labels) + mpls_push(mpls, pkt_dev); iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr)); udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); memcpy(eth, pkt_dev->hh, 12); *(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6); - datalen = pkt_dev->cur_pkt_size - 14 - sizeof(struct ipv6hdr) - sizeof(struct udphdr); /* Eth + IPh + UDPh */ + /* Eth + IPh + UDPh + mpls */ + datalen = pkt_dev->cur_pkt_size - 14 - + sizeof(struct ipv6hdr) - sizeof(struct udphdr) - + pkt_dev->nr_labels*sizeof(u32); if (datalen < sizeof(struct pktgen_hdr)) { datalen = sizeof(struct pktgen_hdr); @@ -2320,8 +2456,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr); ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr); - skb->mac.raw = ((u8 *) iph) - 14; - skb->protocol = __constant_htons(ETH_P_IPV6); + skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32); + skb->protocol = protocol; skb->dev = odev; skb->pkt_type = PACKET_HOST; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index ae10d3740faa..3fcfa9c59e1f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -51,6 +51,10 @@ #include <net/sock.h> #include <net/pkt_sched.h> #include <net/netlink.h> +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +#include <linux/wireless.h> +#include <net/iw_handler.h> +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ static DEFINE_MUTEX(rtnl_mutex); @@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) goto out; } +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + if (ida[IFLA_WIRELESS - 1]) { + + /* Call Wireless Extensions. + * Various stuff checked in there... */ + err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len); + if (err) + goto out; + } +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + err = 0; out: @@ -477,6 +492,83 @@ out: return err; } +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg) +{ + struct ifinfomsg *ifm = NLMSG_DATA(in_nlh); + struct rtattr **ida = arg; + struct net_device *dev; + struct ifinfomsg *r; + struct nlmsghdr *nlh; + int err = -ENOBUFS; + struct sk_buff *skb; + unsigned char *b; + char *iw_buf = NULL; + int iw_buf_len = 0; + + if (ifm->ifi_index >= 0) + dev = dev_get_by_index(ifm->ifi_index); + else + return -EINVAL; + if (!dev) + return -ENODEV; + +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + if (ida[IFLA_WIRELESS - 1]) { + + /* Call Wireless Extensions. We need to know the size before + * we can alloc. Various stuff checked in there... */ + err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len); + if (err) + goto out; + } +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + + /* Create a skb big enough to include all the data. + * Some requests are way bigger than 4k... Jean II */ + skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)), + GFP_KERNEL); + if (!skb) + goto out; + b = skb->tail; + + /* Put in the message the usual good stuff */ + nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq, + RTM_NEWLINK, sizeof(*r)); + r = NLMSG_DATA(nlh); + r->ifi_family = AF_UNSPEC; + r->__ifi_pad = 0; + r->ifi_type = dev->type; + r->ifi_index = dev->ifindex; + r->ifi_flags = dev->flags; + r->ifi_change = 0; + + /* Put the wireless payload if it exist */ + if(iw_buf != NULL) + RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len, + iw_buf + IW_EV_POINT_OFF); + + nlh->nlmsg_len = skb->tail - b; + + /* Needed ? */ + NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; + + err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); + if (err > 0) + err = 0; +out: + if(iw_buf != NULL) + kfree(iw_buf); + dev_put(dev); + return err; + +rtattr_failure: +nlmsg_failure: + kfree_skb(skb); + goto out; +} +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) { int idx; @@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len) static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = { - [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, + [RTM_GETLINK - RTM_BASE] = { +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + .doit = do_getlink, +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + .dumpit = rtnetlink_dump_ifinfo }, [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, diff --git a/net/core/wireless.c b/net/core/wireless.c index 2add7ed609e9..81d6995fcfdb 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -2,7 +2,7 @@ * This file implement the Wireless Extensions APIs. * * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. * * (As all part of the Linux kernel, this file is GPL) */ @@ -65,6 +65,9 @@ * o Start deprecating dev->get_wireless_stats, output a warning * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless * o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats) + * + * v8 - 17.02.06 - Jean II + * o RtNetlink requests support (SET/GET) */ /***************************** INCLUDES *****************************/ @@ -89,11 +92,13 @@ /* Debugging stuff */ #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ +#undef WE_RTNETLINK_DEBUG /* Debug RtNetlink API */ #undef WE_EVENT_DEBUG /* Debug Event dispatcher */ #undef WE_SPY_DEBUG /* Debug enhanced spy support */ /* Options */ -#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ +//CONFIG_NET_WIRELESS_RTNETLINK /* Wireless requests over RtNetlink */ +#define WE_EVENT_RTNETLINK /* Propagate events using RtNetlink */ #define WE_SET_EVENT /* Generate an event on some set commands */ /************************* GLOBAL VARIABLES *************************/ @@ -156,13 +161,18 @@ static const struct iw_ioctl_description standard_ioctl[] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ - .header_type = IW_HEADER_TYPE_NULL, + .header_type = IW_HEADER_TYPE_POINT, + .token_size = sizeof(struct iw_priv_args), + .max_tokens = 16, + .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWSTATS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ - .header_type = IW_HEADER_TYPE_NULL, + .header_type = IW_HEADER_TYPE_POINT, + .token_size = 1, + .max_tokens = sizeof(struct iw_statistics), .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWSPY - SIOCIWFIRST] = { @@ -529,6 +539,70 @@ static inline int adjust_priv_size(__u16 args, return num * iw_priv_type_size[type]; } +/* ---------------------------------------------------------------- */ +/* + * Standard Wireless Handler : get wireless stats + * Allow programatic access to /proc/net/wireless even if /proc + * doesn't exist... Also more efficient... + */ +static int iw_handler_get_iwstats(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) +{ + /* Get stats from the driver */ + struct iw_statistics *stats; + + stats = get_wireless_stats(dev); + if (stats != (struct iw_statistics *) NULL) { + + /* Copy statistics to extra */ + memcpy(extra, stats, sizeof(struct iw_statistics)); + wrqu->data.length = sizeof(struct iw_statistics); + + /* Check if we need to clear the updated flag */ + if(wrqu->data.flags != 0) + stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; + return 0; + } else + return -EOPNOTSUPP; +} + +/* ---------------------------------------------------------------- */ +/* + * Standard Wireless Handler : get iwpriv definitions + * Export the driver private handler definition + * They will be picked up by tools like iwpriv... + */ +static int iw_handler_get_private(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) +{ + /* Check if the driver has something to export */ + if((dev->wireless_handlers->num_private_args == 0) || + (dev->wireless_handlers->private_args == NULL)) + return -EOPNOTSUPP; + + /* Check if there is enough buffer up there */ + if(wrqu->data.length < dev->wireless_handlers->num_private_args) { + /* User space can't know in advance how large the buffer + * needs to be. Give it a hint, so that we can support + * any size buffer we want somewhat efficiently... */ + wrqu->data.length = dev->wireless_handlers->num_private_args; + return -E2BIG; + } + + /* Set the number of available ioctls. */ + wrqu->data.length = dev->wireless_handlers->num_private_args; + + /* Copy structure to the user buffer. */ + memcpy(extra, dev->wireless_handlers->private_args, + sizeof(struct iw_priv_args) * wrqu->data.length); + + return 0; +} + /******************** /proc/net/wireless SUPPORT ********************/ /* @@ -630,81 +704,14 @@ int __init wireless_proc_init(void) /* ---------------------------------------------------------------- */ /* - * Allow programatic access to /proc/net/wireless even if /proc - * doesn't exist... Also more efficient... - */ -static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr) -{ - /* Get stats from the driver */ - struct iw_statistics *stats; - - stats = get_wireless_stats(dev); - if (stats != (struct iw_statistics *) NULL) { - struct iwreq * wrq = (struct iwreq *)ifr; - - /* Copy statistics to the user buffer */ - if(copy_to_user(wrq->u.data.pointer, stats, - sizeof(struct iw_statistics))) - return -EFAULT; - - /* Check if we need to clear the updated flag */ - if(wrq->u.data.flags != 0) - stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; - return 0; - } else - return -EOPNOTSUPP; -} - -/* ---------------------------------------------------------------- */ -/* - * Export the driver private handler definition - * They will be picked up by tools like iwpriv... - */ -static inline int ioctl_export_private(struct net_device * dev, - struct ifreq * ifr) -{ - struct iwreq * iwr = (struct iwreq *) ifr; - - /* Check if the driver has something to export */ - if((dev->wireless_handlers->num_private_args == 0) || - (dev->wireless_handlers->private_args == NULL)) - return -EOPNOTSUPP; - - /* Check NULL pointer */ - if(iwr->u.data.pointer == NULL) - return -EFAULT; - - /* Check if there is enough buffer up there */ - if(iwr->u.data.length < dev->wireless_handlers->num_private_args) { - /* User space can't know in advance how large the buffer - * needs to be. Give it a hint, so that we can support - * any size buffer we want somewhat efficiently... */ - iwr->u.data.length = dev->wireless_handlers->num_private_args; - return -E2BIG; - } - - /* Set the number of available ioctls. */ - iwr->u.data.length = dev->wireless_handlers->num_private_args; - - /* Copy structure to the user buffer. */ - if (copy_to_user(iwr->u.data.pointer, - dev->wireless_handlers->private_args, - sizeof(struct iw_priv_args) * iwr->u.data.length)) - return -EFAULT; - - return 0; -} - -/* ---------------------------------------------------------------- */ -/* * Wrapper to call a standard Wireless Extension handler. * We do various checks and also take care of moving data between * user space and kernel space. */ -static inline int ioctl_standard_call(struct net_device * dev, - struct ifreq * ifr, - unsigned int cmd, - iw_handler handler) +static int ioctl_standard_call(struct net_device * dev, + struct ifreq * ifr, + unsigned int cmd, + iw_handler handler) { struct iwreq * iwr = (struct iwreq *) ifr; const struct iw_ioctl_description * descr; @@ -1048,14 +1055,20 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) { case SIOCGIWSTATS: /* Get Wireless Stats */ - return dev_iwstats(dev, ifr); + return ioctl_standard_call(dev, + ifr, + cmd, + &iw_handler_get_iwstats); case SIOCGIWPRIV: /* Check if we have some wireless handlers defined */ if(dev->wireless_handlers != NULL) { /* We export to user space the definition of * the private handler ourselves */ - return ioctl_export_private(dev, ifr); + return ioctl_standard_call(dev, + ifr, + cmd, + &iw_handler_get_private); } // ## Fall-through for old API ## default: @@ -1088,16 +1101,739 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) return -EINVAL; } +/********************** RTNETLINK REQUEST API **********************/ +/* + * The alternate user space API to configure all those Wireless Extensions + * is through RtNetlink. + * This API support only the new driver API (iw_handler). + * + * This RtNetlink API use the same query/reply model as the ioctl API. + * Maximum effort has been done to fit in the RtNetlink model, and + * we support both RtNetlink Set and RtNelink Get operations. + * On the other hand, we don't offer Dump operations because of the + * following reasons : + * o Large number of parameters, most optional + * o Large size of some parameters (> 100 bytes) + * o Each parameters need to be extracted from hardware + * o Scan requests can take seconds and disable network activity. + * Because of this high cost/overhead, we want to return only the + * parameters the user application is really interested in. + * We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag. + * + * The API uses the standard RtNetlink socket. When the RtNetlink code + * find a IFLA_WIRELESS field in a RtNetlink SET_LINK request, + * it calls here. + */ + +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a standard Wireless Extension GET handler. + * We do various checks and call the handler with the proper args. + */ +static int rtnetlink_standard_get(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler, + char ** p_buf, + int * p_len) +{ + const struct iw_ioctl_description * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + int hdr_len; + struct iw_request_info info; + char * buffer = NULL; + int buffer_size = 0; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + if((cmd - SIOCIWFIRST) >= standard_ioctl_num) + return -EOPNOTSUPP; + descr = &(standard_ioctl[cmd - SIOCIWFIRST]); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found standard handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Check if wrqu is complete */ + hdr_len = event_type_size[descr->header_type]; + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have extra data in the reply or not */ + if(descr->header_type != IW_HEADER_TYPE_POINT) { + + /* Create the kernel buffer that we will return. + * It's at an offset to match the TYPE_POINT case... */ + buffer_size = request_len + IW_EV_POINT_OFF; + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + /* Copy event data */ + memcpy(buffer + IW_EV_POINT_OFF, request, request_len); + /* Use our own copy of wrqu */ + wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF + + IW_EV_LCP_LEN); + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, NULL); + + } else { + union iwreq_data wrqu_point; + char * extra = NULL; + int extra_size = 0; + + /* Get a temp copy of wrqu (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + ((char *) request) + IW_EV_LCP_LEN, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + + /* Calculate space needed by arguments. Always allocate + * for max space. Easier, and won't last long... */ + extra_size = descr->max_tokens * descr->token_size; + /* Support for very large requests */ + if((descr->flags & IW_DESCR_FLAG_NOMAX) && + (wrqu_point.data.length > descr->max_tokens)) + extra_size = (wrqu_point.data.length + * descr->token_size); + buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", + dev->name, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Create the kernel buffer that we will return */ + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + + /* Put wrqu in the right place (just before extra). + * Leave space for IWE header and dummy pointer... + * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... + */ + memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, + ((char *) &wrqu_point) + IW_EV_POINT_OFF, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); + + /* Extra comes logically after that. Offset +12 bytes. */ + extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; + + /* Call the handler */ + ret = handler(dev, &info, wrqu, extra); + + /* Calculate real returned length */ + extra_size = (wrqu->data.length * descr->token_size); + /* Re-adjust reply size */ + request->len = extra_size + IW_EV_POINT_LEN; + + /* Put the iwe header where it should, i.e. scrap the + * dummy pointer. */ + memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Check if there is enough buffer up there */ + if(wrqu_point.data.length < wrqu->data.length) + ret = -E2BIG; + } + + /* Return the buffer to the caller */ + if (!ret) { + *p_buf = buffer; + *p_len = request->len; + } else { + /* Cleanup */ + if(buffer) + kfree(buffer); + } + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a standard Wireless Extension SET handler. + * We do various checks and call the handler with the proper args. + */ +static inline int rtnetlink_standard_set(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler) +{ + const struct iw_ioctl_description * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + union iwreq_data wrqu_point; + int hdr_len; + char * extra = NULL; + int extra_size = 0; + struct iw_request_info info; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + if((cmd - SIOCIWFIRST) >= standard_ioctl_num) + return -EOPNOTSUPP; + descr = &(standard_ioctl[cmd - SIOCIWFIRST]); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found standard SET handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Extract fixed header from request. This is properly aligned. */ + wrqu = &request->u; + + /* Check if wrqu is complete */ + hdr_len = event_type_size[descr->header_type]; + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have extra data in the request or not */ + if(descr->header_type != IW_HEADER_TYPE_POINT) { + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, NULL); + + } else { + int extra_len; + + /* Put wrqu in the right place (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); + /* Don't forget about the event code... */ + wrqu = &wrqu_point; + + /* Check if number of token fits within bounds */ + if(wrqu_point.data.length > descr->max_tokens) + return -E2BIG; + if(wrqu_point.data.length < descr->min_tokens) + return -EINVAL; + + /* Real length of payload */ + extra_len = wrqu_point.data.length * descr->token_size; + + /* Check if request is self consistent */ + if((request_len - hdr_len) < extra_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Always allocate for max space. Easier, and won't last + * long... */ + extra_size = descr->max_tokens * descr->token_size; + extra = kmalloc(extra_size, GFP_KERNEL); + if (extra == NULL) + return -ENOMEM; + + /* Copy extra in aligned buffer */ + memcpy(extra, ((char *) request) + hdr_len, extra_len); + + /* Call the handler */ + ret = handler(dev, &info, &wrqu_point, extra); + } + +#ifdef WE_SET_EVENT + /* Generate an event to notify listeners of the change */ + if((descr->flags & IW_DESCR_FLAG_EVENT) && + ((ret == 0) || (ret == -EIWCOMMIT))) { + if(descr->flags & IW_DESCR_FLAG_RESTRICT) + /* If the event is restricted, don't + * export the payload */ + wireless_send_event(dev, cmd, wrqu, NULL); + else + wireless_send_event(dev, cmd, wrqu, extra); + } +#endif /* WE_SET_EVENT */ + + /* Cleanup - I told you it wasn't that long ;-) */ + if(extra) + kfree(extra); + + /* Call commit handler if needed and defined */ + if(ret == -EIWCOMMIT) + ret = call_commit_handler(dev); + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a private Wireless Extension GET handler. + * Same as above... + * It's not as nice and slimline as the standard wrapper. The cause + * is struct iw_priv_args, which was not really designed for the + * job we are going here. + * + * IMPORTANT : This function prevent to set and get data on the same + * IOCTL and enforce the SET/GET convention. Not doing it would be + * far too hairy... + * If you need to set and get data at the same time, please don't use + * a iw_handler but process it in your ioctl handler (i.e. use the + * old driver API). + */ +static inline int rtnetlink_private_get(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler, + char ** p_buf, + int * p_len) +{ + const struct iw_priv_args * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + int hdr_len; + struct iw_request_info info; + int extra_size = 0; + int i; + char * buffer = NULL; + int buffer_size = 0; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + for(i = 0; i < dev->wireless_handlers->num_private_args; i++) + if(cmd == dev->wireless_handlers->private_args[i].cmd) { + descr = &(dev->wireless_handlers->private_args[i]); + break; + } + if(descr == NULL) + return -EOPNOTSUPP; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n", + dev->name, descr->name, descr->set_args, descr->get_args); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Compute the max size of the get arguments */ + extra_size = get_priv_size(descr->get_args); + + /* Does it fits in wrqu ? */ + if((descr->get_args & IW_PRIV_SIZE_FIXED) && + (extra_size <= IFNAMSIZ)) { + hdr_len = extra_size; + extra_size = 0; + } else { + hdr_len = IW_EV_POINT_LEN; + } + + /* Check if wrqu is complete */ + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have a pointer to user space data or not. */ + if(extra_size == 0) { + + /* Create the kernel buffer that we will return. + * It's at an offset to match the TYPE_POINT case... */ + buffer_size = request_len + IW_EV_POINT_OFF; + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + /* Copy event data */ + memcpy(buffer + IW_EV_POINT_OFF, request, request_len); + /* Use our own copy of wrqu */ + wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF + + IW_EV_LCP_LEN); + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, (char *) wrqu); + + } else { + char * extra; + + /* Buffer for full reply */ + buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", + dev->name, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Create the kernel buffer that we will return */ + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + + /* Put wrqu in the right place (just before extra). + * Leave space for IWE header and dummy pointer... + * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... + */ + memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, + ((char *) request) + IW_EV_LCP_LEN, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); + + /* Extra comes logically after that. Offset +12 bytes. */ + extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; + + /* Call the handler */ + ret = handler(dev, &info, wrqu, extra); + + /* Adjust for the actual length if it's variable, + * avoid leaking kernel bits outside. */ + if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) + extra_size = adjust_priv_size(descr->get_args, wrqu); + /* Re-adjust reply size */ + request->len = extra_size + IW_EV_POINT_LEN; + + /* Put the iwe header where it should, i.e. scrap the + * dummy pointer. */ + memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + } + + /* Return the buffer to the caller */ + if (!ret) { + *p_buf = buffer; + *p_len = request->len; + } else { + /* Cleanup */ + if(buffer) + kfree(buffer); + } + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a private Wireless Extension SET handler. + * Same as above... + * It's not as nice and slimline as the standard wrapper. The cause + * is struct iw_priv_args, which was not really designed for the + * job we are going here. + * + * IMPORTANT : This function prevent to set and get data on the same + * IOCTL and enforce the SET/GET convention. Not doing it would be + * far too hairy... + * If you need to set and get data at the same time, please don't use + * a iw_handler but process it in your ioctl handler (i.e. use the + * old driver API). + */ +static inline int rtnetlink_private_set(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler) +{ + const struct iw_priv_args * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + union iwreq_data wrqu_point; + int hdr_len; + char * extra = NULL; + int extra_size = 0; + int offset = 0; /* For sub-ioctls */ + struct iw_request_info info; + int i; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + for(i = 0; i < dev->wireless_handlers->num_private_args; i++) + if(cmd == dev->wireless_handlers->private_args[i].cmd) { + descr = &(dev->wireless_handlers->private_args[i]); + break; + } + if(descr == NULL) + return -EOPNOTSUPP; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n", + ifr->ifr_name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n", + dev->name, descr->name, descr->set_args, descr->get_args); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Compute the size of the set arguments */ + /* Check for sub-ioctl handler */ + if(descr->name[0] == '\0') + /* Reserve one int for sub-ioctl index */ + offset = sizeof(__u32); + + /* Size of set arguments */ + extra_size = get_priv_size(descr->set_args); + + /* Does it fits in wrqu ? */ + if((descr->set_args & IW_PRIV_SIZE_FIXED) && + (extra_size <= IFNAMSIZ)) { + hdr_len = IW_EV_LCP_LEN + extra_size; + extra_size = 0; + } else { + hdr_len = IW_EV_POINT_LEN; + } + + /* Extract fixed header from request. This is properly aligned. */ + wrqu = &request->u; + + /* Check if wrqu is complete */ + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have a pointer to user space data or not. */ + if(extra_size == 0) { + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, (char *) wrqu); + + } else { + int extra_len; + + /* Put wrqu in the right place (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); + + /* Does it fits within bounds ? */ + if(wrqu_point.data.length > (descr->set_args & + IW_PRIV_SIZE_MASK)) + return -E2BIG; + + /* Real length of payload */ + extra_len = adjust_priv_size(descr->set_args, &wrqu_point); + + /* Check if request is self consistent */ + if((request_len - hdr_len) < extra_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Always allocate for max space. Easier, and won't last + * long... */ + extra = kmalloc(extra_size, GFP_KERNEL); + if (extra == NULL) + return -ENOMEM; + + /* Copy extra in aligned buffer */ + memcpy(extra, ((char *) request) + hdr_len, extra_len); + + /* Call the handler */ + ret = handler(dev, &info, &wrqu_point, extra); + + /* Cleanup - I told you it wasn't that long ;-) */ + kfree(extra); + } + + /* Call commit handler if needed and defined */ + if(ret == -EIWCOMMIT) + ret = call_commit_handler(dev); + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Main RtNetlink dispatcher. Called from the main networking code + * (do_getlink() in net/core/rtnetlink.c). + * Check the type of Request and call the appropriate wrapper... + */ +int wireless_rtnetlink_get(struct net_device * dev, + char * data, + int len, + char ** p_buf, + int * p_len) +{ + struct iw_event * request = (struct iw_event *) data; + iw_handler handler; + + /* Check length */ + if(len < IW_EV_LCP_LEN) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", + dev->name, len); + return -EINVAL; + } + + /* ReCheck length (len may have padding) */ + if(request->len > len) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n", + dev->name, request->len, len); + return -EINVAL; + } + + /* Only accept GET requests in here */ + if(!IW_IS_GET(request->cmd)) + return -EOPNOTSUPP; + + /* Special cases */ + if(request->cmd == SIOCGIWSTATS) + /* Get Wireless Stats */ + return rtnetlink_standard_get(dev, + request, + request->len, + &iw_handler_get_iwstats, + p_buf, p_len); + if(request->cmd == SIOCGIWPRIV) { + /* Check if we have some wireless handlers defined */ + if(dev->wireless_handlers == NULL) + return -EOPNOTSUPP; + /* Get Wireless Stats */ + return rtnetlink_standard_get(dev, + request, + request->len, + &iw_handler_get_private, + p_buf, p_len); + } + + /* Basic check */ + if (!netif_device_present(dev)) + return -ENODEV; + + /* Try to find the handler */ + handler = get_handler(dev, request->cmd); + if(handler != NULL) { + /* Standard and private are not the same */ + if(request->cmd < SIOCIWFIRSTPRIV) + return rtnetlink_standard_get(dev, + request, + request->len, + handler, + p_buf, p_len); + else + return rtnetlink_private_get(dev, + request, + request->len, + handler, + p_buf, p_len); + } + + return -EOPNOTSUPP; +} + +/* ---------------------------------------------------------------- */ +/* + * Main RtNetlink dispatcher. Called from the main networking code + * (do_setlink() in net/core/rtnetlink.c). + * Check the type of Request and call the appropriate wrapper... + */ +int wireless_rtnetlink_set(struct net_device * dev, + char * data, + int len) +{ + struct iw_event * request = (struct iw_event *) data; + iw_handler handler; + + /* Check length */ + if(len < IW_EV_LCP_LEN) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", + dev->name, len); + return -EINVAL; + } + + /* ReCheck length (len may have padding) */ + if(request->len > len) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n", + dev->name, request->len, len); + return -EINVAL; + } + + /* Only accept SET requests in here */ + if(!IW_IS_SET(request->cmd)) + return -EOPNOTSUPP; + + /* Basic check */ + if (!netif_device_present(dev)) + return -ENODEV; + + /* New driver API : try to find the handler */ + handler = get_handler(dev, request->cmd); + if(handler != NULL) { + /* Standard and private are not the same */ + if(request->cmd < SIOCIWFIRSTPRIV) + return rtnetlink_standard_set(dev, + request, + request->len, + handler); + else + return rtnetlink_private_set(dev, + request, + request->len, + handler); + } + + return -EOPNOTSUPP; +} +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + + /************************* EVENT PROCESSING *************************/ /* * Process events generated by the wireless layer or the driver. * Most often, the event will be propagated through rtnetlink */ -#ifdef WE_EVENT_NETLINK -/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here. - * It is declared in <linux/rtnetlink.h> */ - +#ifdef WE_EVENT_RTNETLINK /* ---------------------------------------------------------------- */ /* * Fill a rtnetlink message with our event data. @@ -1121,12 +1857,11 @@ static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb, r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; - r->ifi_flags = dev->flags; + r->ifi_flags = dev_get_flags(dev); r->ifi_change = 0; /* Wireless changes don't affect those flags */ /* Add the wireless events in the netlink packet */ - RTA_PUT(skb, IFLA_WIRELESS, - event_len, event); + RTA_PUT(skb, IFLA_WIRELESS, event_len, event); nlh->nlmsg_len = skb->tail - b; return skb->len; @@ -1163,7 +1898,7 @@ static inline void rtmsg_iwinfo(struct net_device * dev, NETLINK_CB(skb).dst_group = RTNLGRP_LINK; netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); } -#endif /* WE_EVENT_NETLINK */ +#endif /* WE_EVENT_RTNETLINK */ /* ---------------------------------------------------------------- */ /* @@ -1255,10 +1990,10 @@ void wireless_send_event(struct net_device * dev, if(extra != NULL) memcpy(((char *) event) + hdr_len, extra, extra_len); -#ifdef WE_EVENT_NETLINK - /* rtnetlink event channel */ +#ifdef WE_EVENT_RTNETLINK + /* Send via the RtNetlink event channel */ rtmsg_iwinfo(dev, (char *) event, event_len); -#endif /* WE_EVENT_NETLINK */ +#endif /* WE_EVENT_RTNETLINK */ /* Cleanup */ kfree(event); diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index d18ccba3ea9e..dbb08528ddf5 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig @@ -66,3 +66,4 @@ config IEEE80211_CRYPT_TKIP This can be compiled as a modules and it will be called "ieee80211_crypt_tkip". +source "net/ieee80211/softmac/Kconfig" diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile index f988417121da..796a7c76ee48 100644 --- a/net/ieee80211/Makefile +++ b/net/ieee80211/Makefile @@ -10,3 +10,4 @@ ieee80211-objs := \ ieee80211_wx.o \ ieee80211_geo.o +obj-$(CONFIG_IEEE80211_SOFTMAC) += softmac/ diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index a7f2a642a512..604b7b0097bc 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -780,6 +780,80 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, return 0; } +/* Filter out unrelated packets, call ieee80211_rx[_mgt] */ +int ieee80211_rx_any(struct ieee80211_device *ieee, + struct sk_buff *skb, struct ieee80211_rx_stats *stats) +{ + struct ieee80211_hdr_4addr *hdr; + int is_packet_for_us; + u16 fc; + + if (ieee->iw_mode == IW_MODE_MONITOR) + return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL; + + hdr = (struct ieee80211_hdr_4addr *)skb->data; + fc = le16_to_cpu(hdr->frame_ctl); + + if ((fc & IEEE80211_FCTL_VERS) != 0) + return -EINVAL; + + switch (fc & IEEE80211_FCTL_FTYPE) { + case IEEE80211_FTYPE_MGMT: + ieee80211_rx_mgt(ieee, hdr, stats); + return 0; + case IEEE80211_FTYPE_DATA: + break; + case IEEE80211_FTYPE_CTL: + return 0; + default: + return -EINVAL; + } + + is_packet_for_us = 0; + switch (ieee->iw_mode) { + case IW_MODE_ADHOC: + /* our BSS and not from/to DS */ + if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0) + if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) { + /* promisc: get all */ + if (ieee->dev->flags & IFF_PROMISC) + is_packet_for_us = 1; + /* to us */ + else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0) + is_packet_for_us = 1; + /* mcast */ + else if (is_multicast_ether_addr(hdr->addr1)) + is_packet_for_us = 1; + } + break; + case IW_MODE_INFRA: + /* our BSS (== from our AP) and from DS */ + if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0) + if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) { + /* promisc: get all */ + if (ieee->dev->flags & IFF_PROMISC) + is_packet_for_us = 1; + /* to us */ + else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0) + is_packet_for_us = 1; + /* mcast */ + else if (is_multicast_ether_addr(hdr->addr1)) { + /* not our own packet bcasted from AP */ + if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN)) + is_packet_for_us = 1; + } + } + break; + default: + /* ? */ + break; + } + + if (is_packet_for_us) + return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL); + return 0; +} + #define MGMT_FRAME_FIXED_PART_LENGTH 0x24 static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig new file mode 100644 index 000000000000..6cd9f3427be6 --- /dev/null +++ b/net/ieee80211/softmac/Kconfig @@ -0,0 +1,10 @@ +config IEEE80211_SOFTMAC + tristate "Software MAC add-on to the IEEE 802.11 networking stack" + depends on IEEE80211 && EXPERIMENTAL + ---help--- + This option enables the hardware independent software MAC addon + for the IEEE 802.11 networking stack. + +config IEEE80211_SOFTMAC_DEBUG + bool "Enable full debugging output" + depends on IEEE80211_SOFTMAC diff --git a/net/ieee80211/softmac/Makefile b/net/ieee80211/softmac/Makefile new file mode 100644 index 000000000000..bfcb391bb2c7 --- /dev/null +++ b/net/ieee80211/softmac/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_IEEE80211_SOFTMAC) += ieee80211softmac.o +ieee80211softmac-objs := \ + ieee80211softmac_io.o \ + ieee80211softmac_auth.o \ + ieee80211softmac_module.o \ + ieee80211softmac_scan.o \ + ieee80211softmac_wx.o \ + ieee80211softmac_assoc.o \ + ieee80211softmac_event.o diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c new file mode 100644 index 000000000000..be61de78dfa4 --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -0,0 +1,396 @@ +/* + * This file contains the softmac's association logic. + * + * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#include "ieee80211softmac_priv.h" + +/* + * Overview + * + * Before you can associate, you have to authenticate. + * + */ + +/* Sends out an association request to the desired AP */ +static void +ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) +{ + unsigned long flags; + + /* Switch to correct channel for this network */ + mac->set_channel(mac->dev, net->channel); + + /* Send association request */ + ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_ASSOC_REQ, 0); + + dprintk(KERN_INFO PFX "sent association request!\n"); + + /* Change the state to associating */ + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.associating = 1; + mac->associated = 0; /* just to make sure */ + spin_unlock_irqrestore(&mac->lock, flags); + + /* Set a timer for timeout */ + /* FIXME: make timeout configurable */ + schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); +} + +void +ieee80211softmac_assoc_timeout(void *d) +{ + struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + /* we might race against ieee80211softmac_handle_assoc_response, + * so make sure only one of us does something */ + if (!mac->associnfo.associating) { + spin_unlock_irqrestore(&mac->lock, flags); + return; + } + mac->associnfo.associating = 0; + mac->associnfo.bssvalid = 0; + mac->associated = 0; + spin_unlock_irqrestore(&mac->lock, flags); + + dprintk(KERN_INFO PFX "assoc request timed out!\n"); + /* FIXME: we need to know the network here. that requires a bit of restructuring */ + ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL); +} + +/* Sends out a disassociation request to the desired AP */ +static void +ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason) +{ + unsigned long flags; + struct ieee80211softmac_network *found; + + if (mac->associnfo.bssvalid && mac->associated) { + found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); + if (found) + ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); + } else if (mac->associnfo.associating) { + cancel_delayed_work(&mac->associnfo.timeout); + } + + /* Change our state */ + spin_lock_irqsave(&mac->lock, flags); + /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */ + mac->associated = 0; + mac->associnfo.associating = 0; + spin_unlock_irqrestore(&mac->lock, flags); +} + +static inline int +we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len) +{ + int idx, search, found; + u8 rate, search_rate; + + for (idx = 0; idx < (from_len); idx++) { + rate = (from)[idx]; + if (!(rate & IEEE80211_BASIC_RATE_MASK)) + continue; + found = 0; + rate &= ~IEEE80211_BASIC_RATE_MASK; + for (search = 0; search < mac->ratesinfo.count; search++) { + search_rate = mac->ratesinfo.rates[search]; + search_rate &= ~IEEE80211_BASIC_RATE_MASK; + if (rate == search_rate) { + found = 1; + break; + } + } + if (!found) + return 0; + } + return 1; +} + +static int +network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_network *net) +{ + /* we cannot associate to networks whose name we don't know */ + if (ieee80211_is_empty_essid(net->ssid, net->ssid_len)) + return 0; + /* do not associate to a network whose BSSBasicRateSet we cannot support */ + if (!we_support_all_basic_rates(mac, net->rates, net->rates_len)) + return 0; + /* do we really need to check the ex rates? */ + if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) + return 0; + + /* if 'ANY' network requested, take any that doesn't have privacy enabled */ + if (mac->associnfo.req_essid.len == 0 + && !(net->capability & WLAN_CAPABILITY_PRIVACY)) + return 1; + if (net->ssid_len != mac->associnfo.req_essid.len) + return 0; + if (!memcmp(net->ssid, mac->associnfo.req_essid.data, mac->associnfo.req_essid.len)) + return 1; + return 0; +} + +static void +ieee80211softmac_assoc_notify(struct net_device *dev, void *context) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + ieee80211softmac_assoc_work((void*)mac); +} + +/* This function is called to handle userspace requests (asynchronously) */ +void +ieee80211softmac_assoc_work(void *d) +{ + struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; + struct ieee80211softmac_network *found = NULL; + struct ieee80211_network *net = NULL, *best = NULL; + unsigned long flags; + + /* meh */ + if (mac->associated) + ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); + + /* try to find the requested network in our list, if we found one already */ + if (mac->associnfo.bssvalid) + found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); + + /* Search the ieee80211 networks for this network if we didn't find it by bssid, + * but only if we've scanned at least once (to get a better list of networks to + * select from). If we have not scanned before, the !found logic below will be + * invoked and will scan. */ + if (!found && (mac->associnfo.scan_retry < IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT)) + { + s8 rssi = -128; /* if I don't initialise, gcc emits an invalid warning + because it cannot follow the best pointer logic. */ + spin_lock_irqsave(&mac->ieee->lock, flags); + list_for_each_entry(net, &mac->ieee->network_list, list) { + /* we're supposed to find the network with + * the best signal here, as we're asked to join + * any network with a specific ESSID, and many + * different ones could have that. + * + * I'll for now just go with the reported rssi. + * + * We also should take into account the rateset + * here to find the best BSSID to try. + */ + if (network_matches_request(mac, net)) { + if (!best) { + best = net; + rssi = best->stats.rssi; + continue; + } + /* we already had a matching network, so + * compare their properties to get the + * better of the two ... (see above) + */ + if (rssi < net->stats.rssi) { + best = net; + rssi = best->stats.rssi; + } + } + } + /* if we unlock here, we might get interrupted and the `best' + * pointer could go stale */ + if (best) { + found = ieee80211softmac_create_network(mac, best); + /* if found is still NULL, then we got -ENOMEM somewhere */ + if (found) + ieee80211softmac_add_network(mac, found); + } + spin_unlock_irqrestore(&mac->ieee->lock, flags); + } + + if (!found) { + if (mac->associnfo.scan_retry > 0) { + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.scan_retry--; + spin_unlock_irqrestore(&mac->lock, flags); + + /* We know of no such network. Let's scan. + * NB: this also happens if we had no memory to copy the network info... + * Maybe we can hope to have more memory after scanning finishes ;) + */ + dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n"); + ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL); + if (ieee80211softmac_start_scan(mac)) + dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); + return; + } + else { + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.associating = 0; + mac->associated = 0; + spin_unlock_irqrestore(&mac->lock, flags); + + dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); + ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); + return; + } + } + + mac->associnfo.bssvalid = 1; + memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); + /* copy the ESSID for displaying it */ + mac->associnfo.associate_essid.len = found->essid.len; + memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); + + /* we found a network! authenticate (if necessary) and associate to it. */ + if (!found->authenticated) { + /* This relies on the fact that _auth_req only queues the work, + * otherwise adding the notification would be racy. */ + if (!ieee80211softmac_auth_req(mac, found)) { + dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n"); + ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL); + } else { + printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n"); + ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); + } + return; + } + /* finally! now we can start associating */ + ieee80211softmac_assoc(mac, found); +} + +/* call this to do whatever is necessary when we're associated */ +static void +ieee80211softmac_associated(struct ieee80211softmac_device *mac, + struct ieee80211_assoc_response * resp, + struct ieee80211softmac_network *net) +{ + mac->associnfo.associating = 0; + mac->associated = 1; + if (mac->set_bssid_filter) + mac->set_bssid_filter(mac->dev, net->bssid); + memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN); + netif_carrier_on(mac->dev); + + mac->association_id = le16_to_cpup(&resp->aid); +} + +/* received frame handling functions */ +int +ieee80211softmac_handle_assoc_response(struct net_device * dev, + struct ieee80211_assoc_response * resp, + struct ieee80211_network * _ieee80211_network_do_not_use) +{ + /* NOTE: the network parameter has to be ignored by + * this code because it is the ieee80211's pointer + * to the struct, not ours (we made a copy) + */ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + u16 status = le16_to_cpup(&resp->status); + struct ieee80211softmac_network *network = NULL; + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + + if (!mac->associnfo.associating) { + /* we race against the timeout function, so make sure + * only one of us can do work */ + spin_unlock_irqrestore(&mac->lock, flags); + return 0; + } + network = ieee80211softmac_get_network_by_bssid_locked(mac, resp->header.addr3); + + /* someone sending us things without us knowing him? Ignore. */ + if (!network) { + dprintk(KERN_INFO PFX "Received unrequested assocation response from " MAC_FMT "\n", MAC_ARG(resp->header.addr3)); + spin_unlock_irqrestore(&mac->lock, flags); + return 0; + } + + /* now that we know it was for us, we can cancel the timeout */ + cancel_delayed_work(&mac->associnfo.timeout); + + switch (status) { + case 0: + dprintk(KERN_INFO PFX "associated!\n"); + ieee80211softmac_associated(mac, resp, network); + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, network); + break; + case WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH: + if (!network->auth_desynced_once) { + /* there seem to be a few rare cases where our view of + * the world is obscured, or buggy APs that don't DEAUTH + * us properly. So we handle that, but allow it only once. + */ + printkl(KERN_INFO PFX "We were not authenticated during association, retrying...\n"); + network->authenticated = 0; + /* we don't want to do this more than once ... */ + network->auth_desynced_once = 1; + schedule_work(&mac->associnfo.work); + break; + } + default: + dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); + mac->associnfo.associating = 0; + mac->associnfo.bssvalid = 0; + mac->associated = 0; + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); + } + + spin_unlock_irqrestore(&mac->lock, flags); + return 0; +} + +int +ieee80211softmac_handle_disassoc(struct net_device * dev, + struct ieee80211_disassoc *disassoc) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) + return 0; + if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) + return 0; + dprintk(KERN_INFO PFX "got disassoc frame\n"); + netif_carrier_off(dev); + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.bssvalid = 0; + mac->associated = 0; + schedule_work(&mac->associnfo.work); + spin_unlock_irqrestore(&mac->lock, flags); + + return 0; +} + +int +ieee80211softmac_handle_reassoc_req(struct net_device * dev, + struct ieee80211_reassoc_request * resp) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + struct ieee80211softmac_network *network; + + network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); + if (!network) { + dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); + return 0; + } + ieee80211softmac_assoc(mac, network); + return 0; +} diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c new file mode 100644 index 000000000000..9a0eac6c61eb --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -0,0 +1,364 @@ +/* + * This file contains the softmac's authentication logic. + * + * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#include "ieee80211softmac_priv.h" + +static void ieee80211softmac_auth_queue(void *data); + +/* Queues an auth request to the desired AP */ +int +ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net) +{ + struct ieee80211softmac_auth_queue_item *auth; + unsigned long flags; + + if (net->authenticating) + return 0; + + /* Add the network if it's not already added */ + ieee80211softmac_add_network(mac, net); + + dprintk(KERN_NOTICE PFX "Queueing Authentication Request to "MAC_FMT"\n", MAC_ARG(net->bssid)); + /* Queue the auth request */ + auth = (struct ieee80211softmac_auth_queue_item *) + kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL); + if(auth == NULL) + return -ENOMEM; + + auth->net = net; + auth->mac = mac; + auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT; + auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST; + INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth); + + /* Lock (for list) */ + spin_lock_irqsave(&mac->lock, flags); + + /* add to list */ + list_add_tail(&auth->list, &mac->auth_queue); + schedule_work(&auth->work); + spin_unlock_irqrestore(&mac->lock, flags); + + return 0; +} + + +/* Sends an auth request to the desired AP and handles timeouts */ +static void +ieee80211softmac_auth_queue(void *data) +{ + struct ieee80211softmac_device *mac; + struct ieee80211softmac_auth_queue_item *auth; + struct ieee80211softmac_network *net; + unsigned long flags; + + auth = (struct ieee80211softmac_auth_queue_item *)data; + net = auth->net; + mac = auth->mac; + + if(auth->retry > 0) { + /* Switch to correct channel for this network */ + mac->set_channel(mac->dev, net->channel); + + /* Lock and set flags */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticated = 0; + net->authenticating = 1; + /* add a timeout call so we eventually give up waiting for an auth reply */ + schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); + auth->retry--; + spin_unlock_irqrestore(&mac->lock, flags); + if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state)) + dprintk(KERN_NOTICE PFX "Sending Authentication Request to "MAC_FMT" failed (this shouldn't happen, wait for the timeout).\n", MAC_ARG(net->bssid)); + else + dprintk(KERN_NOTICE PFX "Sent Authentication Request to "MAC_FMT".\n", MAC_ARG(net->bssid)); + return; + } + + printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid)); + /* Remove this item from the queue */ + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net); + cancel_delayed_work(&auth->work); /* just to make sure... */ + list_del(&auth->list); + spin_unlock_irqrestore(&mac->lock, flags); + /* Free it */ + kfree(auth); +} + +/* Handle the auth response from the AP + * This should be registered with ieee80211 as handle_auth + */ +int +ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) +{ + + struct list_head *list_ptr; + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + struct ieee80211softmac_auth_queue_item *aq = NULL; + struct ieee80211softmac_network *net = NULL; + unsigned long flags; + u8 * data; + + /* Find correct auth queue item */ + spin_lock_irqsave(&mac->lock, flags); + list_for_each(list_ptr, &mac->auth_queue) { + aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list); + net = aq->net; + if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN)) + break; + else + aq = NULL; + } + spin_unlock_irqrestore(&mac->lock, flags); + + /* Make sure that we've got an auth queue item for this request */ + if(aq == NULL) + { + printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2)); + /* Error #? */ + return -1; + } + + /* Check for out of order authentication */ + if(!net->authenticating) + { + printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2)); + return -1; + } + + /* Parse the auth packet */ + switch(auth->algorithm) { + case WLAN_AUTH_OPEN: + /* Check the status code of the response */ + + switch(auth->status) { + case WLAN_STATUS_SUCCESS: + /* Update the status to Authenticated */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticating = 0; + net->authenticated = 1; + spin_unlock_irqrestore(&mac->lock, flags); + + /* Send event */ + printkl(KERN_NOTICE PFX "Open Authentication completed with "MAC_FMT"\n", MAC_ARG(net->bssid)); + ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net); + break; + default: + /* Lock and reset flags */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticated = 0; + net->authenticating = 0; + spin_unlock_irqrestore(&mac->lock, flags); + + printkl(KERN_NOTICE PFX "Open Authentication with "MAC_FMT" failed, error code: %i\n", + MAC_ARG(net->bssid), le16_to_cpup(&auth->status)); + /* Count the error? */ + break; + } + goto free_aq; + break; + case WLAN_AUTH_SHARED_KEY: + /* Figure out where we are in the process */ + switch(auth->transaction) { + case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE: + /* Check to make sure we have a challenge IE */ + data = (u8 *)auth->info_element; + if(*data++ != MFIE_TYPE_CHALLENGE){ + printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n"); + break; + } + /* Save the challenge */ + spin_lock_irqsave(&mac->lock, flags); + net->challenge_len = *data++; + if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) + net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; + if(net->challenge != NULL) + kfree(net->challenge); + net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC); + memcpy(net->challenge, data, net->challenge_len); + aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; + spin_unlock_irqrestore(&mac->lock, flags); + + /* Switch to correct channel for this network */ + mac->set_channel(mac->dev, net->channel); + + /* Send our response (How to encrypt?) */ + ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); + break; + case IEEE80211SOFTMAC_AUTH_SHARED_PASS: + /* Check the status code of the response */ + switch(auth->status) { + case WLAN_STATUS_SUCCESS: + /* Update the status to Authenticated */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticating = 0; + net->authenticated = 1; + spin_unlock_irqrestore(&mac->lock, flags); + printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", + MAC_ARG(net->bssid)); + break; + default: + printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", + MAC_ARG(net->bssid), le16_to_cpup(&auth->status)); + /* Lock and reset flags */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticating = 0; + net->authenticated = 0; + spin_unlock_irqrestore(&mac->lock, flags); + /* Count the error? */ + break; + } + goto free_aq; + break; + default: + printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction); + break; + } + goto free_aq; + break; + default: + /* ERROR */ + goto free_aq; + break; + } + return 0; +free_aq: + /* Cancel the timeout */ + spin_lock_irqsave(&mac->lock, flags); + cancel_delayed_work(&aq->work); + /* Remove this item from the queue */ + list_del(&aq->list); + spin_unlock_irqrestore(&mac->lock, flags); + + /* Free it */ + kfree(aq); + return 0; +} + +/* + * Handle deauthorization + */ +static void +ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net) +{ + struct ieee80211softmac_auth_queue_item *aq = NULL; + struct list_head *list_ptr; + unsigned long flags; + + /* Lock and reset status flags */ + spin_lock_irqsave(&mac->lock, flags); + net->authenticating = 0; + net->authenticated = 0; + + /* Find correct auth queue item, if it exists */ + list_for_each(list_ptr, &mac->auth_queue) { + aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list); + if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN)) + break; + else + aq = NULL; + } + + /* Cancel pending work */ + if(aq != NULL) + /* Not entirely safe? What about running work? */ + cancel_delayed_work(&aq->work); + + /* Free our network ref */ + ieee80211softmac_del_network_locked(mac, net); + if(net->challenge != NULL) + kfree(net->challenge); + kfree(net); + + /* can't transmit data right now... */ + netif_carrier_off(mac->dev); + /* let's try to re-associate */ + schedule_work(&mac->associnfo.work); + spin_unlock_irqrestore(&mac->lock, flags); +} + +/* + * Sends a deauth request to the desired AP + */ +int +ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net, int reason) +{ + int ret; + + /* Make sure the network is authenticated */ + if (!net->authenticated) + { + printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); + /* Error okay? */ + return -EPERM; + } + + /* Send the de-auth packet */ + if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason))) + return ret; + + ieee80211softmac_deauth_from_net(mac, net); + return 0; +} + +/* + * This should be registered with ieee80211 as handle_deauth + */ +int +ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth) +{ + + struct ieee80211softmac_network *net = NULL; + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + + if (!deauth) { + dprintk("deauth without deauth packet. eek!\n"); + return 0; + } + + net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2); + + if (net == NULL) { + printkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n", + MAC_ARG(deauth->header.addr2)); + return 0; + } + + /* Make sure the network is authenticated */ + if(!net->authenticated) + { + printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); + /* Error okay? */ + return -EPERM; + } + + ieee80211softmac_deauth_from_net(mac, net); + return 0; +} diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c new file mode 100644 index 000000000000..0a52bbda1e4c --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -0,0 +1,159 @@ +/* + * Event system + * Also see comments in public header file and longer explanation below. + * + * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#include "ieee80211softmac_priv.h" + +/* + * Each event has associated to it + * - an event type (see constants in public header) + * - an event context (see below) + * - the function to be called + * - a context (extra parameter to call the function with) + * - and the softmac struct + * + * The event context is private and can only be used from + * within this module. Its meaning varies with the event + * type: + * SCAN_FINISHED: no special meaning + * ASSOCIATED, + * ASSOCIATE_FAILED, + * ASSOCIATE_TIMEOUT, + * AUTHENTICATED, + * AUTH_FAILED, + * AUTH_TIMEOUT: a pointer to the network struct + * ... + * Code within this module can use the event context to be only + * called when the event is true for that specific context + * as per above table. + * If the event context is NULL, then the notification is always called, + * regardless of the event context. The event context is not passed to + * the callback, it is assumed that the context suffices. + * + * You can also use the event context only by setting the event type + * to -1 (private use only), in which case you'll be notified + * whenever the event context matches. + */ + +static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = { + "scan finished", + "associated", + "associating failed", + "associating timed out", + "authenticated", + "authenticating failed", + "authenticating timed out", + "associating failed because no suitable network was found", +}; + + +static void +ieee80211softmac_notify_callback(void *d) +{ + struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d; + kfree(d); + + event.fun(event.mac->dev, event.context); +} + +int +ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac, + int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask) +{ + struct ieee80211softmac_event *eventptr; + unsigned long flags; + + if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST) + return -ENOSYS; + + if (!fun) + return -EINVAL; + + eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask); + if (!eventptr) + return -ENOMEM; + + eventptr->event_type = event; + INIT_WORK(&eventptr->work, ieee80211softmac_notify_callback, eventptr); + eventptr->fun = fun; + eventptr->context = context; + eventptr->mac = mac; + eventptr->event_context = event_context; + + spin_lock_irqsave(&mac->lock, flags); + list_add(&eventptr->list, &mac->events); + spin_unlock_irqrestore(&mac->lock, flags); + + return 0; +} + +int +ieee80211softmac_notify_gfp(struct net_device *dev, + int event, notify_function_ptr fun, void *context, gfp_t gfp_mask) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + + if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST) + return -ENOSYS; + + return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp); + +/* private -- calling all callbacks that were specified */ +void +ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) +{ + struct ieee80211softmac_event *eventptr, *tmp; + union iwreq_data wrqu; + char *msg; + + if (event >= 0) { + msg = event_descriptions[event]; + wrqu.data.length = strlen(msg); + wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg); + } + + if (!list_empty(&mac->events)) + list_for_each_entry_safe(eventptr, tmp, &mac->events, list) { + if ((eventptr->event_type == event || eventptr->event_type == -1) + && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) { + list_del(&eventptr->list); + schedule_work(&eventptr->work); + } + } +} + +void +ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_call_events_locked(mac, event, event_ctx); + + spin_unlock_irqrestore(&mac->lock, flags); +} diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c new file mode 100644 index 000000000000..febc51dbb412 --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_io.c @@ -0,0 +1,474 @@ +/* + * Some parts based on code from net80211 + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF 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. + * + */ + +#include "ieee80211softmac_priv.h" + +/* Helper functions for inserting data into the frames */ + +/* + * Adds an ESSID element to the frame + * + */ +static u8 * +ieee80211softmac_add_essid(u8 *dst, struct ieee80211softmac_essid *essid) +{ + if (essid) { + *dst++ = MFIE_TYPE_SSID; + *dst++ = essid->len; + memcpy(dst, essid->data, essid->len); + return dst+essid->len; + } else { + *dst++ = MFIE_TYPE_SSID; + *dst++ = 0; + return dst; + } +} + +/* Adds Supported Rates and if required Extended Rates Information Element + * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */ +static u8 * +ieee80211softmac_frame_add_rates(u8 *dst, const struct ieee80211softmac_ratesinfo *r) +{ + int cck_len, ofdm_len; + *dst++ = MFIE_TYPE_RATES; + + for(cck_len=0; ieee80211_is_cck_rate(r->rates[cck_len]) && (cck_len < r->count);cck_len++); + + if(cck_len > IEEE80211SOFTMAC_MAX_RATES_LEN) + cck_len = IEEE80211SOFTMAC_MAX_RATES_LEN; + *dst++ = cck_len; + memcpy(dst, r->rates, cck_len); + dst += cck_len; + + if(cck_len < r->count){ + for (ofdm_len=0; ieee80211_is_ofdm_rate(r->rates[ofdm_len + cck_len]) && (ofdm_len + cck_len < r->count); ofdm_len++); + if (ofdm_len > 0) { + if (ofdm_len > IEEE80211SOFTMAC_MAX_EX_RATES_LEN) + ofdm_len = IEEE80211SOFTMAC_MAX_EX_RATES_LEN; + *dst++ = MFIE_TYPE_RATES_EX; + *dst++ = ofdm_len; + memcpy(dst, r->rates + cck_len, ofdm_len); + dst += ofdm_len; + } + } + return dst; +} + +/* Allocate a management frame */ +static u8 * +ieee80211softmac_alloc_mgt(u32 size) +{ + u8 * data; + + /* Add the header and FCS to the size */ + size = size + IEEE80211_3ADDR_LEN; + if(size > IEEE80211_DATA_LEN) + return NULL; + /* Allocate the frame */ + data = kmalloc(size, GFP_ATOMIC); + memset(data, 0, size); + return data; +} + +/* + * Add a 2 Address Header + */ +static void +ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac, + struct ieee80211_hdr_2addr *header, u32 type, u8 *dest) +{ + /* Fill in the frame control flags */ + header->frame_ctl = cpu_to_le16(type); + /* Control packets always have WEP turned off */ + if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL) + header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0; + + /* Fill in the duration */ + header->duration_id = 0; + /* FIXME: How do I find this? + * calculate. But most drivers just fill in 0 (except if it's a station id of course) */ + + /* Fill in the Destination Address */ + if(dest == NULL) + memset(header->addr1, 0xFF, ETH_ALEN); + else + memcpy(header->addr1, dest, ETH_ALEN); + /* Fill in the Source Address */ + memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN); + +} + + +/* Add a 3 Address Header */ +static void +ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac, + struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid) +{ + /* This is common with 2addr, so use that instead */ + ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest); + + /* Fill in the BSS ID */ + if(bssid == NULL) + memset(header->addr3, 0xFF, ETH_ALEN); + else + memcpy(header->addr3, bssid, ETH_ALEN); + + /* Fill in the sequence # */ + /* FIXME: I need to add this to the softmac struct + * shouldn't the sequence number be in ieee80211? */ +} + + +/***************************************************************************** + * Create Management packets + *****************************************************************************/ + +/* Creates an association request packet */ +static u32 +ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) +{ + u8 *data; + (*pkt) = (struct ieee80211_assoc_request *)ieee80211softmac_alloc_mgt( + 2 + /* Capability Info */ + 2 + /* Listen Interval */ + /* SSID IE */ + 1 + 1 + IW_ESSID_MAX_SIZE + + /* Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + + /* Extended Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN + + /* WPA IE if present */ + mac->wpa.IElen + /* Other IE's? Optional? + * Yeah, probably need an extra IE parameter -- lots of vendors like to + * fill in their own IEs */ + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); + + /* Fill in capability Info */ + (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ? + cpu_to_le16(WLAN_CAPABILITY_ESS) : + cpu_to_le16(WLAN_CAPABILITY_IBSS); + /* Need to add this + (*pkt)->capability |= mac->ieee->short_slot ? + cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; + */ + (*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; + /* Fill in Listen Interval (?) */ + (*pkt)->listen_interval = cpu_to_le16(10); + + data = (u8 *)(*pkt)->info_element; + /* Add SSID */ + data = ieee80211softmac_add_essid(data, &net->essid); + /* Add Rates */ + data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); + /* Add WPA IE */ + if (mac->wpa.IElen && mac->wpa.IE) { + memcpy(data, mac->wpa.IE, mac->wpa.IElen); + data += mac->wpa.IElen; + } + /* Return the number of used bytes */ + return (data - (u8*)(*pkt)); +} + +/* Create a reassociation request packet */ +static u32 +ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) +{ + u8 *data; + (*pkt) = (struct ieee80211_reassoc_request *)ieee80211softmac_alloc_mgt( + 2 + /* Capability Info */ + 2 + /* Listen Interval */ + ETH_ALEN + /* AP MAC */ + /* SSID IE */ + 1 + 1 + IW_ESSID_MAX_SIZE + + /* Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + + /* Extended Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN + /* Other IE's? */ + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid); + + /* Fill in capability Info */ + (*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ? + cpu_to_le16(WLAN_CAPABILITY_ESS) : + cpu_to_le16(WLAN_CAPABILITY_IBSS); + /* + (*pkt)->capability |= mac->ieee->short_slot ? + cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; + */ + (*pkt)->capability |= mac->ieee->sec.level ? + cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; + + /* Fill in Listen Interval (?) */ + (*pkt)->listen_interval = cpu_to_le16(10); + /* Fill in the current AP MAC */ + memcpy((*pkt)->current_ap, mac->ieee->bssid, ETH_ALEN); + + data = (u8 *)(*pkt)->info_element; + /* Add SSID */ + data = ieee80211softmac_add_essid(data, &net->essid); + /* Add Rates */ + data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); + /* Return packet size */ + return (data - (u8 *)(*pkt)); +} + +/* Create an authentication packet */ +static u32 +ieee80211softmac_auth(struct ieee80211_auth **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, + u16 transaction, u16 status) +{ + u8 *data; + /* Allocate Packet */ + (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt( + 2 + /* Auth Algorithm */ + 2 + /* Auth Transaction Seq */ + 2 + /* Status Code */ + /* Challenge Text IE */ + mac->ieee->open_wep ? 0 : + 1 + 1 + WLAN_AUTH_CHALLENGE_LEN + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid); + + /* Algorithm */ + (*pkt)->algorithm = mac->ieee->open_wep ? + cpu_to_le16(WLAN_AUTH_OPEN) : + cpu_to_le16(WLAN_AUTH_SHARED_KEY); + /* Transaction */ + (*pkt)->transaction = cpu_to_le16(transaction); + /* Status */ + (*pkt)->status = cpu_to_le16(status); + + data = (u8 *)(*pkt)->info_element; + /* Challenge Text */ + if(!mac->ieee->open_wep){ + *data = MFIE_TYPE_CHALLENGE; + data++; + + /* Copy the challenge in */ + // *data = challenge length + // data += sizeof(u16); + // memcpy(data, challenge, challenge length); + // data += challenge length; + + /* Add the full size to the packet length */ + } + + /* Return the packet size */ + return (data - (u8 *)(*pkt)); +} + +/* Create a disassocation or deauthentication packet */ +static u32 +ieee80211softmac_disassoc_deauth(struct ieee80211_disassoc **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, + u16 type, u16 reason) +{ + /* Allocate Packet */ + (*pkt) = (struct ieee80211_disassoc *)ieee80211softmac_alloc_mgt(2); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), type, net->bssid, net->bssid); + /* Reason */ + (*pkt)->reason = cpu_to_le16(reason); + /* Return the packet size */ + return (2 + IEEE80211_3ADDR_LEN); +} + +/* Create a probe request packet */ +static u32 +ieee80211softmac_probe_req(struct ieee80211_probe_request **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_essid *essid) +{ + u8 *data; + /* Allocate Packet */ + (*pkt) = (struct ieee80211_probe_request *)ieee80211softmac_alloc_mgt( + /* SSID of requested network */ + 1 + 1 + IW_ESSID_MAX_SIZE + + /* Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + + /* Extended Rates IE */ + 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_REQ, NULL, NULL); + + data = (u8 *)(*pkt)->info_element; + /* Add ESSID (can be NULL) */ + data = ieee80211softmac_add_essid(data, essid); + /* Add Rates */ + data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); + /* Return packet size */ + return (data - (u8 *)(*pkt)); +} + +/* Create a probe response packet */ +/* FIXME: Not complete */ +static u32 +ieee80211softmac_probe_resp(struct ieee80211_probe_response **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) +{ + u8 *data; + /* Allocate Packet */ + (*pkt) = (struct ieee80211_probe_response *)ieee80211softmac_alloc_mgt( + 8 + /* Timestamp */ + 2 + /* Beacon Interval */ + 2 + /* Capability Info */ + /* SSID IE */ + 1 + 1 + IW_ESSID_MAX_SIZE + + 7 + /* FH Parameter Set */ + 2 + /* DS Parameter Set */ + 8 + /* CF Parameter Set */ + 4 /* IBSS Parameter Set */ + ); + if (unlikely((*pkt) == NULL)) + return 0; + ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, net->bssid); + data = (u8 *)(*pkt)->info_element; + + /* Return the packet size */ + return (data - (u8 *)(*pkt)); +} + + +/* Sends a manangement packet + * FIXME: document the use of the arg parameter + * for _AUTH: (transaction #) | (status << 16) + */ +int +ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, + void *ptrarg, u32 type, u32 arg) +{ + void *pkt = NULL; + u32 pkt_size = 0; + + switch(type) { + case IEEE80211_STYPE_ASSOC_REQ: + pkt_size = ieee80211softmac_assoc_req((struct ieee80211_assoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); + break; + case IEEE80211_STYPE_REASSOC_REQ: + pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); + break; + case IEEE80211_STYPE_AUTH: + pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16)); + break; + case IEEE80211_STYPE_DISASSOC: + case IEEE80211_STYPE_DEAUTH: + pkt_size = ieee80211softmac_disassoc_deauth((struct ieee80211_disassoc **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, type, (u16)(arg & 0xFFFF)); + break; + case IEEE80211_STYPE_PROBE_REQ: + pkt_size = ieee80211softmac_probe_req((struct ieee80211_probe_request **)(&pkt), mac, (struct ieee80211softmac_essid *)ptrarg); + break; + case IEEE80211_STYPE_PROBE_RESP: + pkt_size = ieee80211softmac_probe_resp((struct ieee80211_probe_response **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); + break; + default: + printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type); + return -EINVAL; + }; + + if(pkt_size == 0 || pkt == NULL) { + printkl(KERN_DEBUG PFX "Error, packet is nonexistant or 0 length\n"); + return -ENOMEM; + } + + /* Send the packet to the ieee80211 layer for tx */ + /* we defined softmac->mgmt_xmit for this. Should we keep it + * as it is (that means we'd need to wrap this into a txb), + * modify the prototype (so it matches this function), + * or get rid of it alltogether? + * Does this work for you now? + */ + ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size); + + kfree(pkt); + return 0; +} + + +/* Create an rts/cts frame */ +static u32 +ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt, + struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, + u32 type) +{ + /* Allocate Packet */ + (*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC); + memset(*pkt, 0, IEEE80211_2ADDR_LEN); + if((*pkt) == NULL) + return 0; + ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid); + return IEEE80211_2ADDR_LEN; +} + + +/* Sends a control packet */ +static int +ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net, u32 type, u32 arg) +{ + void *pkt = NULL; + u32 pkt_size = 0; + + switch(type) { + case IEEE80211_STYPE_RTS: + case IEEE80211_STYPE_CTS: + pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type); + break; + default: + printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type); + return -EINVAL; + } + + if(pkt_size == 0) + return -ENOMEM; + + /* Send the packet to the ieee80211 layer for tx */ + ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size); + + kfree(pkt); + return 0; +} diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c new file mode 100644 index 000000000000..6f99f781bff8 --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -0,0 +1,457 @@ +/* + * Contains some basic softmac functions along with module registration code etc. + * + * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#include "ieee80211softmac_priv.h" +#include <linux/sort.h> + +struct net_device *alloc_ieee80211softmac(int sizeof_priv) +{ + struct ieee80211softmac_device *softmac; + struct net_device *dev; + + dev = alloc_ieee80211(sizeof(struct ieee80211softmac_device) + sizeof_priv); + softmac = ieee80211_priv(dev); + softmac->dev = dev; + softmac->ieee = netdev_priv(dev); + spin_lock_init(&softmac->lock); + + softmac->ieee->handle_auth = ieee80211softmac_auth_resp; + softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp; + softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response; + softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req; + softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; + softmac->scaninfo = NULL; + + /* TODO: initialise all the other callbacks in the ieee struct + * (once they're written) + */ + + INIT_LIST_HEAD(&softmac->auth_queue); + INIT_LIST_HEAD(&softmac->network_list); + INIT_LIST_HEAD(&softmac->events); + + INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac); + INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac); + softmac->start_scan = ieee80211softmac_start_scan_implementation; + softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation; + softmac->stop_scan = ieee80211softmac_stop_scan_implementation; + + //TODO: The mcast rate has to be assigned dynamically somewhere (in scanning, association. Not sure...) + // It has to be set to the highest rate all stations in the current network can handle. + softmac->txrates.mcast_rate = IEEE80211_CCK_RATE_1MB; + softmac->txrates.mcast_fallback = IEEE80211_CCK_RATE_1MB; + /* This is reassigned in ieee80211softmac_start to sane values. */ + softmac->txrates.default_rate = IEEE80211_CCK_RATE_1MB; + softmac->txrates.default_fallback = IEEE80211_CCK_RATE_1MB; + + /* to start with, we can't send anything ... */ + netif_carrier_off(dev); + + return dev; +} +EXPORT_SYMBOL_GPL(alloc_ieee80211softmac); + +/* Clears the pending work queue items, stops all scans, etc. */ +void +ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + struct ieee80211softmac_event *eventptr, *eventtmp; + struct ieee80211softmac_auth_queue_item *authptr, *authtmp; + struct ieee80211softmac_network *netptr, *nettmp; + + ieee80211softmac_stop_scan(sm); + ieee80211softmac_wait_for_scan(sm); + + spin_lock_irqsave(&sm->lock, flags); + /* Free all pending assoc work items */ + cancel_delayed_work(&sm->associnfo.work); + + /* Free all pending scan work items */ + if(sm->scaninfo != NULL) + cancel_delayed_work(&sm->scaninfo->softmac_scan); + + /* Free all pending auth work items */ + list_for_each_entry(authptr, &sm->auth_queue, list) + cancel_delayed_work(&authptr->work); + + /* delete all pending event calls and work items */ + list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) + cancel_delayed_work(&eventptr->work); + + spin_unlock_irqrestore(&sm->lock, flags); + flush_scheduled_work(); + + /* now we should be save and no longer need locking... */ + spin_lock_irqsave(&sm->lock, flags); + /* Free all pending auth work items */ + list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) { + list_del(&authptr->list); + kfree(authptr); + } + + /* delete all pending event calls and work items */ + list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) { + list_del(&eventptr->list); + kfree(eventptr); + } + + /* Free all networks */ + list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) { + ieee80211softmac_del_network_locked(sm, netptr); + if(netptr->challenge != NULL) + kfree(netptr->challenge); + kfree(netptr); + } + + spin_unlock_irqrestore(&sm->lock, flags); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work); + +void free_ieee80211softmac(struct net_device *dev) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(dev); + ieee80211softmac_clear_pending_work(sm); + kfree(sm->scaninfo); + kfree(sm->wpa.IE); + free_ieee80211(dev); +} +EXPORT_SYMBOL_GPL(free_ieee80211softmac); + +static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac) +{ + struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; + /* I took out the sorting check, we're seperating by modulation now. */ + if (ri->count) + return; + /* otherwise assume we hav'em all! */ + if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) { + ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB; + ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB; + ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB; + ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB; + } + if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) { + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB; + ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB; + } +} + +void ieee80211softmac_start(struct net_device *dev) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + struct ieee80211_device *ieee = mac->ieee; + u32 change = 0; + struct ieee80211softmac_txrates oldrates; + + ieee80211softmac_start_check_rates(mac); + + /* TODO: We need some kind of state machine to lower the default rates + * if we loose too many packets. + */ + /* Change the default txrate to the highest possible value. + * The txrate machine will lower it, if it is too high. + */ + if (mac->txrates_change) + oldrates = mac->txrates; + if (ieee->modulation & IEEE80211_OFDM_MODULATION) { + mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; + mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; + } else if (ieee->modulation & IEEE80211_CCK_MODULATION) { + mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; + mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; + } else + assert(0); + if (mac->txrates_change) + mac->txrates_change(dev, change, &oldrates); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_start); + +void ieee80211softmac_stop(struct net_device *dev) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + + ieee80211softmac_clear_pending_work(mac); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_stop); + +void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + memcpy(mac->ratesinfo.rates, rates, count); + mac->ratesinfo.count = count; + spin_unlock_irqrestore(&mac->lock, flags); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates); + +static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate) +{ + int i; + struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; + + for (i=0; i<ri->count-1; i++) { + if (ri->rates[i] == rate) + return ri->rates[i+1]; + } + /* I guess we can't go any higher... */ + return ri->rates[ri->count]; +} + +u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta) +{ + int i; + struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; + + for (i=delta; i<ri->count; i++) { + if (ri->rates[i] == rate) + return ri->rates[i-delta]; + } + /* I guess we can't go any lower... */ + return ri->rates[0]; +} + +static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac, + int amount) +{ + struct ieee80211softmac_txrates oldrates; + u8 default_rate = mac->txrates.default_rate; + u8 default_fallback = mac->txrates.default_fallback; + u32 changes = 0; + + //TODO: This is highly experimental code. + // Maybe the dynamic rate selection does not work + // and it has to be removed again. + +printk("badness %d\n", mac->txrate_badness); + mac->txrate_badness += amount; + if (mac->txrate_badness <= -1000) { + /* Very small badness. Try a faster bitrate. */ + if (mac->txrates_change) + memcpy(&oldrates, &mac->txrates, sizeof(oldrates)); + default_rate = raise_rate(mac, default_rate); + changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; + default_fallback = get_fallback_rate(mac, default_rate); + changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; + mac->txrate_badness = 0; +printk("Bitrate raised to %u\n", default_rate); + } else if (mac->txrate_badness >= 10000) { + /* Very high badness. Try a slower bitrate. */ + if (mac->txrates_change) + memcpy(&oldrates, &mac->txrates, sizeof(oldrates)); + default_rate = lower_rate(mac, default_rate); + changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; + default_fallback = get_fallback_rate(mac, default_rate); + changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; + mac->txrate_badness = 0; +printk("Bitrate lowered to %u\n", default_rate); + } + + mac->txrates.default_rate = default_rate; + mac->txrates.default_fallback = default_fallback; + + if (changes && mac->txrates_change) + mac->txrates_change(mac->dev, changes, &oldrates); +} + +void ieee80211softmac_fragment_lost(struct net_device *dev, + u16 wl_seq) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_add_txrates_badness(mac, 1000); + //TODO + + spin_unlock_irqrestore(&mac->lock, flags); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost); + +static int rate_cmp(const void *a_, const void *b_) { + u8 *a, *b; + a = (u8*)a_; + b = (u8*)b_; + return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK)); +} + +/* Allocate a softmac network struct and fill it from a network */ +struct ieee80211softmac_network * +ieee80211softmac_create_network(struct ieee80211softmac_device *mac, + struct ieee80211_network *net) +{ + struct ieee80211softmac_network *softnet; + softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC); + if(softnet == NULL) + return NULL; + memcpy(softnet->bssid, net->bssid, ETH_ALEN); + softnet->channel = net->channel; + softnet->essid.len = net->ssid_len; + memcpy(softnet->essid.data, net->ssid, softnet->essid.len); + + /* copy rates over */ + softnet->supported_rates.count = net->rates_len; + memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len); + memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len); + softnet->supported_rates.count += net->rates_ex_len; + sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL); + + softnet->capabilities = net->capability; + return softnet; +} + + +/* Add a network to the list, while locked */ +void +ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *add_net) +{ + struct list_head *list_ptr; + struct ieee80211softmac_network *softmac_net = NULL; + + list_for_each(list_ptr, &mac->network_list) { + softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list); + if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN)) + break; + else + softmac_net = NULL; + } + if(softmac_net == NULL) + list_add(&(add_net->list), &mac->network_list); +} + +/* Add a network to the list, with locking */ +void +ieee80211softmac_add_network(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *add_net) +{ + unsigned long flags; + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_add_network_locked(mac, add_net); + spin_unlock_irqrestore(&mac->lock, flags); +} + + +/* Delete a network from the list, while locked*/ +void +ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *del_net) +{ + list_del(&(del_net->list)); +} + +/* Delete a network from the list with locking */ +void +ieee80211softmac_del_network(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *del_net) +{ + unsigned long flags; + spin_lock_irqsave(&mac->lock, flags); + ieee80211softmac_del_network_locked(mac, del_net); + spin_unlock_irqrestore(&mac->lock, flags); +} + +/* Get a network from the list by MAC while locked */ +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac, + u8 *bssid) +{ + struct list_head *list_ptr; + struct ieee80211softmac_network *softmac_net = NULL; + list_for_each(list_ptr, &mac->network_list) { + softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list); + if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN)) + break; + else + softmac_net = NULL; + } + return softmac_net; +} + +/* Get a network from the list by BSSID with locking */ +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac, + u8 *bssid) +{ + unsigned long flags; + struct ieee80211softmac_network *softmac_net; + + spin_lock_irqsave(&mac->lock, flags); + softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid); + spin_unlock_irqrestore(&mac->lock, flags); + return softmac_net; +} + +/* Get a network from the list by ESSID while locked */ +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_essid *essid) +{ + struct list_head *list_ptr; + struct ieee80211softmac_network *softmac_net = NULL; + + list_for_each(list_ptr, &mac->network_list) { + softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list); + if (softmac_net->essid.len == essid->len && + !memcmp(softmac_net->essid.data, essid->data, essid->len)) + return softmac_net; + } + return NULL; +} + +/* Get a network from the list by ESSID with locking */ +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac, + struct ieee80211softmac_essid *essid) +{ + unsigned long flags; + struct ieee80211softmac_network *softmac_net = NULL; + + spin_lock_irqsave(&mac->lock, flags); + softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid); + spin_unlock_irqrestore(&mac->lock, flags); + return softmac_net; +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Johannes Berg"); +MODULE_AUTHOR("Joseph Jezak"); +MODULE_AUTHOR("Larry Finger"); +MODULE_AUTHOR("Danny van Dyk"); +MODULE_AUTHOR("Michael Buesch"); +MODULE_DESCRIPTION("802.11 software MAC"); diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h new file mode 100644 index 000000000000..9ba7dbd161eb --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_priv.h @@ -0,0 +1,230 @@ +/* + * Internal softmac API definitions. + * + * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#ifndef IEEE80211SOFTMAC_PRIV_H_ +#define IEEE80211SOFTMAC_PRIV_H_ + +#include <net/ieee80211softmac.h> +#include <net/ieee80211softmac_wx.h> +#include <linux/kernel.h> +#include <linux/stringify.h> + + +#define PFX "SoftMAC: " + +#ifdef assert +# undef assert +#endif +#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG +#define assert(expr) \ + do { \ + if (unlikely(!(expr))) { \ + printkl(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", #expr, \ + __FILE__, __LINE__, __FUNCTION__); \ + } \ + } while (0) +#else +#define assert(expr) do {} while (0) +#endif + +/* rate limited printk(). */ +#ifdef printkl +# undef printkl +#endif +#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0) +/* rate limited printk() for debugging */ +#ifdef dprintkl +# undef dprintkl +#endif +#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG +# define dprintkl printkl +#else +# define dprintkl(f, x...) do { /* nothing */ } while (0) +#endif + +/* debugging printk() */ +#ifdef dprintk +# undef dprintk +#endif +#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG +# define dprintk(f, x...) do { printk(f ,##x); } while (0) +#else +# define dprintk(f, x...) do { /* nothing */ } while (0) +#endif + +/* private definitions and prototypes */ + +/*** prototypes from _scan.c */ +void ieee80211softmac_scan(void *sm); +/* for internal use if scanning is needed */ +int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac); +void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac); +void ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *mac); + +/* for use by _module.c to assign to the callbacks */ +int ieee80211softmac_start_scan_implementation(struct net_device *dev); +void ieee80211softmac_stop_scan_implementation(struct net_device *dev); +void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev); + +/*** Network prototypes from _module.c */ +struct ieee80211softmac_network * ieee80211softmac_create_network( + struct ieee80211softmac_device *mac, struct ieee80211_network *net); +void ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net); +void ieee80211softmac_add_network(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net); +void ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net); +void ieee80211softmac_del_network(struct ieee80211softmac_device *mac, + struct ieee80211softmac_network *net); +struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid_locked( + struct ieee80211softmac_device *mac, u8 *ea); +struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid( + struct ieee80211softmac_device *mac, u8 *ea); +struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid_locked( + struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len); +struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid( + struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len); +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac, + struct ieee80211softmac_essid *essid); +struct ieee80211softmac_network * +ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac, + struct ieee80211softmac_essid *essid); + +/* Rates related */ +u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta); +static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) { + return ieee80211softmac_lower_rate_delta(mac, rate, 1); +} + +static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate) +{ + return ieee80211softmac_lower_rate_delta(mac, rate, 2); +} + + +/*** prototypes from _io.c */ +int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, + void* ptrarg, u32 type, u32 arg); + +/*** prototypes from _auth.c */ +/* do these have to go into the public header? */ +int ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net); +int ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, int reason); + +/* for use by _module.c to assign to the callbacks */ +int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth); +int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth); + +/*** prototypes from _assoc.c */ +void ieee80211softmac_assoc_work(void *d); +int ieee80211softmac_handle_assoc_response(struct net_device * dev, + struct ieee80211_assoc_response * resp, + struct ieee80211_network * network); +int ieee80211softmac_handle_disassoc(struct net_device * dev, + struct ieee80211_disassoc * disassoc); +int ieee80211softmac_handle_reassoc_req(struct net_device * dev, + struct ieee80211_reassoc_request * reassoc); +void ieee80211softmac_assoc_timeout(void *d); + +/* some helper functions */ +static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm) +{ + return (sm->start_scan == ieee80211softmac_start_scan_implementation) && + (sm->stop_scan == ieee80211softmac_stop_scan_implementation) && + (sm->wait_for_scan == ieee80211softmac_wait_for_scan_implementation); +} + +static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_device *sm) +{ + return ((sm->start_scan != ieee80211softmac_start_scan_implementation) && + (sm->stop_scan != ieee80211softmac_stop_scan_implementation) && + (sm->wait_for_scan != ieee80211softmac_wait_for_scan_implementation) + ) || ieee80211softmac_scan_handlers_check_self(sm); +} + +#define IEEE80211SOFTMAC_PROBE_DELAY HZ/2 +#define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN (17 + IFNAMSIZ) + +struct ieee80211softmac_network { + struct list_head list; /* List */ + /* Network information copied from ieee80211_network */ + u8 bssid[ETH_ALEN]; + u8 channel; + struct ieee80211softmac_essid essid; + + struct ieee80211softmac_ratesinfo supported_rates; + + /* SoftMAC specific */ + u16 authenticating:1, /* Status Flags */ + authenticated:1, + auth_desynced_once:1; + + u16 capabilities; /* Capabilities bitfield */ + u8 challenge_len; /* Auth Challenge length */ + char *challenge; /* Challenge Text */ +}; + +/* structure used to keep track of networks we're auth'ing to */ +struct ieee80211softmac_auth_queue_item { + struct list_head list; /* List head */ + struct ieee80211softmac_network *net; /* Network to auth */ + struct ieee80211softmac_device *mac; /* SoftMAC device */ + u8 retry; /* Retry limit */ + u8 state; /* Auth State */ + struct work_struct work; /* Work queue */ +}; + +/* scanning information */ +struct ieee80211softmac_scaninfo { + u8 current_channel_idx, + number_channels; + struct ieee80211_channel *channels; + u8 started:1, + stop:1; + u8 skip_flags; + struct completion finished; + struct work_struct softmac_scan; +}; + +/* private event struct */ +struct ieee80211softmac_event { + struct list_head list; + int event_type; + void *event_context; + struct work_struct work; + notify_function_ptr fun; + void *context; + struct ieee80211softmac_device *mac; +}; + +void ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_context); +void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_context); +int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac, + int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask); + +#endif /* IEEE80211SOFTMAC_PRIV_H_ */ diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c new file mode 100644 index 000000000000..bb9ab8b45d09 --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -0,0 +1,244 @@ +/* + * Scanning routines. + * + * These are not exported because they're assigned to the function pointers. + * + * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#include <linux/completion.h> +#include "ieee80211softmac_priv.h" + +/* internal, use to trigger scanning if needed. + * Returns -EBUSY if already scanning, + * result of start_scan otherwise */ +int +ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&sm->lock, flags); + if (sm->scanning) + { + spin_unlock_irqrestore(&sm->lock, flags); + return -EINPROGRESS; + } + sm->scanning = 1; + spin_unlock_irqrestore(&sm->lock, flags); + + ret = sm->start_scan(sm->dev); + if (ret) { + spin_lock_irqsave(&sm->lock, flags); + sm->scanning = 0; + spin_unlock_irqrestore(&sm->lock, flags); + } + return ret; +} + +void +ieee80211softmac_stop_scan(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + + spin_lock_irqsave(&sm->lock, flags); + + if (!sm->scanning) { + spin_unlock_irqrestore(&sm->lock, flags); + return; + } + + spin_unlock_irqrestore(&sm->lock, flags); + sm->stop_scan(sm->dev); +} + +void +ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + + spin_lock_irqsave(&sm->lock, flags); + + if (!sm->scanning) { + spin_unlock_irqrestore(&sm->lock, flags); + return; + } + + spin_unlock_irqrestore(&sm->lock, flags); + sm->wait_for_scan(sm->dev); +} + + +/* internal scanning implementation follows */ +void ieee80211softmac_scan(void *d) +{ + int invalid_channel; + u8 current_channel_idx; + struct ieee80211softmac_device *sm = (struct ieee80211softmac_device *)d; + struct ieee80211softmac_scaninfo *si = sm->scaninfo; + unsigned long flags; + + while (!(si->stop) && (si->current_channel_idx < si->number_channels)) { + current_channel_idx = si->current_channel_idx; + si->current_channel_idx++; /* go to the next channel */ + + invalid_channel = (si->skip_flags & si->channels[current_channel_idx].flags); + + if (!invalid_channel) { + sm->set_channel(sm->dev, si->channels[current_channel_idx].channel); + // FIXME make this user configurable (active/passive) + if(ieee80211softmac_send_mgt_frame(sm, NULL, IEEE80211_STYPE_PROBE_REQ, 0)) + printkl(KERN_DEBUG PFX "Sending Probe Request Failed\n"); + + /* also send directed management frame for the network we're looking for */ + // TODO: is this if correct, or should we do this only if scanning from assoc request? + if (sm->associnfo.req_essid.len) + ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0); + schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); + return; + } else { + dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel); + } + } + + spin_lock_irqsave(&sm->lock, flags); + cancel_delayed_work(&si->softmac_scan); + si->started = 0; + spin_unlock_irqrestore(&sm->lock, flags); + + dprintk(PFX "Scanning finished\n"); + ieee80211softmac_scan_finished(sm); + complete_all(&sm->scaninfo->finished); +} + +static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee80211softmac_device *mac) +{ + /* ugh. can we call this without having the spinlock held? */ + struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC); + if (unlikely(!info)) + return NULL; + INIT_WORK(&info->softmac_scan, ieee80211softmac_scan, mac); + init_completion(&info->finished); + return info; +} + +int ieee80211softmac_start_scan_implementation(struct net_device *dev) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(dev); + unsigned long flags; + + if (!(dev->flags & IFF_UP)) + return -ENODEV; + + assert(ieee80211softmac_scan_handlers_check_self(sm)); + if (!ieee80211softmac_scan_handlers_check_self(sm)) + return -EINVAL; + + spin_lock_irqsave(&sm->lock, flags); + /* it looks like we need to hold the lock here + * to make sure we don't allocate two of these... */ + if (unlikely(!sm->scaninfo)) + sm->scaninfo = allocate_scaninfo(sm); + if (unlikely(!sm->scaninfo)) { + spin_unlock_irqrestore(&sm->lock, flags); + return -ENOMEM; + } + + sm->scaninfo->skip_flags = IEEE80211_CH_INVALID; + if (0 /* not scanning in IEEE802.11b */)//TODO + sm->scaninfo->skip_flags |= IEEE80211_CH_B_ONLY; + if (0 /* IEEE802.11a */) {//TODO + sm->scaninfo->channels = sm->ieee->geo.a; + sm->scaninfo->number_channels = sm->ieee->geo.a_channels; + } else { + sm->scaninfo->channels = sm->ieee->geo.bg; + sm->scaninfo->number_channels = sm->ieee->geo.bg_channels; + } + dprintk(PFX "Start scanning with channel: %d\n", sm->scaninfo->channels[0].channel); + dprintk(PFX "Scanning %d channels\n", sm->scaninfo->number_channels); + sm->scaninfo->current_channel_idx = 0; + sm->scaninfo->started = 1; + sm->scaninfo->stop = 0; + INIT_COMPLETION(sm->scaninfo->finished); + schedule_work(&sm->scaninfo->softmac_scan); + spin_unlock_irqrestore(&sm->lock, flags); + return 0; +} + +void ieee80211softmac_stop_scan_implementation(struct net_device *dev) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(dev); + unsigned long flags; + + assert(ieee80211softmac_scan_handlers_check_self(sm)); + if (!ieee80211softmac_scan_handlers_check_self(sm)) + return; + + spin_lock_irqsave(&sm->lock, flags); + assert(sm->scaninfo != NULL); + if (sm->scaninfo) { + if (sm->scaninfo->started) + sm->scaninfo->stop = 1; + else + complete_all(&sm->scaninfo->finished); + } + spin_unlock_irqrestore(&sm->lock, flags); +} + +void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(dev); + unsigned long flags; + + assert(ieee80211softmac_scan_handlers_check_self(sm)); + if (!ieee80211softmac_scan_handlers_check_self(sm)) + return; + + spin_lock_irqsave(&sm->lock, flags); + if (!sm->scaninfo->started) { + spin_unlock_irqrestore(&sm->lock, flags); + return; + } + spin_unlock_irqrestore(&sm->lock, flags); + wait_for_completion(&sm->scaninfo->finished); +} + +/* this is what drivers (that do scanning) call when they're done */ +void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) +{ + unsigned long flags; + + spin_lock_irqsave(&sm->lock, flags); + sm->scanning = 0; + spin_unlock_irqrestore(&sm->lock, flags); + + if (sm->associnfo.bssvalid) { + struct ieee80211softmac_network *net; + + net = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid); + if (net) + sm->set_channel(sm->dev, net->channel); + } + ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c new file mode 100644 index 000000000000..e1a9bc6d36ff --- /dev/null +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -0,0 +1,412 @@ +/* + * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them + * + * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net> + * Joseph Jezak <josejx@gentoo.org> + * Larry Finger <Larry.Finger@lwfinger.net> + * Danny van Dyk <kugelfang@gentoo.org> + * Michael Buesch <mbuesch@freenet.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +#include "ieee80211softmac_priv.h" + +#include <net/iw_handler.h> + + +int +ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + return ieee80211softmac_start_scan(sm); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); + + +int +ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + return ieee80211_wx_get_scan(sm->ieee, info, data, extra); +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); + +int +ieee80211softmac_wx_set_essid(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + int length = 0; + unsigned long flags; + + spin_lock_irqsave(&sm->lock, flags); + + sm->associnfo.static_essid = 0; + + if (data->essid.flags && data->essid.length && extra /*required?*/) { + length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE); + if (length) { + memcpy(sm->associnfo.req_essid.data, extra, length); + sm->associnfo.static_essid = 1; + } + } + sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; + + /* set our requested ESSID length. + * If applicable, we have already copied the data in */ + sm->associnfo.req_essid.len = length; + + /* queue lower level code to do work (if necessary) */ + schedule_work(&sm->associnfo.work); + + spin_unlock_irqrestore(&sm->lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid); + +int +ieee80211softmac_wx_get_essid(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + unsigned long flags; + + /* avoid getting inconsistent information */ + spin_lock_irqsave(&sm->lock, flags); + /* If all fails, return ANY (empty) */ + data->essid.length = 0; + data->essid.flags = 0; /* active */ + + /* If we have a statically configured ESSID then return it */ + if (sm->associnfo.static_essid) { + data->essid.length = sm->associnfo.req_essid.len; + data->essid.flags = 1; /* active */ + memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len); + } + + /* If we're associating/associated, return that */ + if (sm->associated || sm->associnfo.associating) { + data->essid.length = sm->associnfo.associate_essid.len; + data->essid.flags = 1; /* active */ + memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len); + } + spin_unlock_irqrestore(&sm->lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid); + +int +ieee80211softmac_wx_set_rate(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + struct ieee80211_device *ieee = mac->ieee; + unsigned long flags; + s32 in_rate = data->bitrate.value; + u8 rate; + int is_ofdm = 0; + int err = -EINVAL; + + if (in_rate == -1) { + /* automatic detect */ + if (ieee->modulation & IEEE80211_OFDM_MODULATION) + in_rate = 54000000; + else + in_rate = 11000000; + } + + switch (in_rate) { + case 1000000: + rate = IEEE80211_CCK_RATE_1MB; + break; + case 2000000: + rate = IEEE80211_CCK_RATE_2MB; + break; + case 5500000: + rate = IEEE80211_CCK_RATE_5MB; + break; + case 11000000: + rate = IEEE80211_CCK_RATE_11MB; + break; + case 6000000: + rate = IEEE80211_OFDM_RATE_6MB; + is_ofdm = 1; + break; + case 9000000: + rate = IEEE80211_OFDM_RATE_9MB; + is_ofdm = 1; + break; + case 12000000: + rate = IEEE80211_OFDM_RATE_12MB; + is_ofdm = 1; + break; + case 18000000: + rate = IEEE80211_OFDM_RATE_18MB; + is_ofdm = 1; + break; + case 24000000: + rate = IEEE80211_OFDM_RATE_24MB; + is_ofdm = 1; + break; + case 36000000: + rate = IEEE80211_OFDM_RATE_36MB; + is_ofdm = 1; + break; + case 48000000: + rate = IEEE80211_OFDM_RATE_48MB; + is_ofdm = 1; + break; + case 54000000: + rate = IEEE80211_OFDM_RATE_54MB; + is_ofdm = 1; + break; + default: + goto out; + } + + spin_lock_irqsave(&mac->lock, flags); + + /* Check if correct modulation for this PHY. */ + if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION)) + goto out_unlock; + + mac->txrates.default_rate = rate; + mac->txrates.default_fallback = lower_rate(mac, rate); + err = 0; + +out_unlock: + spin_unlock_irqrestore(&mac->lock, flags); +out: + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate); + +int +ieee80211softmac_wx_get_rate(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + unsigned long flags; + int err = -EINVAL; + + spin_lock_irqsave(&mac->lock, flags); + switch (mac->txrates.default_rate) { + case IEEE80211_CCK_RATE_1MB: + data->bitrate.value = 1000000; + break; + case IEEE80211_CCK_RATE_2MB: + data->bitrate.value = 2000000; + break; + case IEEE80211_CCK_RATE_5MB: + data->bitrate.value = 5500000; + break; + case IEEE80211_CCK_RATE_11MB: + data->bitrate.value = 11000000; + break; + case IEEE80211_OFDM_RATE_6MB: + data->bitrate.value = 6000000; + break; + case IEEE80211_OFDM_RATE_9MB: + data->bitrate.value = 9000000; + break; + case IEEE80211_OFDM_RATE_12MB: + data->bitrate.value = 12000000; + break; + case IEEE80211_OFDM_RATE_18MB: + data->bitrate.value = 18000000; + break; + case IEEE80211_OFDM_RATE_24MB: + data->bitrate.value = 24000000; + break; + case IEEE80211_OFDM_RATE_36MB: + data->bitrate.value = 36000000; + break; + case IEEE80211_OFDM_RATE_48MB: + data->bitrate.value = 48000000; + break; + case IEEE80211_OFDM_RATE_54MB: + data->bitrate.value = 54000000; + break; + default: + assert(0); + goto out_unlock; + } + err = 0; +out_unlock: + spin_unlock_irqrestore(&mac->lock, flags); + + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate); + +int +ieee80211softmac_wx_get_wap(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + int err = 0; + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + if (mac->associnfo.bssvalid) + memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN); + else + memset(data->ap_addr.sa_data, 0xff, ETH_ALEN); + data->ap_addr.sa_family = ARPHRD_ETHER; + spin_unlock_irqrestore(&mac->lock, flags); + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap); + +int +ieee80211softmac_wx_set_wap(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned long flags; + + /* sanity check */ + if (data->ap_addr.sa_family != ARPHRD_ETHER) { + return -EINVAL; + } + + spin_lock_irqsave(&mac->lock, flags); + if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || + !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { + schedule_work(&mac->associnfo.work); + goto out; + } else { + if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { + if (mac->associnfo.associating || mac->associated) { + /* bssid unchanged and associated or associating - just return */ + goto out; + } + } else { + /* copy new value in data->ap_addr.sa_data to bssid */ + memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); + } + /* queue associate if new bssid or (old one again and not associated) */ + schedule_work(&mac->associnfo.work); + } + +out: + spin_unlock_irqrestore(&mac->lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap); + +int +ieee80211softmac_wx_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + int err = 0; + char *buf; + int i; + + spin_lock_irqsave(&mac->lock, flags); + /* bleh. shouldn't be locked for that kmalloc... */ + + if (wrqu->data.length) { + if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) { + /* this is an IE, so the length must be + * correct. Is it possible though that + * more than one IE is passed in? + */ + err = -EINVAL; + goto out; + } + if (mac->wpa.IEbuflen <= wrqu->data.length) { + buf = kmalloc(wrqu->data.length, GFP_ATOMIC); + if (!buf) { + err = -ENOMEM; + goto out; + } + kfree(mac->wpa.IE); + mac->wpa.IE = buf; + mac->wpa.IEbuflen = wrqu->data.length; + } + memcpy(mac->wpa.IE, extra, wrqu->data.length); + dprintk(KERN_INFO PFX "generic IE set to "); + for (i=0;i<wrqu->data.length;i++) + dprintk("%.2x", mac->wpa.IE[i]); + dprintk("\n"); + mac->wpa.IElen = wrqu->data.length; + } else { + kfree(mac->wpa.IE); + mac->wpa.IE = NULL; + mac->wpa.IElen = 0; + mac->wpa.IEbuflen = 0; + } + + out: + spin_unlock_irqrestore(&mac->lock, flags); + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie); + +int +ieee80211softmac_wx_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + unsigned long flags; + int err = 0; + int space = wrqu->data.length; + + spin_lock_irqsave(&mac->lock, flags); + + wrqu->data.length = 0; + + if (mac->wpa.IE && mac->wpa.IElen) { + wrqu->data.length = mac->wpa.IElen; + if (mac->wpa.IElen <= space) + memcpy(extra, mac->wpa.IE, mac->wpa.IElen); + else + err = -E2BIG; + } + spin_unlock_irqrestore(&mac->lock, flags); + return err; +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie); + diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 768e8f5d7daa..ec566f3e66c7 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -104,6 +104,8 @@ static struct hlist_head fib_rules; /* writer func called from netlink -- rtnl_sem hold*/ +static void rtmsg_rule(int, struct fib_rule *); + int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { struct rtattr **rta = arg; @@ -131,6 +133,7 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) hlist_del_rcu(&r->hlist); r->r_dead = 1; + rtmsg_rule(RTM_DELRULE, r); fib_rule_put(r); err = 0; break; @@ -253,6 +256,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) else hlist_add_before_rcu(&new_r->hlist, &r->hlist); + rtmsg_rule(RTM_NEWRULE, new_r); return 0; } @@ -382,14 +386,14 @@ static struct notifier_block fib_rules_notifier = { static __inline__ int inet_fill_rule(struct sk_buff *skb, struct fib_rule *r, - struct netlink_callback *cb, + u32 pid, u32 seq, int event, unsigned int flags) { struct rtmsg *rtm; struct nlmsghdr *nlh; unsigned char *b = skb->tail; - nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags); + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags); rtm = NLMSG_DATA(nlh); rtm->rtm_family = AF_INET; rtm->rtm_dst_len = r->r_dst_len; @@ -430,6 +434,21 @@ rtattr_failure: /* callers should hold rtnl semaphore */ +static void rtmsg_rule(int event, struct fib_rule *r) +{ + int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128); + struct sk_buff *skb = alloc_skb(size, GFP_KERNEL); + + if (!skb) + netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS); + else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) { + kfree_skb(skb); + netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL); + } else { + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL); + } +} + int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) { int idx = 0; @@ -442,7 +461,9 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) if (idx < s_idx) continue; - if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) + if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_NEWRULE, NLM_F_MULTI) < 0) break; idx++; } diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4fbc40b13f19..e46048974f37 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -161,7 +161,7 @@ int ip6_output(struct sk_buff *skb) int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, struct ipv6_txoptions *opt, int ipfragok) { - struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL; + struct ipv6_pinfo *np = inet6_sk(sk); struct in6_addr *first_hop = &fl->fl6_dst; struct dst_entry *dst = skb->dst; struct ipv6hdr *hdr; diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 2b670479dde1..78e052591fa9 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -347,8 +347,7 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n) if (n->ht_down) n->ht_down->refcnt--; #ifdef CONFIG_CLS_U32_PERF - if (n) - kfree(n->pf); + kfree(n->pf); #endif kfree(n); return 0; @@ -680,8 +679,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, return 0; } #ifdef CONFIG_CLS_U32_PERF - if (n) - kfree(n->pf); + kfree(n->pf); #endif kfree(n); return err; diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index a17375141c3a..6ba8d6f45fe8 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c @@ -88,8 +88,6 @@ #include <linux/pmu.h> #endif -#include <linux/i2c-dev.h> - #include <asm/uaccess.h> #include <asm/prom.h> #include <asm/machdep.h> diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index 08cde51177d7..aa09ebd9ffb8 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c @@ -22,7 +22,6 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/i2c.h> -#include <linux/i2c-dev.h> #include <linux/kmod.h> #include <linux/slab.h> #include <sound/core.h> diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 6058c2dd1b7f..fb05938dcbd9 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/delay.h> -#include <linux/i2c-dev.h> #include <linux/slab.h> #include <sound/core.h> #include "pmac.h" diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c index 053b8f24e4dc..210be20dc27e 100644 --- a/sound/ppc/toonie.c +++ b/sound/ppc/toonie.c @@ -22,7 +22,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/i2c.h> -#include <linux/i2c-dev.h> #include <linux/kmod.h> #include <linux/slab.h> #include <linux/interrupt.h> diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 838fc113c441..1146dd882bb1 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -28,7 +28,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/i2c.h> -#include <linux/i2c-dev.h> #include <linux/kmod.h> #include <linux/slab.h> #include <linux/interrupt.h> |