## Automatically generated incremental diff ## From: linux-2.5.72-bk2 ## To: linux-2.5.72-bk3 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.72-bk2/Documentation/firmware_class/README linux-2.5.72-bk3/Documentation/firmware_class/README --- linux-2.5.72-bk2/Documentation/firmware_class/README 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.72-bk3/Documentation/firmware_class/README 2003-06-20 04:48:10.000000000 -0700 @@ -0,0 +1,58 @@ + + request_firmware() hotplug interface: + ------------------------------------ + Copyright (C) 2003 Manuel Estrada Sainz + + Why: + --- + + Today, the most extended way to use firmware in the Linux kernel is linking + it statically in a header file. Which has political and technical issues: + + 1) Some firmware is not legal to redistribute. + 2) The firmware occupies memory permanently, even though it often is just + used once. + 3) Some people, like the Debian crowd, don't consider some firmware free + enough and remove entire drivers (e.g.: keyspan). + + about in-kernel persistence: + --------------------------- + Under some circumstances, as explained below, it would be interesting to keep + firmware images in non-swappable kernel memory or even in the kernel image + (probably within initramfs). + + Note that this functionality has not been implemented. + + - Why OPTIONAL in-kernel persistence may be a good idea sometimes: + + - If the device that needs the firmware is needed to access the + filesystem. When upon some error the device has to be reset and the + firmware reloaded, it won't be possible to get it from userspace. + e.g.: + - A diskless client with a network card that needs firmware. + - The filesystem is stored in a disk behind an scsi device + that needs firmware. + - Replacing buggy DSDT/SSDT ACPI tables on boot. + Note: this would require the persistent objects to be included + within the kernel image, probably within initramfs. + + And the same device can be needed to access the filesystem or not depending + on the setup, so I think that the choice on what firmware to make + persistent should be left to userspace. + + - Why register_firmware()+__init can be useful: + - For boot devices needing firmware. + - To make the transition easier: + The firmware can be declared __init and register_firmware() + called on module_init. Then the firmware is warranted to be + there even if "firmware hotplug userspace" is not there yet or + it doesn't yet provide the needed firmware. + Once the firmware is widely available in userspace, it can be + removed from the kernel. Or made optional (CONFIG_.*_FIRMWARE). + + In either case, if firmware hotplug support is there, it can move the + firmware out of kernel memory into the real filesystem for later + usage. + + Note: If persistence is implemented on top of initramfs, + register_firmware() may not be appropriate. diff -urN linux-2.5.72-bk2/Documentation/firmware_class/firmware_sample_driver.c linux-2.5.72-bk3/Documentation/firmware_class/firmware_sample_driver.c --- linux-2.5.72-bk2/Documentation/firmware_class/firmware_sample_driver.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.72-bk3/Documentation/firmware_class/firmware_sample_driver.c 2003-06-20 04:48:10.000000000 -0700 @@ -0,0 +1,126 @@ +/* + * firmware_sample_driver.c - + * + * Copyright (c) 2003 Manuel Estrada Sainz + * + * Sample code on how to use request_firmware() from drivers. + * + * Note that register_firmware() is currently useless. + * + */ + +#include +#include +#include +#include + +#include "linux/firmware.h" + +#define WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE +#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE +char __init inkernel_firmware[] = "let's say that this is firmware\n"; +#endif + +static struct device ghost_device = { + .name = "Ghost Device", + .bus_id = "ghost0", +}; + + +static void sample_firmware_load(char *firmware, int size) +{ + u8 buf[size+1]; + memcpy(buf, firmware, size); + buf[size] = '\0'; + printk("firmware_sample_driver: firmware: %s\n", buf); +} + +static void sample_probe_default(void) +{ + /* uses the default method to get the firmware */ + const struct firmware *fw_entry; + printk("firmware_sample_driver: a ghost device got inserted :)\n"); + + if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0) + { + printk(KERN_ERR + "firmware_sample_driver: Firmware not available\n"); + return; + } + + sample_firmware_load(fw_entry->data, fw_entry->size); + + release_firmware(fw_entry); + + /* finish setting up the device */ +} +static void sample_probe_specific(void) +{ + /* Uses some specific hotplug support to get the firmware from + * userspace directly into the hardware, or via some sysfs file */ + + /* NOTE: This currently doesn't work */ + + printk("firmware_sample_driver: a ghost device got inserted :)\n"); + + if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0) + { + printk(KERN_ERR + "firmware_sample_driver: Firmware load failed\n"); + return; + } + + /* request_firmware blocks until userspace finished, so at + * this point the firmware should be already in the device */ + + /* finish setting up the device */ +} +static void sample_probe_async_cont(const struct firmware *fw, void *context) +{ + if(!fw){ + printk(KERN_ERR + "firmware_sample_driver: firmware load failed\n"); + return; + } + + printk("firmware_sample_driver: device pointer \"%s\"\n", + (char *)context); + sample_firmware_load(fw->data, fw->size); +} +static void sample_probe_async(void) +{ + /* Let's say that I can't sleep */ + int error; + error = request_firmware_nowait (THIS_MODULE, + "sample_driver_fw", &ghost_device, + "my device pointer", + sample_probe_async_cont); + if(error){ + printk(KERN_ERR + "firmware_sample_driver:" + " request_firmware_nowait failed\n"); + } +} + +static int sample_init(void) +{ +#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE + register_firmware("sample_driver_fw", inkernel_firmware, + sizeof(inkernel_firmware)); +#endif + device_initialize(&ghost_device); + /* since there is no real hardware insertion I just call the + * sample probe functions here */ + sample_probe_specific(); + sample_probe_default(); + sample_probe_async(); + return 0; +} +static void __exit sample_exit(void) +{ +} + +module_init (sample_init); +module_exit (sample_exit); + +MODULE_LICENSE("GPL"); diff -urN linux-2.5.72-bk2/Documentation/firmware_class/firmware_sample_firmware_class.c linux-2.5.72-bk3/Documentation/firmware_class/firmware_sample_firmware_class.c --- linux-2.5.72-bk2/Documentation/firmware_class/firmware_sample_firmware_class.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.72-bk3/Documentation/firmware_class/firmware_sample_firmware_class.c 2003-06-20 04:48:10.000000000 -0700 @@ -0,0 +1,205 @@ +/* + * firmware_sample_firmware_class.c - + * + * Copyright (c) 2003 Manuel Estrada Sainz + * + * NOTE: This is just a probe of concept, if you think that your driver would + * be well served by this mechanism please contact me first. + * + * DON'T USE THIS CODE AS IS + * + */ + +#include +#include +#include +#include +#include + +#include "linux/firmware.h" + +MODULE_AUTHOR("Manuel Estrada Sainz "); +MODULE_DESCRIPTION("Hackish sample for using firmware class directly"); +MODULE_LICENSE("GPL"); + +static inline struct class_device *to_class_dev(struct kobject *obj) +{ + return container_of(obj,struct class_device,kobj); +} +static inline +struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) +{ + return container_of(_attr,struct class_device_attribute,attr); +} + +int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); +int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); + +struct firmware_priv { + char fw_id[FIRMWARE_NAME_MAX]; + s32 loading:2; + u32 abort:1; +}; + +extern struct class firmware_class; + +static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + return sprintf(buf, "%d\n", fw_priv->loading); +} +static ssize_t firmware_loading_store(struct class_device *class_dev, + const char *buf, size_t count) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + int prev_loading = fw_priv->loading; + + fw_priv->loading = simple_strtol(buf, NULL, 10); + + switch(fw_priv->loading){ + case -1: + /* abort load an panic */ + break; + case 1: + /* setup load */ + break; + case 0: + if(prev_loading==1){ + /* finish load and get the device back to working + * state */ + } + break; + } + + return count; +} +static CLASS_DEVICE_ATTR(loading, 0644, + firmware_loading_show, firmware_loading_store); + +static ssize_t firmware_data_read(struct kobject *kobj, + char *buffer, loff_t offset, size_t count) +{ + struct class_device *class_dev = to_class_dev(kobj); + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + + /* read from the devices firmware memory */ + + return count; +} +static ssize_t firmware_data_write(struct kobject *kobj, + char *buffer, loff_t offset, size_t count) +{ + struct class_device *class_dev = to_class_dev(kobj); + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + + /* write to the devices firmware memory */ + + return count; +} +static struct bin_attribute firmware_attr_data = { + .attr = {.name = "data", .mode = 0644}, + .size = 0, + .read = firmware_data_read, + .write = firmware_data_write, +}; +static int fw_setup_class_device(struct class_device *class_dev, + const char *fw_name, + struct device *device) +{ + int retval = 0; + struct firmware_priv *fw_priv = kmalloc(sizeof(struct firmware_priv), + GFP_KERNEL); + + if(!fw_priv){ + retval = -ENOMEM; + goto out; + } + memset(fw_priv, 0, sizeof(*fw_priv)); + memset(class_dev, 0, sizeof(*class_dev)); + + strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); + fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0'; + + strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE); + class_dev->class_id[BUS_ID_SIZE-1] = '\0'; + class_dev->dev = device; + + class_dev->class = &firmware_class, + class_set_devdata(class_dev, fw_priv); + retval = class_device_register(class_dev); + if (retval){ + printk(KERN_ERR "%s: class_device_register failed\n", + __FUNCTION__); + goto error_free_fw_priv; + } + + retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data); + if (retval){ + printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", + __FUNCTION__); + goto error_unreg_class_dev; + } + + retval = class_device_create_file(class_dev, + &class_device_attr_loading); + if (retval){ + printk(KERN_ERR "%s: class_device_create_file failed\n", + __FUNCTION__); + goto error_remove_data; + } + + goto out; + +error_remove_data: + sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data); +error_unreg_class_dev: + class_device_unregister(class_dev); +error_free_fw_priv: + kfree(fw_priv); +out: + return retval; +} +static void fw_remove_class_device(struct class_device *class_dev) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + + class_device_remove_file(class_dev, &class_device_attr_loading); + sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data); + class_device_unregister(class_dev); +} + +static struct class_device *class_dev; + +static struct device my_device = { + .name = "Sample Device", + .bus_id = "my_dev0", +}; + +static int __init firmware_sample_init(void) +{ + int error; + + device_initialize(&my_device); + class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL); + if(!class_dev) + return -ENOMEM; + + error = fw_setup_class_device(class_dev, "my_firmware_image", + &my_device); + if(error){ + kfree(class_dev); + return error; + } + return 0; + +} +static void __exit firmware_sample_exit(void) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + fw_remove_class_device(class_dev); + kfree(fw_priv); + kfree(class_dev); +} +module_init(firmware_sample_init); +module_exit(firmware_sample_exit); + diff -urN linux-2.5.72-bk2/Documentation/firmware_class/hotplug-script linux-2.5.72-bk3/Documentation/firmware_class/hotplug-script --- linux-2.5.72-bk2/Documentation/firmware_class/hotplug-script 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.72-bk3/Documentation/firmware_class/hotplug-script 2003-06-20 04:48:10.000000000 -0700 @@ -0,0 +1,16 @@ +#!/bin/sh + +# Simple hotplug script sample: +# +# Both $DEVPATH and $FIRMWARE are already provided in the environment. + +HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/ + +echo 1 > /sysfs/$DEVPATH/loading +cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data +echo 0 > /sysfs/$DEVPATH/loading + +# To cancel the load in case of error: +# +# echo -1 > /sysfs/$DEVPATH/loading +# diff -urN linux-2.5.72-bk2/Documentation/kobject.txt linux-2.5.72-bk3/Documentation/kobject.txt --- linux-2.5.72-bk2/Documentation/kobject.txt 2003-06-16 21:19:46.000000000 -0700 +++ linux-2.5.72-bk3/Documentation/kobject.txt 2003-06-20 04:48:10.000000000 -0700 @@ -5,15 +5,8 @@ Updated: 3 June 2003 -Copyright (c) Patrick Mochel -Copyright (c) Open Source Development Labs -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.2 -or any later version published by the Free Software Foundation; -with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. -A copy of the license is included in the section entitled "GNU -Free Documentation License". - +Copyright (c) 2003 Patrick Mochel +Copyright (c) 2003 Open Source Development Labs 0. Introduction diff -urN linux-2.5.72-bk2/Makefile linux-2.5.72-bk3/Makefile --- linux-2.5.72-bk2/Makefile 2003-06-20 04:48:04.000000000 -0700 +++ linux-2.5.72-bk3/Makefile 2003-06-20 04:48:10.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 72 -EXTRAVERSION = -bk2 +EXTRAVERSION = -bk3 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -urN linux-2.5.72-bk2/arch/alpha/Kconfig linux-2.5.72-bk3/arch/alpha/Kconfig --- linux-2.5.72-bk2/arch/alpha/Kconfig 2003-06-20 04:48:04.000000000 -0700 +++ linux-2.5.72-bk3/arch/alpha/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -653,6 +653,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/pnp/Kconfig" diff -urN linux-2.5.72-bk2/arch/alpha/kernel/alpha_ksyms.c linux-2.5.72-bk3/arch/alpha/kernel/alpha_ksyms.c --- linux-2.5.72-bk2/arch/alpha/kernel/alpha_ksyms.c 2003-06-16 21:19:40.000000000 -0700 +++ linux-2.5.72-bk3/arch/alpha/kernel/alpha_ksyms.c 2003-06-20 04:48:10.000000000 -0700 @@ -156,7 +156,7 @@ EXPORT_SYMBOL(sys_write); EXPORT_SYMBOL(sys_read); EXPORT_SYMBOL(sys_lseek); -EXPORT_SYMBOL(__kernel_execve); +EXPORT_SYMBOL(execve); EXPORT_SYMBOL(sys_setsid); EXPORT_SYMBOL(sys_wait4); diff -urN linux-2.5.72-bk2/arch/alpha/kernel/entry.S linux-2.5.72-bk3/arch/alpha/kernel/entry.S --- linux-2.5.72-bk2/arch/alpha/kernel/entry.S 2003-06-16 21:19:37.000000000 -0700 +++ linux-2.5.72-bk3/arch/alpha/kernel/entry.S 2003-06-20 04:48:10.000000000 -0700 @@ -606,7 +606,8 @@ .globl kernel_thread .ent kernel_thread kernel_thread: - ldgp $gp, 0($27) /* we can be called from a module */ + /* We can be called from a module. */ + ldgp $gp, 0($27) .prologue 1 subq $sp, SP_OFF+6*8, $sp br $1, 2f /* load start address */ @@ -654,26 +655,56 @@ .end kernel_thread /* - * __kernel_execve(path, argv, envp, regs) + * execve(path, argv, envp) */ .align 4 - .globl __kernel_execve - .ent __kernel_execve -__kernel_execve: - ldgp $gp, 0($27) /* we can be called from modules. */ - subq $sp, 16, $sp - .frame $sp, 16, $26, 0 + .globl execve + .ent execve +execve: + /* We can be called from a module. */ + ldgp $gp, 0($27) + lda $sp, -(32+SIZEOF_PT_REGS+8)($sp) + .frame $sp, 32+SIZEOF_PT_REGS+8, $26, 0 stq $26, 0($sp) - stq $19, 8($sp) + stq $16, 8($sp) + stq $17, 16($sp) + stq $18, 24($sp) .prologue 1 - jsr $26, do_execve - bne $0, 1f /* error! */ - ldq $sp, 8($sp) + + lda $16, 32($sp) + lda $17, 0 + lda $18, SIZEOF_PT_REGS + bsr $26, memset !samegp + + /* Avoid the HAE being gratuitously wrong, which would cause us + to do the whole turn off interrupts thing and restore it. */ + ldq $2, alpha_mv+HAE_CACHE + stq $2, 152+32($sp) + + ldq $16, 8($sp) + ldq $17, 16($sp) + ldq $18, 24($sp) + lda $19, 32($sp) + bsr $26, do_execve !samegp + + ldq $26, 0($sp) + bne $0, 1f /* error! */ + + /* Move the temporary pt_regs struct from its current location + to the top of the kernel stack frame. See copy_thread for + details for a normal process. */ + lda $16, 0x4000 - SIZEOF_PT_REGS($8) + lda $17, 32($sp) + lda $18, SIZEOF_PT_REGS + bsr $26, memmove !samegp + + /* Take that over as our new stack frame and visit userland! */ + lda $sp, 0x4000 - SIZEOF_PT_REGS($8) br $31, ret_from_sys_call -1: ldq $26, 0($sp) - addq $sp, 16, $sp + +1: lda $sp, 32+SIZEOF_PT_REGS+8($sp) ret -.end __kernel_execve +.end execve /* diff -urN linux-2.5.72-bk2/arch/alpha/kernel/srmcons.c linux-2.5.72-bk3/arch/alpha/kernel/srmcons.c --- linux-2.5.72-bk2/arch/alpha/kernel/srmcons.c 2003-06-16 21:20:22.000000000 -0700 +++ linux-2.5.72-bk3/arch/alpha/kernel/srmcons.c 2003-06-20 04:48:10.000000000 -0700 @@ -291,6 +291,7 @@ driver->type = TTY_DRIVER_TYPE_SYSTEM; driver->subtype = SYSTEM_TYPE_SYSCONS; driver->init_termios = tty_std_termios; + tty_set_operations(driver, &srmcons_ops); err = tty_register_driver(driver); if (err) { put_tty_driver(driver); diff -urN linux-2.5.72-bk2/arch/alpha/lib/memmove.S linux-2.5.72-bk3/arch/alpha/lib/memmove.S --- linux-2.5.72-bk2/arch/alpha/lib/memmove.S 2003-06-16 21:20:01.000000000 -0700 +++ linux-2.5.72-bk3/arch/alpha/lib/memmove.S 2003-06-20 04:48:10.000000000 -0700 @@ -15,15 +15,23 @@ .globl bcopy .ent bcopy bcopy: + ldgp $29, 0($27) + .prologue 1 mov $16,$0 mov $17,$16 mov $0,$17 + br $31, memmove !samegp .end bcopy .align 4 .globl memmove .ent memmove memmove: + ldgp $29, 0($27) + unop + nop + .prologue 1 + addq $16,$18,$4 addq $17,$18,$5 cmpule $4,$17,$1 /* dest + n <= src */ @@ -32,7 +40,7 @@ bis $1,$2,$1 mov $16,$0 xor $16,$17,$2 - bne $1,memcpy + bne $1,memcpy !samegp and $2,7,$2 /* Test for src/dest co-alignment. */ and $16,7,$1 diff -urN linux-2.5.72-bk2/arch/alpha/oprofile/common.c linux-2.5.72-bk3/arch/alpha/oprofile/common.c --- linux-2.5.72-bk2/arch/alpha/oprofile/common.c 2003-06-16 21:19:40.000000000 -0700 +++ linux-2.5.72-bk3/arch/alpha/oprofile/common.c 2003-06-20 04:48:10.000000000 -0700 @@ -188,7 +188,7 @@ } -void __exit +void oprofile_arch_exit(void) { } diff -urN linux-2.5.72-bk2/arch/arm/Kconfig linux-2.5.72-bk3/arch/arm/Kconfig --- linux-2.5.72-bk2/arch/arm/Kconfig 2003-06-20 04:48:04.000000000 -0700 +++ linux-2.5.72-bk3/arch/arm/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -703,6 +703,8 @@ source "fs/Kconfig.binfmt" +source "drivers/base/Kconfig" + config PM bool "Power Management support" ---help--- diff -urN linux-2.5.72-bk2/arch/arm26/Kconfig linux-2.5.72-bk3/arch/arm26/Kconfig --- linux-2.5.72-bk2/arch/arm26/Kconfig 2003-06-16 21:20:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/arm26/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -297,6 +297,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/parport/Kconfig" source "drivers/pnp/Kconfig" diff -urN linux-2.5.72-bk2/arch/cris/Kconfig linux-2.5.72-bk3/arch/cris/Kconfig --- linux-2.5.72-bk2/arch/cris/Kconfig 2003-06-20 04:48:04.000000000 -0700 +++ linux-2.5.72-bk3/arch/cris/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -515,6 +515,8 @@ endmenu +source "drivers/base/Kconfig" + # bring in Etrax built-in drivers source "arch/cris/drivers/Kconfig" diff -urN linux-2.5.72-bk2/arch/h8300/Kconfig linux-2.5.72-bk3/arch/h8300/Kconfig --- linux-2.5.72-bk2/arch/h8300/Kconfig 2003-06-20 04:48:04.000000000 -0700 +++ linux-2.5.72-bk3/arch/h8300/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -145,6 +145,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/block/Kconfig" source "drivers/ide/Kconfig" diff -urN linux-2.5.72-bk2/arch/i386/Kconfig linux-2.5.72-bk3/arch/i386/Kconfig --- linux-2.5.72-bk2/arch/i386/Kconfig 2003-06-20 04:48:04.000000000 -0700 +++ linux-2.5.72-bk3/arch/i386/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -1194,6 +1194,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/parport/Kconfig" diff -urN linux-2.5.72-bk2/arch/i386/kernel/time.c linux-2.5.72-bk3/arch/i386/kernel/time.c --- linux-2.5.72-bk2/arch/i386/kernel/time.c 2003-06-16 21:20:01.000000000 -0700 +++ linux-2.5.72-bk3/arch/i386/kernel/time.c 2003-06-20 04:48:10.000000000 -0700 @@ -281,19 +281,19 @@ return retval; } -static struct sysdev_class rtc_sysclass = { - set_kset_name("rtc"), +static struct sysdev_class pit_sysclass = { + set_kset_name("pit"), }; /* XXX this driverfs stuff should probably go elsewhere later -john */ static struct sys_device device_i8253 = { - .id = 0, - .cls = &rtc_sysclass, + .id = 0, + .cls = &pit_sysclass, }; static int time_init_device(void) { - int error = sysdev_class_register(&rtc_sysclass); + int error = sysdev_class_register(&pit_sysclass); if (!error) error = sys_device_register(&device_i8253); return error; diff -urN linux-2.5.72-bk2/arch/ia64/Kconfig linux-2.5.72-bk3/arch/ia64/Kconfig --- linux-2.5.72-bk2/arch/ia64/Kconfig 2003-06-20 04:48:04.000000000 -0700 +++ linux-2.5.72-bk3/arch/ia64/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -534,6 +534,8 @@ endmenu +source "drivers/base/Kconfig" + if !IA64_HP_SIM source "drivers/mtd/Kconfig" diff -urN linux-2.5.72-bk2/arch/m68k/Kconfig linux-2.5.72-bk3/arch/m68k/Kconfig --- linux-2.5.72-bk2/arch/m68k/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/m68k/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -573,6 +573,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/block/Kconfig" diff -urN linux-2.5.72-bk2/arch/m68knommu/Kconfig linux-2.5.72-bk3/arch/m68knommu/Kconfig --- linux-2.5.72-bk2/arch/m68knommu/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/m68knommu/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -515,6 +515,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/parport/Kconfig" diff -urN linux-2.5.72-bk2/arch/mips/Kconfig linux-2.5.72-bk3/arch/mips/Kconfig --- linux-2.5.72-bk2/arch/mips/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/mips/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -744,6 +744,8 @@ source "drivers/pnp/Kconfig" endif +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/parport/Kconfig" diff -urN linux-2.5.72-bk2/arch/mips64/Kconfig linux-2.5.72-bk3/arch/mips64/Kconfig --- linux-2.5.72-bk2/arch/mips64/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/mips64/Kconfig 2003-06-20 04:48:10.000000000 -0700 @@ -361,6 +361,8 @@ source "drivers/pci/Kconfig" +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/parport/Kconfig" diff -urN linux-2.5.72-bk2/arch/parisc/Kconfig linux-2.5.72-bk3/arch/parisc/Kconfig --- linux-2.5.72-bk2/arch/parisc/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/parisc/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -170,6 +170,8 @@ endmenu +source "drivers/base/Kconfig" + # source "drivers/mtd/Kconfig" source "drivers/parport/Kconfig" diff -urN linux-2.5.72-bk2/arch/ppc/Kconfig linux-2.5.72-bk3/arch/ppc/Kconfig --- linux-2.5.72-bk2/arch/ppc/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/ppc/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -1163,6 +1163,8 @@ depends on ADVANCED_OPTIONS && 8xx endmenu +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/pnp/Kconfig" diff -urN linux-2.5.72-bk2/arch/ppc64/Kconfig linux-2.5.72-bk3/arch/ppc64/Kconfig --- linux-2.5.72-bk2/arch/ppc64/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/ppc64/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -241,6 +241,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/parport/Kconfig" diff -urN linux-2.5.72-bk2/arch/s390/Kconfig linux-2.5.72-bk3/arch/s390/Kconfig --- linux-2.5.72-bk2/arch/s390/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/s390/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -229,6 +229,8 @@ bool default n +source "drivers/base/Kconfig" + menu "SCSI support" config SCSI diff -urN linux-2.5.72-bk2/arch/sh/Kconfig linux-2.5.72-bk3/arch/sh/Kconfig --- linux-2.5.72-bk2/arch/sh/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/sh/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -767,6 +767,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/parport/Kconfig" diff -urN linux-2.5.72-bk2/arch/sparc/Kconfig linux-2.5.72-bk3/arch/sparc/Kconfig --- linux-2.5.72-bk2/arch/sparc/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/sparc/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -319,6 +319,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/video/Kconfig" source "drivers/mtd/Kconfig" diff -urN linux-2.5.72-bk2/arch/sparc64/Kconfig linux-2.5.72-bk3/arch/sparc64/Kconfig --- linux-2.5.72-bk2/arch/sparc64/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/sparc64/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -521,6 +521,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/video/Kconfig" source "drivers/serial/Kconfig" diff -urN linux-2.5.72-bk2/arch/um/Kconfig linux-2.5.72-bk3/arch/um/Kconfig --- linux-2.5.72-bk2/arch/um/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/um/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -171,6 +171,8 @@ source "init/Kconfig" +source "drivers/base/Kconfig" + source "arch/um/Kconfig_char" source "arch/um/Kconfig_block" diff -urN linux-2.5.72-bk2/arch/v850/Kconfig linux-2.5.72-bk3/arch/v850/Kconfig --- linux-2.5.72-bk2/arch/v850/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/v850/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -249,6 +249,8 @@ ############################################################################# +source "drivers/base/Kconfig" + source drivers/mtd/Kconfig source drivers/parport/Kconfig diff -urN linux-2.5.72-bk2/arch/x86_64/Kconfig linux-2.5.72-bk3/arch/x86_64/Kconfig --- linux-2.5.72-bk2/arch/x86_64/Kconfig 2003-06-20 04:48:05.000000000 -0700 +++ linux-2.5.72-bk3/arch/x86_64/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -397,6 +397,8 @@ endmenu +source "drivers/base/Kconfig" + source "drivers/mtd/Kconfig" source "drivers/parport/Kconfig" diff -urN linux-2.5.72-bk2/drivers/base/Kconfig linux-2.5.72-bk3/drivers/base/Kconfig --- linux-2.5.72-bk2/drivers/base/Kconfig 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.72-bk3/drivers/base/Kconfig 2003-06-20 04:48:11.000000000 -0700 @@ -0,0 +1,10 @@ +menu "Generic Driver Options" + +config FW_LOADER + tristate "Hotplug firmware loading support" + ---help--- + This option is provided for the case where no in-kernel-tree modules + require hotplug firmware loading support, but a module built outside + the kernel tree does. + +endmenu diff -urN linux-2.5.72-bk2/drivers/base/Makefile linux-2.5.72-bk3/drivers/base/Makefile --- linux-2.5.72-bk2/drivers/base/Makefile 2003-06-16 21:20:21.000000000 -0700 +++ linux-2.5.72-bk3/drivers/base/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -3,4 +3,5 @@ obj-y := core.o sys.o interface.o power.o bus.o \ driver.o class.o platform.o \ cpu.o firmware.o init.o map.o +obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o memblk.o diff -urN linux-2.5.72-bk2/drivers/base/firmware_class.c linux-2.5.72-bk3/drivers/base/firmware_class.c --- linux-2.5.72-bk2/drivers/base/firmware_class.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.72-bk3/drivers/base/firmware_class.c 2003-06-20 04:48:11.000000000 -0700 @@ -0,0 +1,505 @@ +/* + * firmware_class.c - Multi purpose firmware loading support + * + * Copyright (c) 2003 Manuel Estrada Sainz + * + * Please see Documentation/firmware_class/ for more information. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "base.h" + +MODULE_AUTHOR("Manuel Estrada Sainz "); +MODULE_DESCRIPTION("Multi purpose firmware loading support"); +MODULE_LICENSE("GPL"); + +static int loading_timeout = 10; /* In seconds */ + +struct firmware_priv { + char fw_id[FIRMWARE_NAME_MAX]; + struct completion completion; + struct bin_attribute attr_data; + struct firmware *fw; + int loading; + int abort; + int alloc_size; + struct timer_list timeout; +}; + +static ssize_t +firmware_timeout_show(struct class *class, char *buf) +{ + return sprintf(buf, "%d\n", loading_timeout); +} + +/** + * firmware_timeout_store: + * Description: + * Sets the number of seconds to wait for the firmware. Once + * this expires an error will be return to the driver and no + * firmware will be provided. + * + * Note: zero means 'wait for ever' + * + **/ +static ssize_t +firmware_timeout_store(struct class *class, const char *buf, size_t count) +{ + loading_timeout = simple_strtol(buf, NULL, 10); + return count; +} + +static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); + +static void fw_class_dev_release(struct class_device *class_dev); +int firmware_class_hotplug(struct class_device *dev, char **envp, + int num_envp, char *buffer, int buffer_size); + +static struct class firmware_class = { + .name = "firmware", + .hotplug = firmware_class_hotplug, + .release = fw_class_dev_release, +}; + +int +firmware_class_hotplug(struct class_device *class_dev, char **envp, + int num_envp, char *buffer, int buffer_size) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + int i = 0; + char *scratch = buffer; + + if (buffer_size < (FIRMWARE_NAME_MAX + 10)) + return -ENOMEM; + if (num_envp < 1) + return -ENOMEM; + + envp[i++] = scratch; + scratch += sprintf(scratch, "FIRMWARE=%s", fw_priv->fw_id) + 1; + return 0; +} + +static ssize_t +firmware_loading_show(struct class_device *class_dev, char *buf) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + return sprintf(buf, "%d\n", fw_priv->loading); +} + +/** + * firmware_loading_store: - loading control file + * Description: + * The relevant values are: + * + * 1: Start a load, discarding any previous partial load. + * 0: Conclude the load and handle the data to the driver code. + * -1: Conclude the load with an error and discard any written data. + **/ +static ssize_t +firmware_loading_store(struct class_device *class_dev, + const char *buf, size_t count) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + int prev_loading = fw_priv->loading; + + fw_priv->loading = simple_strtol(buf, NULL, 10); + + switch (fw_priv->loading) { + case -1: + fw_priv->abort = 1; + wmb(); + complete(&fw_priv->completion); + break; + case 1: + kfree(fw_priv->fw->data); + fw_priv->fw->data = NULL; + fw_priv->fw->size = 0; + fw_priv->alloc_size = 0; + break; + case 0: + if (prev_loading == 1) + complete(&fw_priv->completion); + break; + } + + return count; +} + +static CLASS_DEVICE_ATTR(loading, 0644, + firmware_loading_show, firmware_loading_store); + +static ssize_t +firmware_data_read(struct kobject *kobj, + char *buffer, loff_t offset, size_t count) +{ + struct class_device *class_dev = to_class_dev(kobj); + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + struct firmware *fw = fw_priv->fw; + + if (offset > fw->size) + return 0; + if (offset + count > fw->size) + count = fw->size - offset; + + memcpy(buffer, fw->data + offset, count); + return count; +} +static int +fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) +{ + u8 *new_data; + + if (min_size <= fw_priv->alloc_size) + return 0; + + new_data = vmalloc(fw_priv->alloc_size + PAGE_SIZE); + if (!new_data) { + printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__); + /* Make sure that we don't keep incomplete data */ + fw_priv->abort = 1; + return -ENOMEM; + } + fw_priv->alloc_size += PAGE_SIZE; + if (fw_priv->fw->data) { + memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size); + vfree(fw_priv->fw->data); + } + fw_priv->fw->data = new_data; + BUG_ON(min_size > fw_priv->alloc_size); + return 0; +} + +/** + * firmware_data_write: + * + * Description: + * + * Data written to the 'data' attribute will be later handled to + * the driver as a firmware image. + **/ +static ssize_t +firmware_data_write(struct kobject *kobj, + char *buffer, loff_t offset, size_t count) +{ + struct class_device *class_dev = to_class_dev(kobj); + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + struct firmware *fw = fw_priv->fw; + int retval; + + retval = fw_realloc_buffer(fw_priv, offset + count); + if (retval) + return retval; + + memcpy(fw->data + offset, buffer, count); + + fw->size = max_t(size_t, offset + count, fw->size); + + return count; +} +static struct bin_attribute firmware_attr_data_tmpl = { + .attr = {.name = "data", .mode = 0644}, + .size = 0, + .read = firmware_data_read, + .write = firmware_data_write, +}; + +static void +fw_class_dev_release(struct class_device *class_dev) +{ + kfree(class_dev); +} + +static void +firmware_class_timeout(u_long data) +{ + struct firmware_priv *fw_priv = (struct firmware_priv *) data; + fw_priv->abort = 1; + wmb(); + complete(&fw_priv->completion); +} + +static inline void +fw_setup_class_device_id(struct class_device *class_dev, struct device *dev) +{ + /* XXX warning we should watch out for name collisions */ + strncpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); + class_dev->class_id[BUS_ID_SIZE - 1] = '\0'; +} +static int +fw_setup_class_device(struct class_device **class_dev_p, + const char *fw_name, struct device *device) +{ + int retval = 0; + struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv), + GFP_KERNEL); + struct class_device *class_dev = kmalloc(sizeof (struct class_device), + GFP_KERNEL); + + if (!fw_priv || !class_dev) { + retval = -ENOMEM; + goto error_kfree; + } + memset(fw_priv, 0, sizeof (*fw_priv)); + memset(class_dev, 0, sizeof (*class_dev)); + + init_completion(&fw_priv->completion); + memcpy(&fw_priv->attr_data, &firmware_attr_data_tmpl, + sizeof (firmware_attr_data_tmpl)); + + strncpy(&fw_priv->fw_id[0], fw_name, FIRMWARE_NAME_MAX); + fw_priv->fw_id[FIRMWARE_NAME_MAX - 1] = '\0'; + + fw_setup_class_device_id(class_dev, device); + class_dev->dev = device; + + fw_priv->timeout.function = firmware_class_timeout; + fw_priv->timeout.data = (u_long) fw_priv; + init_timer(&fw_priv->timeout); + + class_dev->class = &firmware_class; + class_set_devdata(class_dev, fw_priv); + retval = class_device_register(class_dev); + if (retval) { + printk(KERN_ERR "%s: class_device_register failed\n", + __FUNCTION__); + goto error_kfree; + } + + retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data); + if (retval) { + printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", + __FUNCTION__); + goto error_unreg_class_dev; + } + + retval = class_device_create_file(class_dev, + &class_device_attr_loading); + if (retval) { + printk(KERN_ERR "%s: class_device_create_file failed\n", + __FUNCTION__); + goto error_remove_data; + } + + fw_priv->fw = kmalloc(sizeof (struct firmware), GFP_KERNEL); + if (!fw_priv->fw) { + printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", + __FUNCTION__); + retval = -ENOMEM; + goto error_remove_loading; + } + memset(fw_priv->fw, 0, sizeof (*fw_priv->fw)); + + goto out; + +error_remove_loading: + class_device_remove_file(class_dev, &class_device_attr_loading); +error_remove_data: + sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data); +error_unreg_class_dev: + class_device_unregister(class_dev); +error_kfree: + kfree(fw_priv); + kfree(class_dev); + *class_dev_p = NULL; +out: + *class_dev_p = class_dev; + return retval; +} +static void +fw_remove_class_device(struct class_device *class_dev) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + + class_device_remove_file(class_dev, &class_device_attr_loading); + sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data); + class_device_unregister(class_dev); +} + +/** + * request_firmware: - request firmware to hotplug and wait for it + * Description: + * @firmware will be used to return a firmware image by the name + * of @name for device @device. + * + * Should be called from user context where sleeping is allowed. + * + * @name will be use as $FIRMWARE in the hotplug environment and + * should be distinctive enough not to be confused with any other + * firmware image for this or any other device. + **/ +int +request_firmware(const struct firmware **firmware, const char *name, + struct device *device) +{ + struct class_device *class_dev; + struct firmware_priv *fw_priv; + int retval; + + if (!firmware) + return -EINVAL; + + *firmware = NULL; + + retval = fw_setup_class_device(&class_dev, name, device); + if (retval) + goto out; + + fw_priv = class_get_devdata(class_dev); + + if (loading_timeout) { + fw_priv->timeout.expires = jiffies + loading_timeout * HZ; + add_timer(&fw_priv->timeout); + } + + wait_for_completion(&fw_priv->completion); + + del_timer(&fw_priv->timeout); + fw_remove_class_device(class_dev); + + if (fw_priv->fw->size && !fw_priv->abort) { + *firmware = fw_priv->fw; + } else { + retval = -ENOENT; + vfree(fw_priv->fw->data); + kfree(fw_priv->fw); + } + kfree(fw_priv); +out: + return retval; +} + +/** + * release_firmware: - release the resource associated with a firmware image + **/ +void +release_firmware(const struct firmware *fw) +{ + if (fw) { + vfree(fw->data); + kfree(fw); + } +} + +/** + * register_firmware: - provide a firmware image for later usage + * + * Description: + * Make sure that @data will be available by requesting firmware @name. + * + * Note: This will not be possible until some kind of persistence + * is available. + **/ +void +register_firmware(const char *name, const u8 *data, size_t size) +{ + /* This is meaningless without firmware caching, so until we + * decide if firmware caching is reasonable just leave it as a + * noop */ +} + +/* Async support */ +struct firmware_work { + struct work_struct work; + struct module *module; + const char *name; + struct device *device; + void *context; + void (*cont)(const struct firmware *fw, void *context); +}; + +static void +request_firmware_work_func(void *arg) +{ + struct firmware_work *fw_work = arg; + const struct firmware *fw; + if (!arg) + return; + request_firmware(&fw, fw_work->name, fw_work->device); + fw_work->cont(fw, fw_work->context); + release_firmware(fw); + module_put(fw_work->module); + kfree(fw_work); +} + +/** + * request_firmware_nowait: + * + * Description: + * Asynchronous variant of request_firmware() for contexts where + * it is not possible to sleep. + * + * @cont will be called asynchronously when the firmware request is over. + * + * @context will be passed over to @cont. + * + * @fw may be %NULL if firmware request fails. + * + **/ +int +request_firmware_nowait( + struct module *module, + const char *name, struct device *device, void *context, + void (*cont)(const struct firmware *fw, void *context)) +{ + struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), + GFP_ATOMIC); + if (!fw_work) + return -ENOMEM; + if (!try_module_get(module)) { + kfree(fw_work); + return -EFAULT; + } + + *fw_work = (struct firmware_work) { + .module = module, + .name = name, + .device = device, + .context = context, + .cont = cont, + }; + INIT_WORK(&fw_work->work, request_firmware_work_func, fw_work); + + schedule_work(&fw_work->work); + return 0; +} + +static int __init +firmware_class_init(void) +{ + int error; + error = class_register(&firmware_class); + if (error) { + printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__); + } + error = class_create_file(&firmware_class, &class_attr_timeout); + if (error) { + printk(KERN_ERR "%s: class_create_file failed\n", + __FUNCTION__); + class_unregister(&firmware_class); + } + return error; + +} +static void __exit +firmware_class_exit(void) +{ + class_remove_file(&firmware_class, &class_attr_timeout); + class_unregister(&firmware_class); +} + +module_init(firmware_class_init); +module_exit(firmware_class_exit); + +EXPORT_SYMBOL(release_firmware); +EXPORT_SYMBOL(request_firmware); +EXPORT_SYMBOL(request_firmware_nowait); +EXPORT_SYMBOL(register_firmware); +EXPORT_SYMBOL(firmware_class); diff -urN linux-2.5.72-bk2/drivers/base/sys.c linux-2.5.72-bk3/drivers/base/sys.c --- linux-2.5.72-bk2/drivers/base/sys.c 2003-06-16 21:19:37.000000000 -0700 +++ linux-2.5.72-bk3/drivers/base/sys.c 2003-06-20 04:48:11.000000000 -0700 @@ -74,6 +74,8 @@ sysfs_remove_file(&s->kobj,&a->attr); } +EXPORT_SYMBOL(sysdev_create_file); +EXPORT_SYMBOL(sysdev_remove_file); /* * declare system_subsys @@ -171,6 +173,9 @@ /* Make sure the kset is set */ sysdev->kobj.kset = &cls->kset; + /* But make sure we point to the right type for sysfs translation */ + sysdev->kobj.ktype = &ktype_sysdev; + /* set the kobject name */ snprintf(sysdev->kobj.name,KOBJ_NAME_LEN,"%s%d", cls->kset.kobj.name,sysdev->id); @@ -218,9 +223,6 @@ if (drv->remove) drv->remove(sysdev); } - - list_del_init(&sysdev->entry); - up_write(&system_subsys.rwsem); kobject_unregister(&sysdev->kobj); diff -urN linux-2.5.72-bk2/drivers/isdn/act2000/Makefile linux-2.5.72-bk3/drivers/isdn/act2000/Makefile --- linux-2.5.72-bk2/drivers/isdn/act2000/Makefile 2003-06-16 21:20:07.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/act2000/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -6,4 +6,4 @@ # Multipart objects. -act2000-objs := module.o capi.o act2000_isa.o +act2000-y := module.o capi.o act2000_isa.o diff -urN linux-2.5.72-bk2/drivers/isdn/capi/Makefile linux-2.5.72-bk3/drivers/isdn/capi/Makefile --- linux-2.5.72-bk2/drivers/isdn/capi/Makefile 2003-06-16 21:20:01.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/capi/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -13,4 +13,3 @@ kernelcapi-y := kcapi.o capiutil.o capilib.o kernelcapi-$(CONFIG_PROC_FS) += kcapi_proc.o -kernelcapi-objs := $(kernelcapi-y) diff -urN linux-2.5.72-bk2/drivers/isdn/divert/Makefile linux-2.5.72-bk3/drivers/isdn/divert/Makefile --- linux-2.5.72-bk2/drivers/isdn/divert/Makefile 2003-06-16 21:20:19.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/divert/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -6,4 +6,4 @@ # Multipart objects. -dss1_divert-objs := isdn_divert.o divert_procfs.o divert_init.o +dss1_divert-y := isdn_divert.o divert_procfs.o divert_init.o diff -urN linux-2.5.72-bk2/drivers/isdn/eicon/Makefile linux-2.5.72-bk3/drivers/isdn/eicon/Makefile --- linux-2.5.72-bk2/drivers/isdn/eicon/Makefile 2003-06-16 21:19:47.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/eicon/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -7,15 +7,13 @@ # Multipart objects. -eicon-objs := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o \ - eicon_io.o -divas-objs := common.o idi.o bri.o pri.o log.o xlog.o kprintf.o fpga.o \ - fourbri.o lincfg.o linchr.o linsys.o linio.o Divas_mod.o +eicon-y := eicon_mod.o eicon_isa.o eicon_pci.o \ + eicon_idi.o eicon_io.o +eicon-$(CONFIG_ISDN_DRV_EICON_PCI) += common.o idi.o bri.o pri.o log.o \ + xlog.o kprintf.o fpga.o fourbri.o lincfg.o \ + linchr.o linsys.o linio.o -# Optional parts of multipart objects. +divas-y := common.o idi.o bri.o pri.o log.o xlog.o \ + kprintf.o fpga.o fourbri.o lincfg.o \ + linchr.o linsys.o linio.o Divas_mod.o -eicon-objs-$(CONFIG_ISDN_DRV_EICON_PCI) += common.o idi.o bri.o pri.o log.o \ - xlog.o kprintf.o fpga.o fourbri.o lincfg.o linchr.o \ - linsys.o linio.o - -eicon-objs += $(eicon-objs-y) diff -urN linux-2.5.72-bk2/drivers/isdn/eicon/eicon_isa.c linux-2.5.72-bk3/drivers/isdn/eicon/eicon_isa.c --- linux-2.5.72-bk2/drivers/isdn/eicon/eicon_isa.c 2003-06-16 21:19:41.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/eicon/eicon_isa.c 2003-06-20 04:48:11.000000000 -0700 @@ -123,7 +123,7 @@ int eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { int tmp; - int timeout; + unsigned long timeout; eicon_isa_codebuf cbuf; unsigned char *code; eicon_isa_boot *boot; @@ -300,7 +300,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { eicon_isa_boot *boot; int tmp; - int timeout; + unsigned long timeout; int j; eicon_isa_codebuf cbuf; unsigned char *code; diff -urN linux-2.5.72-bk2/drivers/isdn/hardware/avm/b1pci.c linux-2.5.72-bk3/drivers/isdn/hardware/avm/b1pci.c --- linux-2.5.72-bk2/drivers/isdn/hardware/avm/b1pci.c 2003-06-16 21:19:39.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/hardware/avm/b1pci.c 2003-06-20 04:48:11.000000000 -0700 @@ -111,7 +111,7 @@ cinfo->capi_ctrl.procinfo = b1pci_procinfo; cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; + cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { @@ -239,6 +239,7 @@ goto err_unmap; } + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "b1pciv4"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = b1dma_register_appl; @@ -249,7 +250,6 @@ cinfo->capi_ctrl.procinfo = b1pciv4_procinfo; cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { diff -urN linux-2.5.72-bk2/drivers/isdn/hardware/avm/b1pcmcia.c linux-2.5.72-bk3/drivers/isdn/hardware/avm/b1pcmcia.c --- linux-2.5.72-bk2/drivers/isdn/hardware/avm/b1pcmcia.c 2003-06-16 21:19:37.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/hardware/avm/b1pcmcia.c 2003-06-20 04:48:11.000000000 -0700 @@ -95,6 +95,7 @@ b1_reset(card->port); b1_getrevision(card); + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "b1pcmcia"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = b1_register_appl; @@ -105,7 +106,6 @@ cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo; cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { diff -urN linux-2.5.72-bk2/drivers/isdn/hardware/avm/t1pci.c linux-2.5.72-bk3/drivers/isdn/hardware/avm/t1pci.c --- linux-2.5.72-bk2/drivers/isdn/hardware/avm/t1pci.c 2003-06-16 21:19:41.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/hardware/avm/t1pci.c 2003-06-20 04:48:11.000000000 -0700 @@ -109,6 +109,7 @@ goto err_unmap; } + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "t1pci"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = b1dma_register_appl; @@ -119,7 +120,6 @@ cinfo->capi_ctrl.procinfo = t1pci_procinfo; cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { diff -urN linux-2.5.72-bk2/drivers/isdn/hardware/eicon/Makefile linux-2.5.72-bk3/drivers/isdn/hardware/eicon/Makefile --- linux-2.5.72-bk2/drivers/isdn/hardware/eicon/Makefile 2003-06-16 21:20:21.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/hardware/eicon/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -1,24 +1,24 @@ # Makefile for the Eicon DIVA ISDN drivers. +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DIVAS) += divadidd.o divas.o +obj-$(CONFIG_ISDN_DIVAS_MAINT) += diva_mnt.o +obj-$(CONFIG_ISDN_DIVAS_USERIDI) += diva_idi.o +obj-$(CONFIG_ISDN_DIVAS_DIVACAPI) += divacapi.o + # Multipart objects. -divas-objs := divasmain.o divasfunc.o di.o io.o istream.o diva.o dlist.o divasproc.o diva_dma.o -divacapi-objs := capimain.o capifunc.o message.o capidtmf.o -divadidd-objs := diva_didd.o diddfunc.o dadapter.o -diva_mnt-objs := divamnt.o mntfunc.o debug.o maintidi.o -diva_idi-objs := divasi.o idifunc.o um_idi.o dqueue.o dlist.o - -# Optional parts of multipart objects. - -divas-objs-$(CONFIG_ISDN_DIVAS_BRIPCI) += os_bri.o s_bri.o -divas-objs-$(CONFIG_ISDN_DIVAS_4BRIPCI) += os_4bri.o s_4bri.o -divas-objs-$(CONFIG_ISDN_DIVAS_PRIPCI) += os_pri.o s_pri.o +divas-y := divasmain.o divasfunc.o di.o io.o istream.o \ + diva.o dlist.o divasproc.o diva_dma.o +divas-$(CONFIG_ISDN_DIVAS_BRIPCI) += os_bri.o s_bri.o +divas-$(CONFIG_ISDN_DIVAS_4BRIPCI) += os_4bri.o s_4bri.o +divas-$(CONFIG_ISDN_DIVAS_PRIPCI) += os_pri.o s_pri.o -divas-objs += $(sort $(divas-objs-y)) +divacapi-y := capimain.o capifunc.o message.o capidtmf.o -# Each configuration option enables a list of files. +divadidd-y := diva_didd.o diddfunc.o dadapter.o + +diva_mnt-y := divamnt.o mntfunc.o debug.o maintidi.o -obj-$(CONFIG_ISDN_DIVAS) += divadidd.o divas.o -obj-$(CONFIG_ISDN_DIVAS_MAINT) += diva_mnt.o -obj-$(CONFIG_ISDN_DIVAS_USERIDI) += diva_idi.o -obj-$(CONFIG_ISDN_DIVAS_DIVACAPI) += divacapi.o +diva_idi-y := divasi.o idifunc.o um_idi.o dqueue.o dlist.o diff -urN linux-2.5.72-bk2/drivers/isdn/hisax/Makefile linux-2.5.72-bk3/drivers/isdn/hisax/Makefile --- linux-2.5.72-bk2/drivers/isdn/hisax/Makefile 2003-06-16 21:19:59.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/hisax/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -17,47 +17,45 @@ # Multipart objects. -hisax_st5481-objs := st5481_init.o st5481_usb.o st5481_d.o st5481_b.o \ - st5481_hdlc.o -hisax-objs := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \ - lmgr.o q931.o callc.o fsm.o cert.o +hisax_st5481-y := st5481_init.o st5481_usb.o st5481_d.o \ + st5481_b.o st5481_hdlc.o -# Optional parts of multipart objects. -hisax-objs-$(CONFIG_HISAX_EURO) += l3dss1.o -hisax-objs-$(CONFIG_HISAX_NI1) += l3ni1.o -hisax-objs-$(CONFIG_HISAX_1TR6) += l3_1tr6.o - -hisax-objs-$(CONFIG_HISAX_16_0) += teles0.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_16_3) += teles3.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_TELESPCI) += telespci.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_S0BOX) += s0box.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o -hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o ipac.o -hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipac.o ipacx.o -hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o ipac.o -hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o -hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o ipac.o isar.o -hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o -hisax-objs-$(CONFIG_HISAX_NETJET_U) += nj_u.o netjet.o icc.o -hisax-objs-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o -hisax-objs-$(CONFIG_HISAX_HFC_PCI) += hfc_pci.o -hisax-objs-$(CONFIG_HISAX_HFC_SX) += hfc_sx.o -hisax-objs-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o -hisax-objs-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o -hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o ipac.o -hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o ipac.o -hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o -hisax-objs-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o -#hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o - -hisax-objs += $(hisax-objs-y) +hisax-y := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \ + lmgr.o q931.o callc.o fsm.o cert.o +hisax-$(CONFIG_HISAX_EURO) += l3dss1.o +hisax-$(CONFIG_HISAX_NI1) += l3ni1.o +hisax-$(CONFIG_HISAX_1TR6) += l3_1tr6.o + +hisax-$(CONFIG_HISAX_16_0) += teles0.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_16_3) += teles3.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_TELESPCI) += telespci.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_S0BOX) += s0box.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o +hisax-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipac.o ipacx.o +hisax-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o +hisax-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o ipac.o \ + isar.o +hisax-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o +hisax-$(CONFIG_HISAX_NETJET_U) += nj_u.o netjet.o icc.o +hisax-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o +hisax-$(CONFIG_HISAX_HFC_PCI) += hfc_pci.o +hisax-$(CONFIG_HISAX_HFC_SX) += hfc_sx.o +hisax-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o +hisax-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o +hisax-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_W6692) += w6692.o +hisax-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o +#hisax-$(CONFIG_HISAX_TESTEMU) += testemu.o CERT := $(shell cd $(src); md5sum -c md5sums.asc > /dev/null 2> /dev/null ;echo $$?) CFLAGS_cert.o := -DCERTIFICATION=$(CERT) diff -urN linux-2.5.72-bk2/drivers/isdn/hisax/avma1_cs.c linux-2.5.72-bk3/drivers/isdn/hisax/avma1_cs.c --- linux-2.5.72-bk2/drivers/isdn/hisax/avma1_cs.c 2003-06-16 21:20:07.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/hisax/avma1_cs.c 2003-06-20 04:48:11.000000000 -0700 @@ -153,6 +153,8 @@ /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + if (!link) + return NULL; memset(link, 0, sizeof(struct dev_link_t)); link->release.function = &avma1cs_release; link->release.data = (u_long)link; @@ -186,6 +188,10 @@ /* Allocate space for private device-specific data */ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) { + kfree(link); + return NULL; + } memset(local, 0, sizeof(local_info_t)); link->priv = local; diff -urN linux-2.5.72-bk2/drivers/isdn/hysdn/Makefile linux-2.5.72-bk3/drivers/isdn/hysdn/Makefile --- linux-2.5.72-bk2/drivers/isdn/hysdn/Makefile 2003-06-16 21:20:28.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/hysdn/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -2,15 +2,10 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_HYSDN) += hysdn.o +obj-$(CONFIG_HYSDN) += hysdn.o # Multipart objects. -hysdn-objs := hysdn_procconf.o hysdn_proclog.o boardergo.o hysdn_boot.o \ - hysdn_sched.o hysdn_net.o hysdn_init.o - -# Optional parts of multipart objects. - -hysdn-objs-$(CONFIG_HYSDN_CAPI) += hycapi.o - -hysdn-objs += $(hysdn-objs-y) +hysdn-y := hysdn_procconf.o hysdn_proclog.o boardergo.o \ + hysdn_boot.o hysdn_sched.o hysdn_net.o hysdn_init.o +hysdn-$(CONFIG_HYSDN_CAPI) += hycapi.o diff -urN linux-2.5.72-bk2/drivers/isdn/hysdn/hysdn_proclog.c linux-2.5.72-bk3/drivers/isdn/hysdn/hysdn_proclog.c --- linux-2.5.72-bk2/drivers/isdn/hysdn/hysdn_proclog.c 2003-06-16 21:19:41.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/hysdn/hysdn_proclog.c 2003-06-20 04:48:11.000000000 -0700 @@ -98,7 +98,8 @@ { struct log_data *ib; struct procdata *pd = card->proclog; - int i, flags; + int i; + unsigned long flags; if (!pd) return; @@ -300,7 +301,8 @@ struct log_data *inf; struct procdata *pd; hysdn_card *card; - int flags, retval = 0; + int retval = 0; + unsigned long flags; lock_kernel(); diff -urN linux-2.5.72-bk2/drivers/isdn/i4l/Makefile linux-2.5.72-bk3/drivers/isdn/i4l/Makefile --- linux-2.5.72-bk2/drivers/isdn/i4l/Makefile 2003-06-16 21:19:47.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/i4l/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -2,25 +2,18 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_ISDN) += isdn.o -obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o +obj-$(CONFIG_ISDN) += isdn.o +obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o # Multipart objects. -isdn-objs := isdn_net_lib.o \ - isdn_fsm.o \ - isdn_tty.o isdn_v110.o \ - isdn_common.o \ - -# Optional parts of multipart objects. - -isdn-objs-$(CONFIG_ISDN_NET_SIMPLE) += isdn_net.o -isdn-objs-$(CONFIG_ISDN_NET_CISCO) += isdn_ciscohdlck.o -isdn-objs-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn_ppp_ccp.o -isdn-objs-$(CONFIG_ISDN_PPP_VJ) += isdn_ppp_vj.o -isdn-objs-$(CONFIG_ISDN_MPP) += isdn_ppp_mp.o -isdn-objs-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o -isdn-objs-$(CONFIG_ISDN_AUDIO) += isdn_audio.o -isdn-objs-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o - -isdn-objs += $(isdn-objs-y) +isdn-y := isdn_net_lib.o isdn_fsm.o isdn_tty.o \ + isdn_v110.o isdn_common.o +isdn-$(CONFIG_ISDN_NET_SIMPLE) += isdn_net.o +isdn-$(CONFIG_ISDN_NET_CISCO) += isdn_ciscohdlck.o +isdn-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn_ppp_ccp.o +isdn-$(CONFIG_ISDN_PPP_VJ) += isdn_ppp_vj.o +isdn-$(CONFIG_ISDN_MPP) += isdn_ppp_mp.o +isdn-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o +isdn-$(CONFIG_ISDN_AUDIO) += isdn_audio.o +isdn-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o diff -urN linux-2.5.72-bk2/drivers/isdn/i4l/isdn_bsdcomp.c linux-2.5.72-bk3/drivers/isdn/i4l/isdn_bsdcomp.c --- linux-2.5.72-bk2/drivers/isdn/i4l/isdn_bsdcomp.c 2003-06-16 21:20:22.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/i4l/isdn_bsdcomp.c 2003-06-20 04:48:11.000000000 -0700 @@ -300,7 +300,6 @@ * Finally release the structure itself. */ kfree (db); - MOD_DEC_USE_COUNT; } } @@ -355,8 +354,6 @@ return NULL; } - MOD_INC_USE_COUNT; - /* * If this is the compression buffer then there is no length data. * For decompression, the length information is needed as well. @@ -907,6 +904,7 @@ *************************************************************/ static struct isdn_ppp_compressor ippp_bsd_compress = { + .owner = THIS_MODULE, .num = CI_BSD_COMPRESS, .alloc = bsd_alloc, .free = bsd_free, diff -urN linux-2.5.72-bk2/drivers/isdn/i4l/isdn_ppp_ccp.c linux-2.5.72-bk3/drivers/isdn/i4l/isdn_ppp_ccp.c --- linux-2.5.72-bk2/drivers/isdn/i4l/isdn_ppp_ccp.c 2003-06-16 21:19:58.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/i4l/isdn_ppp_ccp.c 2003-06-20 04:48:11.000000000 -0700 @@ -259,11 +259,14 @@ { int id; - if (ccp->comp_stat) + if (ccp->comp_stat) { ccp->compressor->free(ccp->comp_stat); - if (ccp->decomp_stat) + module_put(ccp->compressor->owner); + } + if (ccp->decomp_stat) { ccp->decompressor->free(ccp->decomp_stat); - + module_put(ccp->decompressor->owner); + } for (id = 0; id < 256; id++) { if (ccp->reset->rs[id]) ippp_ccp_reset_free_state(ccp, id); @@ -553,13 +556,14 @@ } } -static struct isdn_ppp_compressor *ipc_head = NULL; +static LIST_HEAD(ipc_head); +static spinlock_t ipc_head_lock; int ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit, struct isdn_ppp_comp_data *data) { - struct isdn_ppp_compressor *ipc = ipc_head; + struct isdn_ppp_compressor *ipc; int ret; void *stat; int num = data->num; @@ -568,34 +572,48 @@ printk(KERN_DEBUG "[%d] Set %scompressor type %d\n", unit, data->flags & IPPP_COMP_FLAG_XMIT ? "" : "de", num); - for (ipc = ipc_head; ipc; ipc = ipc->next) { - if (ipc->num != num) - continue; - - stat = ipc->alloc(data); - if (!stat) { - printk(KERN_ERR "Can't alloc (de)compression!\n"); - break; - } - ret = ipc->init(stat, data, unit, 0); - if(!ret) { - printk(KERN_ERR "Can't init (de)compression!\n"); - ipc->free(stat); - break; + spin_lock(&ipc_head_lock); + list_for_each_entry(ipc, &ipc_head, list) { + if (ipc->num == num && + try_module_get(ipc->owner)) + goto found; + } + spin_unlock(&ipc_head_lock); + return -EINVAL; + + found: + spin_unlock(&ipc_head_lock); + + stat = ipc->alloc(data); + if (!stat) { + printk(KERN_ERR "Can't alloc (de)compression!\n"); + goto err; + } + ret = ipc->init(stat, data, unit, 0); + if(!ret) { + printk(KERN_ERR "Can't init (de)compression!\n"); + ipc->free(stat); + goto err; + } + if (data->flags & IPPP_COMP_FLAG_XMIT) { + if (ccp->comp_stat) { + ccp->compressor->free(ccp->comp_stat); + module_put(ccp->compressor->owner); } - if (data->flags & IPPP_COMP_FLAG_XMIT) { - if (ccp->comp_stat) - ccp->compressor->free(ccp->comp_stat); ccp->comp_stat = stat; ccp->compressor = ipc; - } else { - if (ccp->decomp_stat) - ccp->decompressor->free(ccp->decomp_stat); - ccp->decomp_stat = stat; - ccp->decompressor = ipc; + } else { + if (ccp->decomp_stat) { + ccp->decompressor->free(ccp->decomp_stat); + module_put(ccp->decompressor->owner); } - return 0; + ccp->decomp_stat = stat; + ccp->decompressor = ipc; } + return 0; + + err: + module_put(ipc->owner); return -EINVAL; } @@ -606,36 +624,34 @@ int i, j; memset(protos, 0, sizeof(unsigned long) * 8); - for (ipc = ipc_head; ipc; ipc = ipc->next) { + + spin_lock(&ipc_head_lock); + list_for_each_entry(ipc, &ipc_head, list) { j = ipc->num / (sizeof(long)*8); i = ipc->num % (sizeof(long)*8); if (j < 8) protos[j] |= 1 << i; } + spin_unlock(&ipc_head_lock); } int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc) { - ipc->next = ipc_head; - ipc->prev = NULL; - if (ipc_head) { - ipc_head->prev = ipc; - } - ipc_head = ipc; + spin_lock(&ipc_head_lock); + list_add_tail(&ipc->list, &ipc_head); + spin_unlock(&ipc_head_lock); + return 0; } int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc) { - if (ipc->prev) - ipc->prev->next = ipc->next; - else - ipc_head = ipc->next; - if (ipc->next) - ipc->next->prev = ipc->prev; - ipc->prev = ipc->next = NULL; + spin_lock(&ipc_head_lock); + list_del(&ipc->list); + spin_unlock(&ipc_head_lock); + return 0; } diff -urN linux-2.5.72-bk2/drivers/isdn/i4l/isdn_tty.c linux-2.5.72-bk3/drivers/isdn/i4l/isdn_tty.c --- linux-2.5.72-bk2/drivers/isdn/i4l/isdn_tty.c 2003-06-16 21:20:19.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/i4l/isdn_tty.c 2003-06-20 04:48:11.000000000 -0700 @@ -1983,7 +1983,7 @@ memcpy(m->pmsn, m->msn, ISDN_MSNLEN); memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN); if (dev->profd) - group_send_sig_info(SIGIO, SEND_SIG_PRIV, dev->profd); + kill_pg_info(SIGIO, SEND_SIG_PRIV, dev->profd->pgrp); } static struct tty_operations modem_ops = { @@ -2095,11 +2095,10 @@ #endif kfree(info->xmit_buf - 4); } - err_unregister_tty: - tty_unregister_driver(&isdn_mdm->tty_modem); + tty_unregister_driver(m->tty_modem); err: - put_tty_driver(&isdn_mdm->tty_modem); - isdn_mdm->tty_modem = NULL; + put_tty_driver(m->tty_modem); + m->tty_modem = NULL; return retval; } @@ -2118,9 +2117,9 @@ #endif kfree(info->xmit_buf - 4); } - tty_unregister_driver(&isdn_mdm->tty_modem); - put_tty_driver(&isdn_mdm->tty_modem); - isdn_mdm->tty_modem = NULL; + tty_unregister_driver(isdn_mdm.tty_modem); + put_tty_driver(isdn_mdm.tty_modem); + isdn_mdm.tty_modem = NULL; } /* diff -urN linux-2.5.72-bk2/drivers/isdn/i4l/isdn_ttyfax.c linux-2.5.72-bk3/drivers/isdn/i4l/isdn_ttyfax.c --- linux-2.5.72-bk2/drivers/isdn/i4l/isdn_ttyfax.c 2003-06-16 21:19:39.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/i4l/isdn_ttyfax.c 2003-06-20 04:48:11.000000000 -0700 @@ -303,7 +303,7 @@ isdn_ctrl c; int par; struct isdn_slot *slot; - long flags; + unsigned long flags; for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++) if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2)) diff -urN linux-2.5.72-bk2/drivers/isdn/isdnloop/Makefile linux-2.5.72-bk3/drivers/isdn/isdnloop/Makefile --- linux-2.5.72-bk2/drivers/isdn/isdnloop/Makefile 2003-06-16 21:19:39.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/isdnloop/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -1,6 +1,4 @@ -# # Makefile for the isdnloop ISDN device driver -# # Each configuration option enables a list of files. diff -urN linux-2.5.72-bk2/drivers/isdn/pcbit/Makefile linux-2.5.72-bk3/drivers/isdn/pcbit/Makefile --- linux-2.5.72-bk2/drivers/isdn/pcbit/Makefile 2003-06-16 21:20:22.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/pcbit/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -6,4 +6,4 @@ # Multipart objects. -pcbit-objs := module.o edss1.o drv.o layer2.o capi.o callbacks.o +pcbit-y := module.o edss1.o drv.o layer2.o capi.o callbacks.o diff -urN linux-2.5.72-bk2/drivers/isdn/sc/Makefile linux-2.5.72-bk3/drivers/isdn/sc/Makefile --- linux-2.5.72-bk2/drivers/isdn/sc/Makefile 2003-06-16 21:19:46.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/sc/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -6,5 +6,5 @@ # Multipart objects. -sc-objs := shmem.o init.o debug.o packet.o command.o event.o \ - ioctl.o interrupt.o message.o timer.o +sc-y := shmem.o init.o debug.o packet.o command.o event.o \ + ioctl.o interrupt.o message.o timer.o diff -urN linux-2.5.72-bk2/drivers/isdn/tpam/Makefile linux-2.5.72-bk3/drivers/isdn/tpam/Makefile --- linux-2.5.72-bk2/drivers/isdn/tpam/Makefile 2003-06-16 21:19:39.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/tpam/Makefile 2003-06-20 04:48:11.000000000 -0700 @@ -6,5 +6,6 @@ # Multipart objects. -tpam-objs := tpam_main.o tpam_nco.o tpam_memory.o tpam_commands.o \ - tpam_queues.o tpam_hdlc.o tpam_crcpc.o +tpam-y := tpam_main.o tpam_nco.o tpam_memory.o \ + tpam_commands.o tpam_queues.o tpam_hdlc.o \ + tpam_crcpc.o diff -urN linux-2.5.72-bk2/drivers/isdn/tpam/tpam_queues.c linux-2.5.72-bk3/drivers/isdn/tpam/tpam_queues.c --- linux-2.5.72-bk2/drivers/isdn/tpam/tpam_queues.c 2003-06-16 21:19:39.000000000 -0700 +++ linux-2.5.72-bk3/drivers/isdn/tpam/tpam_queues.c 2003-06-20 04:48:11.000000000 -0700 @@ -145,6 +145,7 @@ do { hpic = readl(card->bar0 + TPAM_HPIC_REGISTER); if (waiting_too_long++ > 0xfffffff) { + kfree_skb(skb); spin_unlock(&card->lock); printk(KERN_ERR "TurboPAM(tpam_irq): " "waiting too long...\n"); diff -urN linux-2.5.72-bk2/drivers/net/myri_sbus.c linux-2.5.72-bk3/drivers/net/myri_sbus.c --- linux-2.5.72-bk2/drivers/net/myri_sbus.c 2003-06-16 21:19:40.000000000 -0700 +++ linux-2.5.72-bk3/drivers/net/myri_sbus.c 2003-06-20 04:48:11.000000000 -0700 @@ -766,10 +766,14 @@ int myri_header_cache(struct neighbour *neigh, struct hh_cache *hh) { unsigned short type = hh->hh_type; - unsigned char *pad = (unsigned char *) hh->hh_data; - struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN); + unsigned char *pad; + struct ethhdr *eth; struct net_device *dev = neigh->dev; + pad = ((unsigned char *) hh->hh_data) + + HH_DATA_OFF(sizeof(*eth) + MYRI_PAD_LEN); + eth = (struct ethhdr *) (pad + MYRI_PAD_LEN); + if (type == __constant_htons(ETH_P_802_3)) return -1; @@ -788,7 +792,8 @@ /* Called by Address Resolution module to notify changes in address. */ void myri_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr) { - memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len); + memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)), + haddr, dev->addr_len); } static int myri_change_mtu(struct net_device *dev, int new_mtu) diff -urN linux-2.5.72-bk2/drivers/net/plip.c linux-2.5.72-bk3/drivers/net/plip.c --- linux-2.5.72-bk2/drivers/net/plip.c 2003-06-16 21:20:27.000000000 -0700 +++ linux-2.5.72-bk3/drivers/net/plip.c 2003-06-20 04:48:11.000000000 -0700 @@ -1078,7 +1078,10 @@ if ((ret = nl->orig_hard_header_cache(neigh, hh)) == 0) { - struct ethhdr *eth = (struct ethhdr*)(((u8*)hh->hh_data) + 2); + struct ethhdr *eth; + + eth = (struct ethhdr*)(((u8*)hh->hh_data) + + HH_DATA_OFF(sizeof(*eth))); plip_rewrite_address (neigh->dev, eth); } diff -urN linux-2.5.72-bk2/drivers/net/pppoe.c linux-2.5.72-bk3/drivers/net/pppoe.c --- linux-2.5.72-bk2/drivers/net/pppoe.c 2003-06-16 21:20:06.000000000 -0700 +++ linux-2.5.72-bk3/drivers/net/pppoe.c 2003-06-20 04:48:11.000000000 -0700 @@ -1061,6 +1061,7 @@ } static struct file_operations pppoe_seq_fops = { + .owner = THIS_MODULE, .open = pppoe_seq_open, .read = seq_read, .llseek = seq_lseek, diff -urN linux-2.5.72-bk2/drivers/pnp/base.h linux-2.5.72-bk3/drivers/pnp/base.h --- linux-2.5.72-bk2/drivers/pnp/base.h 2003-06-16 21:19:42.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/base.h 2003-06-20 04:48:11.000000000 -0700 @@ -4,29 +4,11 @@ int pnp_interface_attach_device(struct pnp_dev *dev); void pnp_name_device(struct pnp_dev *dev); void pnp_fixup_device(struct pnp_dev *dev); -void pnp_free_resources(struct pnp_resources *resources); +void pnp_free_option(struct pnp_option *option); int __pnp_add_device(struct pnp_dev *dev); void __pnp_remove_device(struct pnp_dev *dev); -/* resource conflict types */ -#define CONFLICT_TYPE_NONE 0x0000 /* there are no conflicts, other than those in the link */ -#define CONFLICT_TYPE_RESERVED 0x0001 /* the resource requested was reserved */ -#define CONFLICT_TYPE_IN_USE 0x0002 /* there is a conflict because the resource is in use */ -#define CONFLICT_TYPE_PCI 0x0004 /* there is a conflict with a pci device */ -#define CONFLICT_TYPE_INVALID 0x0008 /* the resource requested is invalid */ -#define CONFLICT_TYPE_INTERNAL 0x0010 /* resources within the device conflict with each ohter */ -#define CONFLICT_TYPE_PNP_WARM 0x0020 /* there is a conflict with a pnp device that is active */ -#define CONFLICT_TYPE_PNP_COLD 0x0040 /* there is a conflict with a pnp device that is disabled */ - -/* conflict search modes */ -#define SEARCH_WARM 1 /* check for conflicts with active devices */ -#define SEARCH_COLD 0 /* check for conflicts with disabled devices */ - -struct pnp_dev * pnp_check_port_conflicts(struct pnp_dev * dev, int idx, int mode); int pnp_check_port(struct pnp_dev * dev, int idx); -struct pnp_dev * pnp_check_mem_conflicts(struct pnp_dev * dev, int idx, int mode); int pnp_check_mem(struct pnp_dev * dev, int idx); -struct pnp_dev * pnp_check_irq_conflicts(struct pnp_dev * dev, int idx, int mode); int pnp_check_irq(struct pnp_dev * dev, int idx); -struct pnp_dev * pnp_check_dma_conflicts(struct pnp_dev * dev, int idx, int mode); int pnp_check_dma(struct pnp_dev * dev, int idx); diff -urN linux-2.5.72-bk2/drivers/pnp/core.c linux-2.5.72-bk3/drivers/pnp/core.c --- linux-2.5.72-bk2/drivers/pnp/core.c 2003-06-16 21:19:42.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/core.c 2003-06-20 04:48:11.000000000 -0700 @@ -104,8 +104,8 @@ static void pnp_release_device(struct device *dmdev) { struct pnp_dev * dev = to_pnp_dev(dmdev); - if (dev->possible) - pnp_free_resources(dev->possible); + pnp_free_option(dev->independent); + pnp_free_option(dev->dependent); pnp_free_ids(dev); kfree(dev); } @@ -122,7 +122,7 @@ list_add_tail(&dev->global_list, &pnp_global); list_add_tail(&dev->protocol_list, &dev->protocol->devices); spin_unlock(&pnp_lock); - pnp_auto_config_dev(dev); + ret = device_register(&dev->dev); if (ret == 0) pnp_interface_attach_device(dev); diff -urN linux-2.5.72-bk2/drivers/pnp/interface.c linux-2.5.72-bk3/drivers/pnp/interface.c --- linux-2.5.72-bk2/drivers/pnp/interface.c 2003-06-16 21:19:41.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/interface.c 2003-06-20 04:48:11.000000000 -0700 @@ -168,7 +168,8 @@ pnp_printf(buffer, ", %s\n", s); } -static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct pnp_resources *res, int dep) +static void pnp_print_option(pnp_info_buffer_t *buffer, char *space, + struct pnp_option *option, int dep) { char *s; struct pnp_port *port; @@ -176,49 +177,55 @@ struct pnp_dma *dma; struct pnp_mem *mem; - switch (res->priority) { - case PNP_RES_PRIORITY_PREFERRED: - s = "preferred"; - break; - case PNP_RES_PRIORITY_ACCEPTABLE: - s = "acceptable"; - break; - case PNP_RES_PRIORITY_FUNCTIONAL: - s = "functional"; - break; - default: - s = "invalid"; - } - if (dep > 0) + if (dep) { + switch (option->priority) { + case PNP_RES_PRIORITY_PREFERRED: + s = "preferred"; + break; + case PNP_RES_PRIORITY_ACCEPTABLE: + s = "acceptable"; + break; + case PNP_RES_PRIORITY_FUNCTIONAL: + s = "functional"; + break; + default: + s = "invalid"; + } pnp_printf(buffer, "Dependent: %02i - Priority %s\n",dep, s); - for (port = res->port; port; port = port->next) + } + + for (port = option->port; port; port = port->next) pnp_print_port(buffer, space, port); - for (irq = res->irq; irq; irq = irq->next) + for (irq = option->irq; irq; irq = irq->next) pnp_print_irq(buffer, space, irq); - for (dma = res->dma; dma; dma = dma->next) + for (dma = option->dma; dma; dma = dma->next) pnp_print_dma(buffer, space, dma); - for (mem = res->mem; mem; mem = mem->next) + for (mem = option->mem; mem; mem = mem->next) pnp_print_mem(buffer, space, mem); } -static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf) + +static ssize_t pnp_show_options(struct device *dmdev, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); - struct pnp_resources * res = dev->possible; - int ret, dep = 0; + struct pnp_option * independent = dev->independent; + struct pnp_option * dependent = dev->dependent; + int ret, dep = 1; + pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t)); if (!buffer) return -ENOMEM; + buffer->len = PAGE_SIZE; buffer->buffer = buf; buffer->curr = buffer->buffer; - while (res){ - if (dep == 0) - pnp_print_resources(buffer, "", res, dep); - else - pnp_print_resources(buffer, " ", res, dep); - res = res->dep; + if (independent) + pnp_print_option(buffer, "", independent, 0); + + while (dependent){ + pnp_print_option(buffer, " ", dependent, dep); + dependent = dependent->next; dep++; } ret = (buffer->curr - buf); @@ -226,97 +233,8 @@ return ret; } -static DEVICE_ATTR(possible,S_IRUGO,pnp_show_possible_resources,NULL); - -static void pnp_print_conflict_node(pnp_info_buffer_t *buffer, struct pnp_dev * dev) -{ - if (!dev) - return; - pnp_printf(buffer, "'%s'.\n", dev->dev.bus_id); -} - -static void pnp_print_conflict_desc(pnp_info_buffer_t *buffer, int conflict) -{ - if (!conflict) - return; - pnp_printf(buffer, " Conflict Detected: %2x - ", conflict); - switch (conflict) { - case CONFLICT_TYPE_RESERVED: - pnp_printf(buffer, "manually reserved.\n"); - break; - - case CONFLICT_TYPE_IN_USE: - pnp_printf(buffer, "currently in use.\n"); - break; - - case CONFLICT_TYPE_PCI: - pnp_printf(buffer, "PCI device.\n"); - break; - - case CONFLICT_TYPE_INVALID: - pnp_printf(buffer, "invalid.\n"); - break; - - case CONFLICT_TYPE_INTERNAL: - pnp_printf(buffer, "another resource on this device.\n"); - break; - - case CONFLICT_TYPE_PNP_WARM: - pnp_printf(buffer, "active PnP device "); - break; - - case CONFLICT_TYPE_PNP_COLD: - pnp_printf(buffer, "disabled PnP device "); - break; - default: - pnp_printf(buffer, "Unknown conflict.\n"); - break; - } -} +static DEVICE_ATTR(options,S_IRUGO,pnp_show_options,NULL); -static void pnp_print_conflict(pnp_info_buffer_t *buffer, struct pnp_dev * dev, int idx, int type) -{ - struct pnp_dev * cdev, * wdev = NULL; - int conflict; - switch (type) { - case IORESOURCE_IO: - conflict = pnp_check_port(dev, idx); - if (conflict == CONFLICT_TYPE_PNP_WARM) - wdev = pnp_check_port_conflicts(dev, idx, SEARCH_WARM); - cdev = pnp_check_port_conflicts(dev, idx, SEARCH_COLD); - break; - case IORESOURCE_MEM: - conflict = pnp_check_mem(dev, idx); - if (conflict == CONFLICT_TYPE_PNP_WARM) - wdev = pnp_check_mem_conflicts(dev, idx, SEARCH_WARM); - cdev = pnp_check_mem_conflicts(dev, idx, SEARCH_COLD); - break; - case IORESOURCE_IRQ: - conflict = pnp_check_irq(dev, idx); - if (conflict == CONFLICT_TYPE_PNP_WARM) - wdev = pnp_check_irq_conflicts(dev, idx, SEARCH_WARM); - cdev = pnp_check_irq_conflicts(dev, idx, SEARCH_COLD); - break; - case IORESOURCE_DMA: - conflict = pnp_check_dma(dev, idx); - if (conflict == CONFLICT_TYPE_PNP_WARM) - wdev = pnp_check_dma_conflicts(dev, idx, SEARCH_WARM); - cdev = pnp_check_dma_conflicts(dev, idx, SEARCH_COLD); - break; - default: - return; - } - - pnp_print_conflict_desc(buffer, conflict); - - if (wdev) - pnp_print_conflict_node(buffer, wdev); - - if (cdev) { - pnp_print_conflict_desc(buffer, CONFLICT_TYPE_PNP_COLD); - pnp_print_conflict_node(buffer, cdev); - } -} static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) { @@ -332,12 +250,6 @@ buffer->buffer = buf; buffer->curr = buffer->buffer; - pnp_printf(buffer,"mode = "); - if (dev->config_mode & PNP_CONFIG_MANUAL) - pnp_printf(buffer,"manual\n"); - else - pnp_printf(buffer,"auto\n"); - pnp_printf(buffer,"state = "); if (dev->active) pnp_printf(buffer,"active\n"); @@ -350,7 +262,6 @@ pnp_printf(buffer," 0x%lx-0x%lx \n", pnp_port_start(dev, i), pnp_port_end(dev, i)); - pnp_print_conflict(buffer, dev, i, IORESOURCE_IO); } } for (i = 0; i < PNP_MAX_MEM; i++) { @@ -359,21 +270,18 @@ pnp_printf(buffer," 0x%lx-0x%lx \n", pnp_mem_start(dev, i), pnp_mem_end(dev, i)); - pnp_print_conflict(buffer, dev, i, IORESOURCE_MEM); } } for (i = 0; i < PNP_MAX_IRQ; i++) { if (pnp_irq_valid(dev, i)) { pnp_printf(buffer,"irq"); pnp_printf(buffer," %ld \n", pnp_irq(dev, i)); - pnp_print_conflict(buffer, dev, i, IORESOURCE_IRQ); } } for (i = 0; i < PNP_MAX_DMA; i++) { if (pnp_dma_valid(dev, i)) { pnp_printf(buffer,"dma"); pnp_printf(buffer," %ld \n", pnp_dma(dev, i)); - pnp_print_conflict(buffer, dev, i, IORESOURCE_DMA); } } ret = (buffer->curr - buf); @@ -381,7 +289,7 @@ return ret; } -extern int pnp_resolve_conflicts(struct pnp_dev *dev); +extern struct semaphore pnp_res_mutex; static ssize_t pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count) @@ -390,6 +298,12 @@ char *buf = (void *)ubuf; int retval = 0; + if (dev->status & PNP_ATTACHED) { + retval = -EBUSY; + pnp_info("Device %s cannot be configured because it is in use.", dev->dev.bus_id); + goto done; + } + while (isspace(*buf)) ++buf; if (!strnicmp(buf,"disable",7)) { @@ -400,41 +314,30 @@ retval = pnp_activate_dev(dev); goto done; } - if (!strnicmp(buf,"reset",5)) { - if (!dev->active) - goto done; - retval = pnp_disable_dev(dev); - if (retval) + if (!strnicmp(buf,"fill",4)) { + if (dev->active) goto done; - retval = pnp_activate_dev(dev); + retval = pnp_auto_config_dev(dev); goto done; } if (!strnicmp(buf,"auto",4)) { if (dev->active) goto done; + pnp_init_resources(&dev->res); retval = pnp_auto_config_dev(dev); goto done; } if (!strnicmp(buf,"clear",5)) { if (dev->active) goto done; - spin_lock(&pnp_lock); - dev->config_mode = PNP_CONFIG_MANUAL; - pnp_init_resource_table(&dev->res); - if (dev->rule) - dev->rule->depnum = 0; - spin_unlock(&pnp_lock); - goto done; - } - if (!strnicmp(buf,"resolve",7)) { - retval = pnp_resolve_conflicts(dev); + pnp_init_resources(&dev->res); goto done; } if (!strnicmp(buf,"get",3)) { - spin_lock(&pnp_lock); + down(&pnp_res_mutex); if (pnp_can_read(dev)) dev->protocol->get(dev, &dev->res); - spin_unlock(&pnp_lock); + up(&pnp_res_mutex); goto done; } if (!strnicmp(buf,"set",3)) { @@ -442,9 +345,8 @@ if (dev->active) goto done; buf += 3; - spin_lock(&pnp_lock); - dev->config_mode = PNP_CONFIG_MANUAL; - pnp_init_resource_table(&dev->res); + pnp_init_resources(&dev->res); + down(&pnp_res_mutex); while (1) { while (isspace(*buf)) ++buf; @@ -514,7 +416,7 @@ } break; } - spin_unlock(&pnp_lock); + up(&pnp_res_mutex); goto done; } done: @@ -543,7 +445,7 @@ int pnp_interface_attach_device(struct pnp_dev *dev) { - device_create_file(&dev->dev,&dev_attr_possible); + device_create_file(&dev->dev,&dev_attr_options); device_create_file(&dev->dev,&dev_attr_resources); device_create_file(&dev->dev,&dev_attr_id); return 0; diff -urN linux-2.5.72-bk2/drivers/pnp/isapnp/core.c linux-2.5.72-bk3/drivers/pnp/isapnp/core.c --- linux-2.5.72-bk2/drivers/pnp/isapnp/core.c 2003-06-16 21:20:02.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/isapnp/core.c 2003-06-20 04:48:11.000000000 -0700 @@ -31,6 +31,7 @@ * 2002-06-06 Made the use of dma channel 0 configurable * Gerald Teschl * 2002-10-06 Ported to PnP Layer - Adam Belay + * 2003-08-11 Resource Management Updates - Adam Belay */ #include @@ -54,7 +55,6 @@ int isapnp_disable; /* Disable ISA PnP */ int isapnp_rdp; /* Read Data Port */ int isapnp_reset = 1; /* reset all PnP cards (deactivate) */ -int isapnp_skip_pci_scan; /* skip PCI resource scanning */ int isapnp_verbose = 1; /* verbose mode */ MODULE_AUTHOR("Jaroslav Kysela "); @@ -66,8 +66,6 @@ MODULE_PARM(isapnp_reset, "i"); MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards"); MODULE_PARM(isapnp_allow_dma0, "i"); -MODULE_PARM(isapnp_skip_pci_scan, "i"); -MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning"); MODULE_PARM(isapnp_verbose, "i"); MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode"); MODULE_LICENSE("GPL"); @@ -460,6 +458,7 @@ dev->capabilities |= PNP_READ; dev->capabilities |= PNP_WRITE; dev->capabilities |= PNP_DISABLE; + pnp_init_resources(&dev->res); return dev; } @@ -468,8 +467,8 @@ * Add IRQ resource to resources list. */ -static void __init isapnp_add_irq_resource(struct pnp_dev *dev, - int depnum, int size) +static void __init isapnp_parse_irq_resource(struct pnp_option *option, + int size) { unsigned char tmp[3]; struct pnp_irq *irq; @@ -483,7 +482,7 @@ irq->flags = tmp[2]; else irq->flags = IORESOURCE_IRQ_HIGHEDGE; - pnp_add_irq_resource(dev, depnum, irq); + pnp_register_irq_resource(option, irq); return; } @@ -491,8 +490,8 @@ * Add DMA resource to resources list. */ -static void __init isapnp_add_dma_resource(struct pnp_dev *dev, - int depnum, int size) +static void __init isapnp_parse_dma_resource(struct pnp_option *option, + int size) { unsigned char tmp[2]; struct pnp_dma *dma; @@ -503,7 +502,7 @@ return; dma->map = tmp[0]; dma->flags = tmp[1]; - pnp_add_dma_resource(dev, depnum, dma); + pnp_register_dma_resource(option, dma); return; } @@ -511,8 +510,8 @@ * Add port resource to resources list. */ -static void __init isapnp_add_port_resource(struct pnp_dev *dev, - int depnum, int size) +static void __init isapnp_parse_port_resource(struct pnp_option *option, + int size) { unsigned char tmp[7]; struct pnp_port *port; @@ -526,7 +525,7 @@ port->align = tmp[5]; port->size = tmp[6]; port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_add_port_resource(dev,depnum,port); + pnp_register_port_resource(option,port); return; } @@ -534,8 +533,8 @@ * Add fixed port resource to resources list. */ -static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev, - int depnum, int size) +static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, + int size) { unsigned char tmp[3]; struct pnp_port *port; @@ -548,7 +547,7 @@ port->size = tmp[2]; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_add_port_resource(dev,depnum,port); + pnp_register_port_resource(option,port); return; } @@ -556,8 +555,8 @@ * Add memory resource to resources list. */ -static void __init isapnp_add_mem_resource(struct pnp_dev *dev, - int depnum, int size) +static void __init isapnp_parse_mem_resource(struct pnp_option *option, + int size) { unsigned char tmp[9]; struct pnp_mem *mem; @@ -571,7 +570,7 @@ mem->align = (tmp[6] << 8) | tmp[5]; mem->size = ((tmp[8] << 8) | tmp[7]) << 8; mem->flags = tmp[0]; - pnp_add_mem_resource(dev,depnum,mem); + pnp_register_mem_resource(option,mem); return; } @@ -579,8 +578,8 @@ * Add 32-bit memory resource to resources list. */ -static void __init isapnp_add_mem32_resource(struct pnp_dev *dev, - int depnum, int size) +static void __init isapnp_parse_mem32_resource(struct pnp_option *option, + int size) { unsigned char tmp[17]; struct pnp_mem *mem; @@ -594,15 +593,15 @@ mem->align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; mem->size = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; mem->flags = tmp[0]; - pnp_add_mem_resource(dev,depnum,mem); + pnp_register_mem_resource(option,mem); } /* * Add 32-bit fixed memory resource to resources list. */ -static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev, - int depnum, int size) +static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, + int size) { unsigned char tmp[9]; struct pnp_mem *mem; @@ -615,14 +614,14 @@ mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; mem->align = 0; mem->flags = tmp[0]; - pnp_add_mem_resource(dev,depnum,mem); + pnp_register_mem_resource(option,mem); } /* * Parse card name for ISA PnP device. */ - -static void __init + +static void __init isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) { if (name[0] == '\0') { @@ -634,7 +633,7 @@ /* clean whitespace from end of string */ while (size1 > 0 && name[--size1] == ' ') name[size1] = '\0'; - } + } } /* @@ -644,14 +643,17 @@ static int __init isapnp_create_device(struct pnp_card *card, unsigned short size) { - int number = 0, skip = 0, depnum = 0, dependent = 0, compat = 0; + int number = 0, skip = 0, priority = 0, compat = 0; unsigned char type, tmp[17]; + struct pnp_option *option; struct pnp_dev *dev; if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; - if (pnp_build_resource(dev, 0) == NULL) + option = pnp_register_independent_option(dev); + if (!option) return 1; pnp_add_card_device(card,dev); + while (1) { if (isapnp_read_tag(&type, &size)<0) return 1; @@ -662,15 +664,16 @@ if (size >= 5 && size <= 6) { if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; - pnp_build_resource(dev,0); - pnp_add_card_device(card,dev); size = 0; skip = 0; + option = pnp_register_independent_option(dev); + if (!option) + return 1; + pnp_add_card_device(card,dev); } else { skip = 1; } - dependent = 0; - depnum = 0; + priority = 0; compat = 0; break; case _STAG_COMPATDEVID: @@ -684,43 +687,43 @@ case _STAG_IRQ: if (size < 2 || size > 3) goto __skip; - isapnp_add_irq_resource(dev, depnum, size); + isapnp_parse_irq_resource(option, size); size = 0; break; case _STAG_DMA: if (size != 2) goto __skip; - isapnp_add_dma_resource(dev, depnum, size); + isapnp_parse_dma_resource(option, size); size = 0; break; case _STAG_STARTDEP: if (size > 1) goto __skip; - dependent = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; + priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; if (size > 0) { isapnp_peek(tmp, size); - dependent = 0x100 | tmp[0]; + priority = 0x100 | tmp[0]; size = 0; } - pnp_build_resource(dev,dependent); - depnum = pnp_get_max_depnum(dev); + option = pnp_register_dependent_option(dev,priority); + if (!option) + return 1; break; case _STAG_ENDDEP: if (size != 0) goto __skip; - dependent = 0; - depnum = 0; + priority = 0; break; case _STAG_IOPORT: if (size != 7) goto __skip; - isapnp_add_port_resource(dev, depnum, size); + isapnp_parse_port_resource(option, size); size = 0; break; case _STAG_FIXEDIO: if (size != 3) goto __skip; - isapnp_add_fixed_port_resource(dev, depnum, size); + isapnp_parse_fixed_port_resource(option, size); size = 0; break; case _STAG_VENDOR: @@ -728,7 +731,7 @@ case _LTAG_MEMRANGE: if (size != 9) goto __skip; - isapnp_add_mem_resource(dev, depnum, size); + isapnp_parse_mem_resource(option, size); size = 0; break; case _LTAG_ANSISTR: @@ -743,13 +746,13 @@ case _LTAG_MEM32RANGE: if (size != 17) goto __skip; - isapnp_add_mem32_resource(dev, depnum, size); + isapnp_parse_mem32_resource(option, size); size = 0; break; case _LTAG_FIXEDMEM32RANGE: if (size != 9) goto __skip; - isapnp_add_fixed_mem32_resource(dev, depnum, size); + isapnp_parse_fixed_mem32_resource(option, size); size = 0; break; case _STAG_END: @@ -859,63 +862,6 @@ pnp_add_card_id(id,card); } - -static int isapnp_parse_current_resources(struct pnp_dev *dev, struct pnp_resource_table * res) -{ - int tmp, ret; - struct pnp_rule_table rule; - if (dev->rule) - rule = *dev->rule; - else { - if (!pnp_generate_rule(dev,1,&rule)) - return -EINVAL; - } - - dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); - if (dev->active) { - for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { - ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); - if (!ret) - continue; - res->port_resource[tmp].start = ret; - if (rule.port[tmp]) - res->port_resource[tmp].end = ret + rule.port[tmp]->size - 1; - else - res->port_resource[tmp].end = ret + 1; /* all we can do is assume 1 :-( */ - res->port_resource[tmp].flags = IORESOURCE_IO; - } - for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { - ret = isapnp_read_dword(ISAPNP_CFG_MEM + (tmp << 3)); - if (!ret) - continue; - res->mem_resource[tmp].start = ret; - if (rule.mem[tmp]) - res->mem_resource[tmp].end = ret + rule.mem[tmp]->size - 1; - else - res->mem_resource[tmp].end = ret + 1; /* all we can do is assume 1 :-( */ - res->mem_resource[tmp].flags = IORESOURCE_MEM; - } - for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { - ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8); - if (!ret) - continue; - res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret; - res->irq_resource[tmp].flags = IORESOURCE_IRQ; - } - for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { - ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); - if (ret == 4) - continue; - if (rule.dma[tmp]) { /* some isapnp systems forget to set this to 4 so we have to check */ - res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret; - res->dma_resource[tmp].flags = IORESOURCE_DMA; - } - } - } - return 0; -} - - /* * Build device list for all present ISA PnP devices. */ @@ -925,7 +871,6 @@ int csn; unsigned char header[9], checksum; struct pnp_card *card; - struct pnp_dev *dev; isapnp_wait(); isapnp_key(); @@ -959,13 +904,6 @@ card->checksum = isapnp_checksum_value; card->protocol = &isapnp_protocol; - /* read the current resource data */ - card_for_each_dev(card,dev) { - isapnp_device(dev->number); - pnp_init_resource_table(&dev->res); - isapnp_parse_current_resources(dev, &dev->res); - } - pnp_add_card(card); } isapnp_wait(); @@ -1041,12 +979,50 @@ EXPORT_SYMBOL(isapnp_wake); EXPORT_SYMBOL(isapnp_device); +static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res) +{ + int tmp, ret; + + dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); + if (dev->active) { + for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { + ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); + if (!ret) + continue; + res->port_resource[tmp].start = ret; + res->port_resource[tmp].flags = IORESOURCE_IO; + } + for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { + ret = isapnp_read_dword(ISAPNP_CFG_MEM + (tmp << 3)); + if (!ret) + continue; + res->mem_resource[tmp].start = ret; + res->mem_resource[tmp].flags = IORESOURCE_MEM; + } + for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { + ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8); + if (!ret) + continue; + res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret; + res->irq_resource[tmp].flags = IORESOURCE_IRQ; + } + for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { + ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); + if (ret == 4) + continue; + res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret; + res->dma_resource[tmp].flags = IORESOURCE_DMA; + } + } + return 0; +} + static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * res) { int ret; - pnp_init_resource_table(res); + pnp_init_resources(res); isapnp_cfg_begin(dev->card->number, dev->number); - ret = isapnp_parse_current_resources(dev, res); + ret = isapnp_read_resources(dev, res); isapnp_cfg_end(); return ret; } @@ -1196,7 +1172,6 @@ { (void)((get_option(&str,&isapnp_rdp) == 2) && (get_option(&str,&isapnp_reset) == 2) && - (get_option(&str,&isapnp_skip_pci_scan) == 2) && (get_option(&str,&isapnp_verbose) == 2)); return 1; } diff -urN linux-2.5.72-bk2/drivers/pnp/manager.c linux-2.5.72-bk3/drivers/pnp/manager.c --- linux-2.5.72-bk2/drivers/pnp/manager.c 2003-06-16 21:20:25.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/manager.c 2003-06-20 04:48:11.000000000 -0700 @@ -1,6 +1,7 @@ /* * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices * + * based on isapnp.c resource management (c) Jaroslav Kysela * Copyright 2003 Adam Belay * */ @@ -20,549 +21,339 @@ #include #include "base.h" +DECLARE_MUTEX(pnp_res_mutex); -int pnp_max_moves = 4; - - -static int pnp_next_port(struct pnp_dev * dev, int idx) +static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) { - struct pnp_port *port; unsigned long *start, *end, *flags; - if (!dev || idx < 0 || idx >= PNP_MAX_PORT) - return 0; - port = dev->rule->port[idx]; - if (!port) + + if (!dev || !rule) + return -EINVAL; + + if (idx >= PNP_MAX_PORT) { + pnp_err("More than 4 ports is incompatible with pnp specifications."); + /* pretend we were successful so at least the manager won't try again */ + return 1; + } + + /* check if this resource has been manually set, if so skip */ + if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) return 1; start = &dev->res.port_resource[idx].start; end = &dev->res.port_resource[idx].end; flags = &dev->res.port_resource[idx].flags; - /* set the initial values if this is the first time */ - if (*start == 0) { - *start = port->min; - *end = *start + port->size - 1; - *flags = port->flags | IORESOURCE_IO; - if (!pnp_check_port(dev, idx)) - return 1; - } + /* set the initial values */ + *start = rule->min; + *end = *start + rule->size - 1; + *flags = *flags | rule->flags | IORESOURCE_IO; /* run through until pnp_check_port is happy */ - do { - *start += port->align; - *end = *start + port->size - 1; - if (*start > port->max || !port->align) + while (!pnp_check_port(dev, idx)) { + *start += rule->align; + *end = *start + rule->size - 1; + if (*start > rule->max || !rule->align) return 0; - } while (pnp_check_port(dev, idx)); + } return 1; } -static int pnp_next_mem(struct pnp_dev * dev, int idx) +static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) { - struct pnp_mem *mem; unsigned long *start, *end, *flags; - if (!dev || idx < 0 || idx >= PNP_MAX_MEM) - return 0; - mem = dev->rule->mem[idx]; - if (!mem) + + if (!dev || !rule) + return -EINVAL; + + if (idx >= PNP_MAX_MEM) { + pnp_err("More than 8 mems is incompatible with pnp specifications."); + /* pretend we were successful so at least the manager won't try again */ + return 1; + } + + /* check if this resource has been manually set, if so skip */ + if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) return 1; start = &dev->res.mem_resource[idx].start; end = &dev->res.mem_resource[idx].end; flags = &dev->res.mem_resource[idx].flags; - /* set the initial values if this is the first time */ - if (*start == 0) { - *start = mem->min; - *end = *start + mem->size -1; - *flags = mem->flags | IORESOURCE_MEM; - if (!(mem->flags & IORESOURCE_MEM_WRITEABLE)) - *flags |= IORESOURCE_READONLY; - if (mem->flags & IORESOURCE_MEM_CACHEABLE) - *flags |= IORESOURCE_CACHEABLE; - if (mem->flags & IORESOURCE_MEM_RANGELENGTH) - *flags |= IORESOURCE_RANGELENGTH; - if (mem->flags & IORESOURCE_MEM_SHADOWABLE) - *flags |= IORESOURCE_SHADOWABLE; - if (!pnp_check_mem(dev, idx)) - return 1; - } + /* set the initial values */ + *start = rule->min; + *end = *start + rule->size -1; + *flags = *flags | rule->flags | IORESOURCE_MEM; + + /* convert pnp flags to standard Linux flags */ + if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) + *flags |= IORESOURCE_READONLY; + if (rule->flags & IORESOURCE_MEM_CACHEABLE) + *flags |= IORESOURCE_CACHEABLE; + if (rule->flags & IORESOURCE_MEM_RANGELENGTH) + *flags |= IORESOURCE_RANGELENGTH; + if (rule->flags & IORESOURCE_MEM_SHADOWABLE) + *flags |= IORESOURCE_SHADOWABLE; /* run through until pnp_check_mem is happy */ - do { - *start += mem->align; - *end = *start + mem->size - 1; - if (*start > mem->max || !mem->align) + while (!pnp_check_mem(dev, idx)) { + *start += rule->align; + *end = *start + rule->size - 1; + if (*start > rule->max || !rule->align) return 0; - } while (pnp_check_mem(dev, idx)); + } return 1; } -static int pnp_next_irq(struct pnp_dev * dev, int idx) +static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx) { - struct pnp_irq *irq; unsigned long *start, *end, *flags; - int i, mask; - if (!dev || idx < 0 || idx >= PNP_MAX_IRQ) - return 0; - irq = dev->rule->irq[idx]; - if (!irq) - return 1; + int i; - start = &dev->res.irq_resource[idx].start; - end = &dev->res.irq_resource[idx].end; - flags = &dev->res.irq_resource[idx].flags; + /* IRQ priority: this table is good for i386 */ + static unsigned short xtab[16] = { + 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 + }; - /* set the initial values if this is the first time */ - if (*start == -1) { - *start = *end = 0; - *flags = irq->flags | IORESOURCE_IRQ; - if (!pnp_check_irq(dev, idx)) - return 1; - } + if (!dev || !rule) + return -EINVAL; - mask = irq->map; - for (i = *start + 1; i < 16; i++) - { - if(mask>>i & 0x01) { - *start = *end = i; - if(!pnp_check_irq(dev, idx)) - return 1; - } + if (idx >= PNP_MAX_IRQ) { + pnp_err("More than 2 irqs is incompatible with pnp specifications."); + /* pretend we were successful so at least the manager won't try again */ + return 1; } - return 0; -} -static int pnp_next_dma(struct pnp_dev * dev, int idx) -{ - struct pnp_dma *dma; - unsigned long *start, *end, *flags; - int i, mask; - if (!dev || idx < 0 || idx >= PNP_MAX_DMA) - return -EINVAL; - dma = dev->rule->dma[idx]; - if (!dma) + /* check if this resource has been manually set, if so skip */ + if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) return 1; - start = &dev->res.dma_resource[idx].start; - end = &dev->res.dma_resource[idx].end; - flags = &dev->res.dma_resource[idx].flags; + start = &dev->res.irq_resource[idx].start; + end = &dev->res.irq_resource[idx].end; + flags = &dev->res.irq_resource[idx].flags; - /* set the initial values if this is the first time */ - if (*start == -1) { - *start = *end = 0; - *flags = dma->flags | IORESOURCE_DMA; - if (!pnp_check_dma(dev, idx)) - return 1; - } + /* set the initial values */ + *flags = *flags | rule->flags | IORESOURCE_IRQ; - mask = dma->map; - for (i = *start + 1; i < 8; i++) - { - if(mask>>i & 0x01) { - *start = *end = i; - if(!pnp_check_dma(dev, idx)) + for (i = 0; i < 16; i++) { + if(rule->map & (1<rule->depnum; - int max = pnp_get_max_depnum(dev); - int priority = PNP_RES_PRIORITY_PREFERRED; - - if (depnum < 0) - return 0; - - if (max == 0) { - if (pnp_generate_rule(dev, 0, dev->rule)) { - dev->rule->depnum = -1; - return 1; - } - } - - if(depnum > 0) { - struct pnp_resources * res = pnp_find_resources(dev, depnum); - priority = res->priority; - } - - for (; priority <= PNP_RES_PRIORITY_FUNCTIONAL; priority++, depnum = 0) { - depnum += 1; - for (; depnum <= max; depnum++) { - struct pnp_resources * res = pnp_find_resources(dev, depnum); - if (res->priority == priority) { - if(pnp_generate_rule(dev, depnum, dev->rule)) { - dev->rule->depnum = depnum; - return 1; - } - } - } - } - return 0; -} - -struct pnp_change { - struct list_head change_list; - struct list_head changes; - struct pnp_resource_table res_bak; - struct pnp_rule_table rule_bak; - struct pnp_dev * dev; -}; - -static void pnp_free_changes(struct pnp_change * parent) -{ - struct list_head * pos, * temp; - list_for_each_safe(pos, temp, &parent->changes) { - struct pnp_change * change = list_entry(pos, struct pnp_change, change_list); - list_del(&change->change_list); - kfree(change); - } -} - -static void pnp_undo_changes(struct pnp_change * parent) -{ - struct list_head * pos, * temp; - list_for_each_safe(pos, temp, &parent->changes) { - struct pnp_change * change = list_entry(pos, struct pnp_change, change_list); - *change->dev->rule = change->rule_bak; - change->dev->res = change->res_bak; - list_del(&change->change_list); - kfree(change); - } -} - -static struct pnp_change * pnp_add_change(struct pnp_change * parent, struct pnp_dev * dev) -{ - struct pnp_change * change = pnp_alloc(sizeof(struct pnp_change)); - if (!change) - return NULL; - change->res_bak = dev->res; - change->rule_bak = *dev->rule; - change->dev = dev; - INIT_LIST_HEAD(&change->changes); - if (parent) - list_add(&change->change_list, &parent->changes); - return change; -} - -static void pnp_commit_changes(struct pnp_change * parent, struct pnp_change * change) -{ - /* check if it's the root change */ - if (!parent) - return; - if (!list_empty(&change->changes)) - list_splice_init(&change->changes, &parent->changes); -} - -static int pnp_next_config(struct pnp_dev * dev, int move, struct pnp_change * parent); - -static int pnp_next_request(struct pnp_dev * dev, int move, struct pnp_change * parent, struct pnp_change * change) +static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) { + unsigned long *start, *end, *flags; int i; - struct pnp_dev * cdev; - for (i = 0; i < PNP_MAX_PORT; i++) { - if (dev->res.port_resource[i].start == 0 - || pnp_check_port_conflicts(dev,i,SEARCH_WARM)) { - if (!pnp_next_port(dev,i)) - return 0; - } - do { - cdev = pnp_check_port_conflicts(dev,i,SEARCH_COLD); - if (cdev && (!move || !pnp_next_config(cdev,move,change))) { - pnp_undo_changes(change); - if (!pnp_next_port(dev,i)) - return 0; - } - } while (cdev); - pnp_commit_changes(parent, change); - } - for (i = 0; i < PNP_MAX_MEM; i++) { - if (dev->res.mem_resource[i].start == 0 - || pnp_check_mem_conflicts(dev,i,SEARCH_WARM)) { - if (!pnp_next_mem(dev,i)) - return 0; - } - do { - cdev = pnp_check_mem_conflicts(dev,i,SEARCH_COLD); - if (cdev && (!move || !pnp_next_config(cdev,move,change))) { - pnp_undo_changes(change); - if (!pnp_next_mem(dev,i)) - return 0; - } - } while (cdev); - pnp_commit_changes(parent, change); - } - for (i = 0; i < PNP_MAX_IRQ; i++) { - if (dev->res.irq_resource[i].start == -1 - || pnp_check_irq_conflicts(dev,i,SEARCH_WARM)) { - if (!pnp_next_irq(dev,i)) - return 0; - } - do { - cdev = pnp_check_irq_conflicts(dev,i,SEARCH_COLD); - if (cdev && (!move || !pnp_next_config(cdev,move,change))) { - pnp_undo_changes(change); - if (!pnp_next_irq(dev,i)) - return 0; - } - } while (cdev); - pnp_commit_changes(parent, change); - } - for (i = 0; i < PNP_MAX_DMA; i++) { - if (dev->res.dma_resource[i].start == -1 - || pnp_check_dma_conflicts(dev,i,SEARCH_WARM)) { - if (!pnp_next_dma(dev,i)) - return 0; - } - do { - cdev = pnp_check_dma_conflicts(dev,i,SEARCH_COLD); - if (cdev && (!move || !pnp_next_config(cdev,move,change))) { - pnp_undo_changes(change); - if (!pnp_next_dma(dev,i)) - return 0; - } - } while (cdev); - pnp_commit_changes(parent, change); - } - return 1; -} - -static int pnp_next_config(struct pnp_dev * dev, int move, struct pnp_change * parent) -{ - struct pnp_change * change; - move--; - if (!dev->rule) - return 0; - change = pnp_add_change(parent,dev); - if (!change) - return 0; - if (!pnp_can_configure(dev)) - goto fail; - if (!dev->rule->depnum) { - if (!pnp_next_rule(dev)) - goto fail; - } - while (!pnp_next_request(dev, move, parent, change)) { - if(!pnp_next_rule(dev)) - goto fail; - pnp_init_resource_table(&dev->res); - } - if (!parent) { - pnp_free_changes(change); - kfree(change); - } - return 1; + /* DMA priority: this table is good for i386 */ + static unsigned short xtab[8] = { + 1, 3, 5, 6, 7, 0, 2, 4 + }; -fail: - if (!parent) - kfree(change); - return 0; -} + if (!dev || !rule) + return -EINVAL; -/* this advanced algorithm will shuffle other configs to make room and ensure that the most possible devices have configs */ -static int pnp_advanced_config(struct pnp_dev * dev) -{ - int move; - /* if the device cannot be configured skip it */ - if (!pnp_can_configure(dev)) + if (idx >= PNP_MAX_DMA) { + pnp_err("More than 2 dmas is incompatible with pnp specifications."); + /* pretend we were successful so at least the manager won't try again */ return 1; - if (!dev->rule) { - dev->rule = pnp_alloc(sizeof(struct pnp_rule_table)); - if (!dev->rule) - return -ENOMEM; - } - - spin_lock(&pnp_lock); - for (move = 1; move <= pnp_max_moves; move++) { - dev->rule->depnum = 0; - pnp_init_resource_table(&dev->res); - if (pnp_next_config(dev,move,NULL)) { - spin_unlock(&pnp_lock); - return 1; - } } - pnp_init_resource_table(&dev->res); - dev->rule->depnum = 0; - spin_unlock(&pnp_lock); - pnp_err("res: Unable to resolve resource conflicts for the device '%s', some devices may not be usable.", dev->dev.bus_id); - return 0; -} + /* check if this resource has been manually set, if so skip */ + if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) + return 1; -int pnp_resolve_conflicts(struct pnp_dev *dev) -{ - int i; - struct pnp_dev * cdev; + start = &dev->res.dma_resource[idx].start; + end = &dev->res.dma_resource[idx].end; + flags = &dev->res.dma_resource[idx].flags; - for (i = 0; i < PNP_MAX_PORT; i++) - { - do { - cdev = pnp_check_port_conflicts(dev,i,SEARCH_COLD); - if (cdev) - pnp_advanced_config(cdev); - } while (cdev); - } - for (i = 0; i < PNP_MAX_MEM; i++) - { - do { - cdev = pnp_check_mem_conflicts(dev,i,SEARCH_COLD); - if (cdev) - pnp_advanced_config(cdev); - } while (cdev); - } - for (i = 0; i < PNP_MAX_IRQ; i++) - { - do { - cdev = pnp_check_irq_conflicts(dev,i,SEARCH_COLD); - if (cdev) - pnp_advanced_config(cdev); - } while (cdev); - } - for (i = 0; i < PNP_MAX_DMA; i++) - { - do { - cdev = pnp_check_dma_conflicts(dev,i,SEARCH_COLD); - if (cdev) - pnp_advanced_config(cdev); - } while (cdev); - } - return 1; -} + /* set the initial values */ + *flags = *flags | rule->flags | IORESOURCE_DMA; -/* this is a much faster algorithm but it may not leave resources for other devices to use */ -static int pnp_simple_config(struct pnp_dev * dev) -{ - int i; - spin_lock(&pnp_lock); - if (dev->active) { - spin_unlock(&pnp_lock); - return 1; - } - if (!dev->rule) { - dev->rule = pnp_alloc(sizeof(struct pnp_rule_table)); - if (!dev->rule) { - spin_unlock(&pnp_lock); - return -ENOMEM; - } - } - dev->rule->depnum = 0; - pnp_init_resource_table(&dev->res); - while (pnp_next_rule(dev)) { - for (i = 0; i < PNP_MAX_PORT; i++) { - if (!pnp_next_port(dev,i)) - continue; - } - for (i = 0; i < PNP_MAX_MEM; i++) { - if (!pnp_next_mem(dev,i)) - continue; - } - for (i = 0; i < PNP_MAX_IRQ; i++) { - if (!pnp_next_irq(dev,i)) - continue; - } - for (i = 0; i < PNP_MAX_DMA; i++) { - if (!pnp_next_dma(dev,i)) - continue; + for (i = 0; i < 8; i++) { + if(rule->map & (1<res); - dev->rule->depnum = 0; - spin_unlock(&pnp_lock); return 0; - -done: - pnp_resolve_conflicts(dev); /* this is required or we will break the advanced configs */ - return 1; } -static int pnp_compare_resources(struct pnp_resource_table * resa, struct pnp_resource_table * resb) +/** + * pnp_init_resources - Resets a resource table to default values. + * @table: pointer to the desired resource table + * + */ +void pnp_init_resources(struct pnp_resource_table *table) { int idx; + down(&pnp_res_mutex); for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - if (resa->irq_resource[idx].start != resb->irq_resource[idx].start) - return 1; + table->irq_resource[idx].name = NULL; + table->irq_resource[idx].start = -1; + table->irq_resource[idx].end = -1; + table->irq_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { - if (resa->dma_resource[idx].start != resb->dma_resource[idx].start) - return 1; + table->dma_resource[idx].name = NULL; + table->dma_resource[idx].start = -1; + table->dma_resource[idx].end = -1; + table->dma_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { - if (resa->port_resource[idx].start != resb->port_resource[idx].start) - return 1; - if (resa->port_resource[idx].end != resb->port_resource[idx].end) - return 1; + table->port_resource[idx].name = NULL; + table->port_resource[idx].start = 0; + table->port_resource[idx].end = 0; + table->port_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { - if (resa->mem_resource[idx].start != resb->mem_resource[idx].start) - return 1; - if (resa->mem_resource[idx].end != resb->mem_resource[idx].end) - return 1; + table->mem_resource[idx].name = NULL; + table->mem_resource[idx].start = 0; + table->mem_resource[idx].end = 0; + table->mem_resource[idx].flags = IORESOURCE_AUTO; } - return 0; + up(&pnp_res_mutex); } - -/* - * PnP Device Resource Management - */ - /** - * pnp_auto_config_dev - determines the best possible resource configuration based on available information - * @dev: pointer to the desired device + * pnp_clean_resources - clears resources that were not manually set + * @res - the resources to clean * */ - -int pnp_auto_config_dev(struct pnp_dev *dev) -{ - int error; - if(!dev) - return -EINVAL; - - dev->config_mode = PNP_CONFIG_AUTO; - - if(dev->active) - error = pnp_resolve_conflicts(dev); - else - error = pnp_advanced_config(dev); - return error; -} - -static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struct pnp_resource_table * ntab) +static void pnp_clean_resources(struct pnp_resource_table * res) { int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) + if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) continue; - ctab->irq_resource[idx].start = ntab->irq_resource[idx].start; - ctab->irq_resource[idx].end = ntab->irq_resource[idx].end; - ctab->irq_resource[idx].flags = ntab->irq_resource[idx].flags; + res->irq_resource[idx].start = -1; + res->irq_resource[idx].end = -1; + res->irq_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { - if (ntab->dma_resource[idx].flags & IORESOURCE_AUTO) + if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) continue; - ctab->dma_resource[idx].start = ntab->dma_resource[idx].start; - ctab->dma_resource[idx].end = ntab->dma_resource[idx].end; - ctab->dma_resource[idx].flags = ntab->dma_resource[idx].flags; + res->dma_resource[idx].start = -1; + res->dma_resource[idx].end = -1; + res->dma_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { - if (ntab->port_resource[idx].flags & IORESOURCE_AUTO) + if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) continue; - ctab->port_resource[idx].start = ntab->port_resource[idx].start; - ctab->port_resource[idx].end = ntab->port_resource[idx].end; - ctab->port_resource[idx].flags = ntab->port_resource[idx].flags; + res->port_resource[idx].start = 0; + res->port_resource[idx].end = 0; + res->port_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { - if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) + if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) continue; - ctab->irq_resource[idx].start = ntab->mem_resource[idx].start; - ctab->irq_resource[idx].end = ntab->mem_resource[idx].end; - ctab->irq_resource[idx].flags = ntab->mem_resource[idx].flags; + res->mem_resource[idx].start = 0; + res->mem_resource[idx].end = 0; + res->mem_resource[idx].flags = IORESOURCE_AUTO; + } +} + +/** + * pnp_assign_resources - assigns resources to the device based on the specified dependent number + * @dev: pointer to the desired device + * @depnum: the dependent function number + * + * Only set depnum to 0 if the device does not have dependent options. + */ +int pnp_assign_resources(struct pnp_dev *dev, int depnum) +{ + struct pnp_port *port; + struct pnp_mem *mem; + struct pnp_irq *irq; + struct pnp_dma *dma; + int nport = 0, nmem = 0, nirq = 0, ndma = 0; + + if (!pnp_can_configure(dev)) + return -ENODEV; + + down(&pnp_res_mutex); + pnp_clean_resources(&dev->res); /* start with a fresh slate */ + if (dev->independent) { + port = dev->independent->port; + mem = dev->independent->mem; + irq = dev->independent->irq; + dma = dev->independent->dma; + while (port) { + if (!pnp_assign_port(dev, port, nport)) + goto fail; + nport++; + port = port->next; + } + while (mem) { + if (!pnp_assign_mem(dev, mem, nmem)) + goto fail; + nmem++; + mem = mem->next; + } + while (irq) { + if (!pnp_assign_irq(dev, irq, nirq)) + goto fail; + nirq++; + irq = irq->next; + } + while (dma) { + if (!pnp_assign_dma(dev, dma, ndma)) + goto fail; + ndma++; + dma = dma->next; + } } + + if (depnum) { + struct pnp_option *dep; + int i; + for (i=1,dep=dev->dependent; inext) + if(!dep) + goto fail; + port =dep->port; + mem = dep->mem; + irq = dep->irq; + dma = dep->dma; + while (port) { + if (!pnp_assign_port(dev, port, nport)) + goto fail; + nport++; + port = port->next; + } + while (mem) { + if (!pnp_assign_mem(dev, mem, nmem)) + goto fail; + nmem++; + mem = mem->next; + } + while (irq) { + if (!pnp_assign_irq(dev, irq, nirq)) + goto fail; + nirq++; + irq = irq->next; + } + while (dma) { + if (!pnp_assign_dma(dev, dma, ndma)) + goto fail; + ndma++; + dma = dma->next; + } + } else if (dev->dependent) + goto fail; + + up(&pnp_res_mutex); + return 1; + +fail: + pnp_clean_resources(&dev->res); + up(&pnp_res_mutex); + return 0; } /** @@ -572,22 +363,21 @@ * * This function can be used by drivers that want to manually set thier resources. */ - int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, int mode) { int i; struct pnp_resource_table * bak; if (!dev || !res) return -EINVAL; - if (dev->active) - return -EBUSY; + if (!pnp_can_configure(dev)) + return -ENODEV; bak = pnp_alloc(sizeof(struct pnp_resource_table)); if (!bak) return -ENOMEM; *bak = dev->res; - spin_lock(&pnp_lock); - pnp_process_manual_resources(&dev->res, res); + down(&pnp_res_mutex); + dev->res = *res; if (!(mode & PNP_CONFIG_FORCE)) { for (i = 0; i < PNP_MAX_PORT; i++) { if(pnp_check_port(dev,i)) @@ -606,27 +396,64 @@ goto fail; } } - dev->config_mode = PNP_CONFIG_MANUAL; - spin_unlock(&pnp_lock); + up(&pnp_res_mutex); - pnp_resolve_conflicts(dev); + pnp_auto_config_dev(dev); kfree(bak); return 0; fail: dev->res = *bak; - spin_unlock(&pnp_lock); + up(&pnp_res_mutex); kfree(bak); return -EINVAL; } /** - * pnp_activate_dev - activates a PnP device for use + * pnp_auto_config_dev - automatically assigns resources to a device * @dev: pointer to the desired device * - * finds the best resource configuration and then informs the correct pnp protocol */ +int pnp_auto_config_dev(struct pnp_dev *dev) +{ + struct pnp_option *dep; + int i = 1; + + if(!dev) + return -EINVAL; + + if(!pnp_can_configure(dev)) { + pnp_info("Device %s does not support resource configuration.", dev->dev.bus_id); + return -ENODEV; + } + + if (!dev->dependent) { + if (pnp_assign_resources(dev, 0)) + return 1; + else + return 0; + } + + dep = dev->dependent; + do { + if (pnp_assign_resources(dev, i)) + return 1; + /* if this dependent resource failed, try the next one */ + dep = dep->next; + i++; + } while (dep); + + pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id); + return 0; +} + +/** + * pnp_activate_dev - activates a PnP device for use + * @dev: pointer to the desired device + * + * does not validate or set resources so be careful. + */ int pnp_activate_dev(struct pnp_dev *dev) { if (!dev) @@ -634,55 +461,25 @@ if (dev->active) { return 0; /* the device is already active */ } - /* If this condition is true, advanced configuration failed, we need to get this device up and running - * so we use the simple config engine which ignores cold conflicts, this of course may lead to new failures */ - if (!pnp_is_active(dev)) { - if (!pnp_simple_config(dev)) { - pnp_err("res: Unable to resolve resource conflicts for the device '%s'.", dev->dev.bus_id); - goto fail; - } - } - spin_lock(&pnp_lock); /* we lock just in case the device is being configured during this call */ - dev->active = 1; - spin_unlock(&pnp_lock); /* once the device is claimed active we know it won't be configured so we can unlock */ + /* ensure resources are allocated */ + if (!pnp_auto_config_dev(dev)) + return -EBUSY; - if (dev->config_mode & PNP_CONFIG_INVALID) { - pnp_info("res: Unable to activate the PnP device '%s' because its resource configuration is invalid.", dev->dev.bus_id); - goto fail; - } - if (dev->status != PNP_READY && dev->status != PNP_ATTACHED){ - pnp_err("res: Activation failed because the PnP device '%s' is busy.", dev->dev.bus_id); - goto fail; - } if (!pnp_can_write(dev)) { - pnp_info("res: Unable to activate the PnP device '%s' because this feature is not supported.", dev->dev.bus_id); - goto fail; + pnp_info("Device %s does not supported activation.", dev->dev.bus_id); + return -EINVAL; } + if (dev->protocol->set(dev, &dev->res)<0) { - pnp_err("res: The protocol '%s' reports that activating the PnP device '%s' has failed.", dev->protocol->name, dev->dev.bus_id); - goto fail; - } - if (pnp_can_read(dev)) { - struct pnp_resource_table * res = pnp_alloc(sizeof(struct pnp_resource_table)); - if (!res) - goto fail; - dev->protocol->get(dev, res); - if (pnp_compare_resources(&dev->res, res)) /* if this happens we may be in big trouble but it's best just to continue */ - pnp_err("res: The resources requested do not match those set for the PnP device '%s'.", dev->dev.bus_id); - kfree(res); - } else - dev->active = pnp_is_active(dev); - pnp_dbg("res: the device '%s' has been activated.", dev->dev.bus_id); - if (dev->rule) { - kfree(dev->rule); - dev->rule = NULL; + pnp_err("Failed to activate device %s.", dev->dev.bus_id); + return -EIO; } - return 0; -fail: - dev->active = 0; /* fixes incorrect active state */ - return -EINVAL; + dev->active = 1; + pnp_info("Device %s activated.", dev->dev.bus_id); + + return 1; } /** @@ -691,7 +488,6 @@ * * inform the correct pnp protocol so that resources can be used by other devices */ - int pnp_disable_dev(struct pnp_dev *dev) { if (!dev) @@ -699,21 +495,25 @@ if (!dev->active) { return 0; /* the device is already disabled */ } - if (dev->status != PNP_READY){ - pnp_info("res: Disable failed becuase the PnP device '%s' is busy.", dev->dev.bus_id); - return -EINVAL; - } + if (!pnp_can_disable(dev)) { - pnp_info("res: Unable to disable the PnP device '%s' because this feature is not supported.", dev->dev.bus_id); + pnp_info("Device %s does not supported disabling.", dev->dev.bus_id); return -EINVAL; } if (dev->protocol->disable(dev)<0) { - pnp_err("res: The protocol '%s' reports that disabling the PnP device '%s' has failed.", dev->protocol->name, dev->dev.bus_id); - return -1; + pnp_err("Failed to disable device %s.", dev->dev.bus_id); + return -EIO; } - dev->active = 0; /* just in case the protocol doesn't do this */ - pnp_dbg("res: the device '%s' has been disabled.", dev->dev.bus_id); - return 0; + + dev->active = 0; + pnp_info("Device %s disabled.", dev->dev.bus_id); + + /* release the resources so that other devices can use them */ + down(&pnp_res_mutex); + pnp_clean_resources(&dev->res); + up(&pnp_res_mutex); + + return 1; } /** @@ -723,7 +523,6 @@ * @size: size of region * */ - void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { if (resource == NULL) @@ -734,19 +533,10 @@ } -EXPORT_SYMBOL(pnp_auto_config_dev); +EXPORT_SYMBOL(pnp_assign_resources); EXPORT_SYMBOL(pnp_manual_config_dev); +EXPORT_SYMBOL(pnp_auto_config_dev); EXPORT_SYMBOL(pnp_activate_dev); EXPORT_SYMBOL(pnp_disable_dev); EXPORT_SYMBOL(pnp_resource_change); - - -/* format is: pnp_max_moves=num */ - -static int __init pnp_setup_max_moves(char *str) -{ - get_option(&str,&pnp_max_moves); - return 1; -} - -__setup("pnp_max_moves=", pnp_setup_max_moves); +EXPORT_SYMBOL(pnp_init_resources); diff -urN linux-2.5.72-bk2/drivers/pnp/pnpbios/core.c linux-2.5.72-bk3/drivers/pnp/pnpbios/core.c --- linux-2.5.72-bk2/drivers/pnp/pnpbios/core.c 2003-06-16 21:19:39.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/pnpbios/core.c 2003-06-20 04:48:11.000000000 -0700 @@ -935,6 +935,10 @@ dev->capabilities |= PNP_REMOVABLE; dev->protocol = &pnpbios_protocol; + /* clear out the damaged flags */ + if (!dev->active) + pnp_init_resources(&dev->res); + pnp_add_device(dev); pnpbios_interface_attach_device(node); diff -urN linux-2.5.72-bk2/drivers/pnp/quirks.c linux-2.5.72-bk3/drivers/pnp/quirks.c --- linux-2.5.72-bk2/drivers/pnp/quirks.c 2003-06-16 21:20:21.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/quirks.c 2003-06-20 04:48:11.000000000 -0700 @@ -30,7 +30,7 @@ static void quirk_awe32_resources(struct pnp_dev *dev) { struct pnp_port *port, *port2, *port3; - struct pnp_resources *res = dev->possible->dep; + struct pnp_option *res = dev->dependent; /* * Unfortunately the isapnp_add_port_resource is too tightly bound @@ -38,7 +38,7 @@ * two extra ports (at offset 0x400 and 0x800 from the one given) by * hand. */ - for ( ; res ; res = res->dep ) { + for ( ; res ; res = res->next ) { port2 = pnp_alloc(sizeof(struct pnp_port)); if (!port2) return; @@ -62,9 +62,9 @@ static void quirk_cmi8330_resources(struct pnp_dev *dev) { - struct pnp_resources *res = dev->possible->dep; + struct pnp_option *res = dev->dependent; - for ( ; res ; res = res->dep ) { + for ( ; res ; res = res->next ) { struct pnp_irq *irq; struct pnp_dma *dma; @@ -82,7 +82,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) { struct pnp_port *port; - struct pnp_resources *res = dev->possible->dep; + struct pnp_option *res = dev->dependent; int changed = 0; /* @@ -91,7 +91,7 @@ * auto-configured. */ - for( ; res ; res = res->dep ) { + for( ; res ; res = res->next ) { port = res->port; if(!port) continue; @@ -118,11 +118,11 @@ * doesn't allow a DMA channel of 0, afflicted card is an * OPL3Sax where x=4. */ - struct pnp_resources *res; + struct pnp_option *res; int max; - res = dev->possible; + res = dev->dependent; max = 0; - for (res = res->dep; res; res = res->dep) { + for (; res; res = res->next) { if (res->dma->map > max) max = res->dma->map; } diff -urN linux-2.5.72-bk2/drivers/pnp/resource.c linux-2.5.72-bk3/drivers/pnp/resource.c --- linux-2.5.72-bk2/drivers/pnp/resource.c 2003-06-16 21:20:05.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/resource.c 2003-06-20 04:48:11.000000000 -0700 @@ -10,18 +10,19 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include #include "base.h" -int pnp_allow_dma0 = -1; /* allow dma 0 during auto activation: -1=off (:default), 0=off (set by user), 1=on */ +int pnp_allow_dma0 = -1; /* allow dma 0 during auto activation: + * -1=off (:default), 0=off (set by user), 1=on */ int pnp_skip_pci_scan; /* skip PCI resource scanning */ int pnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */ int pnp_reserve_dma[8] = { [0 ... 7] = -1 }; /* reserve (don't use) some DMA */ @@ -30,88 +31,75 @@ /* - * possible resource registration + * option registration */ -struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) +static struct pnp_option * pnp_build_option(int priority) { - struct pnp_resources *res, *ptr, *ptra; + struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option)); - res = pnp_alloc(sizeof(struct pnp_resources)); - if (!res) + /* check if pnp_alloc ran out of memory */ + if (!option) return NULL; - ptr = dev->possible; - if (ptr) { /* add to another list */ - ptra = ptr->dep; - while (ptra && ptra->dep) - ptra = ptra->dep; - if (!ptra) - ptr->dep = res; - else - ptra->dep = res; - } else - dev->possible = res; - if (dependent) { - res->priority = dependent & 0xff; - if (res->priority > PNP_RES_PRIORITY_FUNCTIONAL) - res->priority = PNP_RES_PRIORITY_INVALID; - } else - res->priority = PNP_RES_PRIORITY_PREFERRED; - return res; + + option->priority = priority & 0xff; + /* make sure the priority is valid */ + if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL) + option->priority = PNP_RES_PRIORITY_INVALID; + + return option; } -struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) +struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev) { - int i; - struct pnp_resources *res; + struct pnp_option *option; if (!dev) return NULL; - res = dev->possible; - if (!res) - return NULL; - for (i = 0; i < depnum; i++) - { - if (res->dep) - res = res->dep; - else - return NULL; - } - return res; + + option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED); + + /* this should never happen but if it does we'll try to continue */ + if (dev->independent) + pnp_err("independent resource already registered"); + dev->independent = option; + return option; } -int pnp_get_max_depnum(struct pnp_dev *dev) +struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int priority) { - int num = 0; - struct pnp_resources *res; + struct pnp_option *option; if (!dev) - return -EINVAL; - res = dev->possible; - if (!res) - return -EINVAL; - while (res->dep){ - res = res->dep; - num++; - } - return num; + return NULL; + + option = pnp_build_option(priority); + + if (dev->dependent) { + struct pnp_option *parent = dev->dependent; + while (parent->next) + parent = parent->next; + parent->next = option; + } else + dev->dependent = option; + return option; } -int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) +int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) { int i; - struct pnp_resources *res; struct pnp_irq *ptr; - res = pnp_find_resources(dev,depnum); - if (!res) + if (!option) return -EINVAL; if (!data) return -EINVAL; - ptr = res->irq; + + ptr = option->irq; while (ptr && ptr->next) ptr = ptr->next; if (ptr) ptr->next = data; else - res->irq = data; + option->irq = data; + #ifdef CONFIG_PCI for (i=0; i<16; i++) if (data->map & (1<dma; + + ptr = option->dma; while (ptr && ptr->next) ptr = ptr->next; if (ptr) ptr->next = data; else - res->dma = data; + option->dma = data; + return 0; } -int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data) +int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) { - struct pnp_resources *res; struct pnp_port *ptr; - res = pnp_find_resources(dev,depnum); - if (!res) + if (!option) return -EINVAL; if (!data) return -EINVAL; - ptr = res->port; + + ptr = option->port; while (ptr && ptr->next) ptr = ptr->next; if (ptr) ptr->next = data; else - res->port = data; + option->port = data; + return 0; } -int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data) +int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) { - struct pnp_resources *res; struct pnp_mem *ptr; - res = pnp_find_resources(dev,depnum); - if (!res) + if (!option) return -EINVAL; if (!data) return -EINVAL; - ptr = res->mem; + + ptr = option->mem; while (ptr && ptr->next) ptr = ptr->next; if (ptr) ptr->next = data; else - res->mem = data; + option->mem = data; return 0; } @@ -221,18 +208,18 @@ } } -void pnp_free_resources(struct pnp_resources *resources) +void pnp_free_option(struct pnp_option *option) { - struct pnp_resources *next; + struct pnp_option *next; - while (resources) { - next = resources->dep; - pnp_free_port(resources->port); - pnp_free_irq(resources->irq); - pnp_free_dma(resources->dma); - pnp_free_mem(resources->mem); - kfree(resources); - resources = next; + while (option) { + next = option->next; + pnp_free_port(option->port); + pnp_free_irq(option->irq); + pnp_free_dma(option->dma); + pnp_free_mem(option->mem); + kfree(option); + option = next; } } @@ -253,50 +240,23 @@ (*(enda) >= *(startb) && *(enda) <= *(endb)) || \ (*(starta) < *(startb) && *(enda) > *(endb))) -struct pnp_dev * pnp_check_port_conflicts(struct pnp_dev * dev, int idx, int mode) -{ - int tmp; - unsigned long *port, *end, *tport, *tend; - struct pnp_dev *tdev; - port = &dev->res.port_resource[idx].start; - end = &dev->res.port_resource[idx].end; - - /* if the resource doesn't exist, don't complain about it */ - if (dev->res.port_resource[idx].start == 0) - return NULL; - - /* check for cold conflicts */ - pnp_for_each_dev(tdev) { - /* Is the device configurable? */ - if (tdev == dev || (mode ? !tdev->active : tdev->active)) - continue; - for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { - if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { - tport = &tdev->res.port_resource[tmp].start; - tend = &tdev->res.port_resource[tmp].end; - if (ranged_conflict(port,end,tport,tend)) - return tdev; - } - } - } - return NULL; -} - int pnp_check_port(struct pnp_dev * dev, int idx) { int tmp; + struct pnp_dev *tdev; unsigned long *port, *end, *tport, *tend; port = &dev->res.port_resource[idx].start; end = &dev->res.port_resource[idx].end; /* if the resource doesn't exist, don't complain about it */ if (dev->res.port_resource[idx].start == 0) - return 0; + return 1; - /* check if the resource is already in use, skip if the device is active because it itself may be in use */ + /* check if the resource is already in use, skip if the + * device is active because it itself may be in use */ if(!dev->active) { - if (check_region(*port, length(port,end))) - return CONFLICT_TYPE_IN_USE; + if (__check_region(&ioport_resource, *port, length(port,end))) + return 0; } /* check if the resource is reserved */ @@ -304,7 +264,7 @@ int rport = pnp_reserve_io[tmp << 1]; int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1; if (ranged_conflict(port,end,&rport,&rend)) - return CONFLICT_TYPE_RESERVED; + return 0; } /* check for internal conflicts */ @@ -313,61 +273,44 @@ tport = &dev->res.port_resource[tmp].start; tend = &dev->res.port_resource[tmp].end; if (ranged_conflict(port,end,tport,tend)) - return CONFLICT_TYPE_INTERNAL; + return 0; } } - /* check for warm conflicts */ - if (pnp_check_port_conflicts(dev, idx, SEARCH_WARM)) - return CONFLICT_TYPE_PNP_WARM; - - return 0; -} - -struct pnp_dev * pnp_check_mem_conflicts(struct pnp_dev * dev, int idx, int mode) -{ - int tmp; - unsigned long *addr, *end, *taddr, *tend; - struct pnp_dev *tdev; - addr = &dev->res.mem_resource[idx].start; - end = &dev->res.mem_resource[idx].end; - - /* if the resource doesn't exist, don't complain about it */ - if (dev->res.mem_resource[idx].start == 0) - return NULL; - - /* check for cold conflicts */ + /* check for conflicts with other pnp devices */ pnp_for_each_dev(tdev) { - /* Is the device configurable? */ - if (tdev == dev || (mode ? !tdev->active : tdev->active)) + if (tdev == dev) continue; - for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { - if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { - taddr = &tdev->res.mem_resource[tmp].start; - tend = &tdev->res.mem_resource[tmp].end; - if (ranged_conflict(addr,end,taddr,tend)) - return tdev; + for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { + if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { + tport = &tdev->res.port_resource[tmp].start; + tend = &tdev->res.port_resource[tmp].end; + if (ranged_conflict(port,end,tport,tend)) + return 0; } } } - return NULL; + + return 1; } int pnp_check_mem(struct pnp_dev * dev, int idx) { int tmp; + struct pnp_dev *tdev; unsigned long *addr, *end, *taddr, *tend; addr = &dev->res.mem_resource[idx].start; end = &dev->res.mem_resource[idx].end; /* if the resource doesn't exist, don't complain about it */ if (dev->res.mem_resource[idx].start == 0) - return 0; + return 1; - /* check if the resource is already in use, skip if the device is active because it itself may be in use */ + /* check if the resource is already in use, skip if the + * device is active because it itself may be in use */ if(!dev->active) { - if (__check_region(&iomem_resource, *addr, length(addr,end))) - return CONFLICT_TYPE_IN_USE; + if (check_mem_region(*addr, length(addr,end))) + return 0; } /* check if the resource is reserved */ @@ -375,7 +318,7 @@ int raddr = pnp_reserve_mem[tmp << 1]; int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1; if (ranged_conflict(addr,end,&raddr,&rend)) - return CONFLICT_TYPE_RESERVED; + return 0; } /* check for internal conflicts */ @@ -384,40 +327,25 @@ taddr = &dev->res.mem_resource[tmp].start; tend = &dev->res.mem_resource[tmp].end; if (ranged_conflict(addr,end,taddr,tend)) - return CONFLICT_TYPE_INTERNAL; + return 0; } } - /* check for warm conflicts */ - if (pnp_check_mem_conflicts(dev, idx, SEARCH_WARM)) - return CONFLICT_TYPE_PNP_WARM; - - return 0; -} - -struct pnp_dev * pnp_check_irq_conflicts(struct pnp_dev * dev, int idx, int mode) -{ - int tmp; - struct pnp_dev * tdev; - unsigned long * irq = &dev->res.irq_resource[idx].start; - - /* if the resource doesn't exist, don't complain about it */ - if (dev->res.irq_resource[idx].start == -1) - return NULL; - - /* check for cold conflicts */ + /* check for conflicts with other pnp devices */ pnp_for_each_dev(tdev) { - /* Is the device configurable? */ - if (tdev == dev || (mode ? !tdev->active : tdev->active)) + if (tdev == dev) continue; - for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { - if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { - if ((tdev->res.irq_resource[tmp].start == *irq)) - return tdev; + for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { + if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { + taddr = &tdev->res.mem_resource[tmp].start; + tend = &tdev->res.mem_resource[tmp].end; + if (ranged_conflict(addr,end,taddr,tend)) + return 0; } } } - return NULL; + + return 1; } static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs) @@ -428,27 +356,28 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) { int tmp; + struct pnp_dev *tdev; unsigned long * irq = &dev->res.irq_resource[idx].start; /* if the resource doesn't exist, don't complain about it */ if (dev->res.irq_resource[idx].start == -1) - return 0; + return 1; /* check if the resource is valid */ if (*irq < 0 || *irq > 15) - return CONFLICT_TYPE_INVALID; + return 0; /* check if the resource is reserved */ for (tmp = 0; tmp < 16; tmp++) { if (pnp_reserve_irq[tmp] == *irq) - return CONFLICT_TYPE_RESERVED; + return 0; } /* check for internal conflicts */ for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) { if (dev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { if (dev->res.irq_resource[tmp].start == *irq) - return CONFLICT_TYPE_INTERNAL; + return 0; } } @@ -458,233 +387,94 @@ struct pci_dev * pci = NULL; while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) { if (pci->irq == *irq) - return CONFLICT_TYPE_PCI; + return 0; } } #endif - /* check if the resource is already in use, skip if the device is active because it itself may be in use */ + /* check if the resource is already in use, skip if the + * device is active because it itself may be in use */ if(!dev->active) { if (request_irq(*irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL)) - return CONFLICT_TYPE_IN_USE; + return 0; free_irq(*irq, NULL); } - /* check for warm conflicts */ - if (pnp_check_irq_conflicts(dev, idx, SEARCH_WARM)) - return CONFLICT_TYPE_PNP_WARM; - - return 0; -} - - -struct pnp_dev * pnp_check_dma_conflicts(struct pnp_dev * dev, int idx, int mode) -{ - int tmp; - struct pnp_dev * tdev; - unsigned long * dma = &dev->res.dma_resource[idx].start; - - /* if the resource doesn't exist, don't complain about it */ - if (dev->res.dma_resource[idx].start == -1) - return NULL; - - /* check for cold conflicts */ + /* check for conflicts with other pnp devices */ pnp_for_each_dev(tdev) { - /* Is the device configurable? */ - if (tdev == dev || (mode ? !tdev->active : tdev->active)) + if (tdev == dev) continue; - for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { - if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { - if ((tdev->res.dma_resource[tmp].start == *dma)) - return tdev; + for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { + if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { + if ((tdev->res.irq_resource[tmp].start == *irq)) + return 0; } } } - return NULL; + + return 1; } int pnp_check_dma(struct pnp_dev * dev, int idx) { int tmp, mindma = 1; + struct pnp_dev *tdev; unsigned long * dma = &dev->res.dma_resource[idx].start; /* if the resource doesn't exist, don't complain about it */ if (dev->res.dma_resource[idx].start == -1) - return 0; + return 1; /* check if the resource is valid */ if (pnp_allow_dma0 == 1) mindma = 0; if (*dma < mindma || *dma == 4 || *dma > 7) - return CONFLICT_TYPE_INVALID; + return 0; /* check if the resource is reserved */ for (tmp = 0; tmp < 8; tmp++) { if (pnp_reserve_dma[tmp] == *dma) - return CONFLICT_TYPE_RESERVED; + return 0; } /* check for internal conflicts */ for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) { if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { if (dev->res.dma_resource[tmp].start == *dma) - return CONFLICT_TYPE_INTERNAL; + return 0; } } - /* check if the resource is already in use, skip if the device is active because it itself may be in use */ + /* check if the resource is already in use, skip if the + * device is active because it itself may be in use */ if(!dev->active) { if (request_dma(*dma, "pnp")) - return CONFLICT_TYPE_IN_USE; + return 0; free_dma(*dma); } - /* check for warm conflicts */ - if (pnp_check_dma_conflicts(dev, idx, SEARCH_WARM)) - return CONFLICT_TYPE_PNP_WARM; - return 0; -} - - -/** - * pnp_init_resource_table - Resets a resource table to default values. - * @table: pointer to the desired resource table - * - */ - -void pnp_init_resource_table(struct pnp_resource_table *table) -{ - int idx; - for (idx = 0; idx < PNP_MAX_IRQ; idx++) { - table->irq_resource[idx].name = NULL; - table->irq_resource[idx].start = -1; - table->irq_resource[idx].end = -1; - table->irq_resource[idx].flags = IORESOURCE_AUTO; - } - for (idx = 0; idx < PNP_MAX_DMA; idx++) { - table->dma_resource[idx].name = NULL; - table->dma_resource[idx].start = -1; - table->dma_resource[idx].end = -1; - table->dma_resource[idx].flags = IORESOURCE_AUTO; - } - for (idx = 0; idx < PNP_MAX_PORT; idx++) { - table->port_resource[idx].name = NULL; - table->port_resource[idx].start = 0; - table->port_resource[idx].end = 0; - table->port_resource[idx].flags = IORESOURCE_AUTO; - } - for (idx = 0; idx < PNP_MAX_MEM; idx++) { - table->mem_resource[idx].name = NULL; - table->mem_resource[idx].start = 0; - table->mem_resource[idx].end = 0; - table->mem_resource[idx].flags = IORESOURCE_AUTO; - } -} - - -/** - * pnp_generate_rule - Creates a rule table structure based on depnum and device. - * @dev: pointer to the desired device - * @depnum: dependent function, if not valid will return an error - * @rule: pointer to a rule structure to record data to - * - */ - -int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule) -{ - int nport = 0, nirq = 0, ndma = 0, nmem = 0; - struct pnp_resources * res; - struct pnp_port * port; - struct pnp_mem * mem; - struct pnp_irq * irq; - struct pnp_dma * dma; - - if (depnum < 0 || !rule) - return -EINVAL; - - /* independent */ - res = pnp_find_resources(dev, 0); - if (!res) - return -ENODEV; - port = res->port; - mem = res->mem; - irq = res->irq; - dma = res->dma; - while (port){ - rule->port[nport] = port; - nport++; - port = port->next; - } - while (mem){ - rule->mem[nmem] = mem; - nmem++; - mem = mem->next; - } - while (irq){ - rule->irq[nirq] = irq; - nirq++; - irq = irq->next; - } - while (dma){ - rule->dma[ndma] = dma; - ndma++; - dma = dma->next; + /* check for conflicts with other pnp devices */ + pnp_for_each_dev(tdev) { + if (tdev == dev) + continue; + for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { + if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { + if ((tdev->res.dma_resource[tmp].start == *dma)) + return 0; + } + } } - /* dependent */ - if (depnum == 0) - return 1; - res = pnp_find_resources(dev, depnum); - if (!res) - return -ENODEV; - port = res->port; - mem = res->mem; - irq = res->irq; - dma = res->dma; - while (port){ - rule->port[nport] = port; - nport++; - port = port->next; - } - while (mem){ - rule->mem[nmem] = mem; - nmem++; - mem = mem->next; - } - - while (irq){ - rule->irq[nirq] = irq; - nirq++; - irq = irq->next; - } - while (dma){ - rule->dma[ndma] = dma; - ndma++; - dma = dma->next; - } - - /* clear the remaining values */ - for (; nport < PNP_MAX_PORT; nport++) - rule->port[nport] = NULL; - for (; nmem < PNP_MAX_MEM; nmem++) - rule->mem[nmem] = NULL; - for (; nirq < PNP_MAX_IRQ; nirq++) - rule->irq[nirq] = NULL; - for (; ndma < PNP_MAX_DMA; ndma++) - rule->dma[ndma] = NULL; return 1; } -EXPORT_SYMBOL(pnp_build_resource); -EXPORT_SYMBOL(pnp_find_resources); -EXPORT_SYMBOL(pnp_get_max_depnum); -EXPORT_SYMBOL(pnp_add_irq_resource); -EXPORT_SYMBOL(pnp_add_dma_resource); -EXPORT_SYMBOL(pnp_add_port_resource); -EXPORT_SYMBOL(pnp_add_mem_resource); -EXPORT_SYMBOL(pnp_init_resource_table); -EXPORT_SYMBOL(pnp_generate_rule); +EXPORT_SYMBOL(pnp_register_dependent_option); +EXPORT_SYMBOL(pnp_register_independent_option); +EXPORT_SYMBOL(pnp_register_irq_resource); +EXPORT_SYMBOL(pnp_register_dma_resource); +EXPORT_SYMBOL(pnp_register_port_resource); +EXPORT_SYMBOL(pnp_register_mem_resource); /* format is: allowdma0 */ diff -urN linux-2.5.72-bk2/drivers/pnp/support.c linux-2.5.72-bk3/drivers/pnp/support.c --- linux-2.5.72-bk2/drivers/pnp/support.c 2003-06-16 21:19:42.000000000 -0700 +++ linux-2.5.72-bk3/drivers/pnp/support.c 2003-06-20 04:48:11.000000000 -0700 @@ -1,7 +1,7 @@ /* * support.c - provides standard pnp functions for the use of pnp protocol drivers, * - * Copyright 2002 Adam Belay + * Copyright 2003 Adam Belay * * Resource parsing functions are based on those in the linux pnpbios driver. * Copyright Christian Schmidt, Tom Lees, David Hinds, Alan Cox, Thomas Hood, @@ -10,6 +10,7 @@ #include #include +#include #ifdef CONFIG_PNP_DEBUG #define DEBUG @@ -122,7 +123,7 @@ return NULL; /* Blank the resource table values */ - pnp_init_resource_table(res); + pnp_init_resources(res); while ((char *)p < (char *)end) { @@ -250,51 +251,51 @@ * Possible resource reading functions * */ -static void possible_mem(unsigned char *p, int size, int depnum, struct pnp_dev *dev) +static void possible_mem(unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem * mem; mem = pnp_alloc(sizeof(struct pnp_mem)); if (!mem) return; - mem->min = ((p[3] << 8) | p[2]) << 8; - mem->max = ((p[5] << 8) | p[4]) << 8; - mem->align = (p[7] << 8) | p[6]; - mem->size = ((p[9] << 8) | p[8]) << 8; - mem->flags = p[1]; - pnp_add_mem_resource(dev,depnum,mem); + mem->min = ((p[5] << 8) | p[4]) << 8; + mem->max = ((p[7] << 8) | p[6]) << 8; + mem->align = (p[9] << 8) | p[8]; + mem->size = ((p[11] << 8) | p[10]) << 8; + mem->flags = p[3]; + pnp_register_mem_resource(option,mem); return; } -static void possible_mem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev) +static void possible_mem32(unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem * mem; mem = pnp_alloc(sizeof(struct pnp_mem)); if (!mem) return; - mem->min = (p[5] << 24) | (p[4] << 16) | (p[3] << 8) | p[2]; - mem->max = (p[9] << 24) | (p[8] << 16) | (p[7] << 8) | p[6]; - mem->align = (p[13] << 24) | (p[12] << 16) | (p[11] << 8) | p[10]; - mem->size = (p[17] << 24) | (p[16] << 16) | (p[15] << 8) | p[14]; - mem->flags = p[1]; - pnp_add_mem_resource(dev,depnum,mem); + mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; + mem->max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; + mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; + mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; + mem->flags = p[3]; + pnp_register_mem_resource(option,mem); return; } -static void possible_fixed_mem32(unsigned char *p, int size, int depnum, struct pnp_dev *dev) +static void possible_fixed_mem32(unsigned char *p, int size, struct pnp_option *option) { struct pnp_mem * mem; mem = pnp_alloc(sizeof(struct pnp_mem)); if (!mem) return; - mem->min = mem->max = (p[5] << 24) | (p[4] << 16) | (p[3] << 8) | p[2]; - mem->size = (p[9] << 24) | (p[8] << 16) | (p[7] << 8) | p[6]; + mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; + mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; mem->align = 0; - mem->flags = p[1]; - pnp_add_mem_resource(dev,depnum,mem); + mem->flags = p[3]; + pnp_register_mem_resource(option,mem); return; } -static void possible_irq(unsigned char *p, int size, int depnum, struct pnp_dev *dev) +static void possible_irq(unsigned char *p, int size, struct pnp_option *option) { struct pnp_irq * irq; irq = pnp_alloc(sizeof(struct pnp_irq)); @@ -303,11 +304,13 @@ irq->map = (p[2] << 8) | p[1]; if (size > 2) irq->flags = p[3]; - pnp_add_irq_resource(dev,depnum,irq); + else + irq->flags = IORESOURCE_IRQ_HIGHEDGE; + pnp_register_irq_resource(option,irq); return; } -static void possible_dma(unsigned char *p, int size, int depnum, struct pnp_dev *dev) +static void possible_dma(unsigned char *p, int size, struct pnp_option *option) { struct pnp_dma * dma; dma = pnp_alloc(sizeof(struct pnp_dma)); @@ -315,11 +318,11 @@ return; dma->map = p[1]; dma->flags = p[2]; - pnp_add_dma_resource(dev,depnum,dma); + pnp_register_dma_resource(option,dma); return; } -static void possible_port(unsigned char *p, int size, int depnum, struct pnp_dev *dev) +static void possible_port(unsigned char *p, int size, struct pnp_option *option) { struct pnp_port * port; port = pnp_alloc(sizeof(struct pnp_port)); @@ -330,11 +333,11 @@ port->align = p[6]; port->size = p[7]; port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_add_port_resource(dev,depnum,port); + pnp_register_port_resource(option,port); return; } -static void possible_fixed_port(unsigned char *p, int size, int depnum, struct pnp_dev *dev) +static void possible_fixed_port(unsigned char *p, int size, struct pnp_option *option) { struct pnp_port * port; port = pnp_alloc(sizeof(struct pnp_port)); @@ -344,7 +347,7 @@ port->size = p[3]; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_add_port_resource(dev,depnum,port); + pnp_register_port_resource(option,port); return; } @@ -358,12 +361,14 @@ unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev *dev) { - int len, depnum = 0, dependent = 0; + int len, priority = 0; + struct pnp_option *option; if (!p) return NULL; - if (pnp_build_resource(dev, 0) == NULL) + option = pnp_register_independent_option(dev); + if (!option) return NULL; while ((char *)p < (char *)end) { @@ -375,21 +380,21 @@ { if (len != 9) goto lrg_err; - possible_mem(p,len,depnum,dev); + possible_mem(p,len,option); break; } case LARGE_TAG_MEM32: { if (len != 17) goto lrg_err; - possible_mem32(p,len,depnum,dev); + possible_mem32(p,len,option); break; } case LARGE_TAG_FIXEDMEM32: { if (len != 9) goto lrg_err; - possible_fixed_mem32(p,len,depnum,dev); + possible_fixed_mem32(p,len,option); break; } default: /* an unkown tag */ @@ -410,46 +415,46 @@ { if (len < 2 || len > 3) goto sm_err; - possible_irq(p,len,depnum,dev); + possible_irq(p,len,option); break; } case SMALL_TAG_DMA: { if (len != 2) goto sm_err; - possible_dma(p,len,depnum,dev); + possible_dma(p,len,option); break; } case SMALL_TAG_STARTDEP: { if (len > 1) goto sm_err; - dependent = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; + priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE; if (len > 0) - dependent = 0x100 | p[1]; - pnp_build_resource(dev,dependent); - depnum = pnp_get_max_depnum(dev); + priority = 0x100 | p[1]; + option = pnp_register_dependent_option(dev, priority); + if (!option) + return NULL; break; } case SMALL_TAG_ENDDEP: { if (len != 0) goto sm_err; - depnum = 0; break; } case SMALL_TAG_PORT: { if (len != 7) goto sm_err; - possible_port(p,len,depnum,dev); + possible_port(p,len,option); break; } case SMALL_TAG_FIXEDPORT: { if (len != 3) goto sm_err; - possible_fixed_port(p,len,depnum,dev); + possible_fixed_port(p,len,option); break; } case SMALL_TAG_END: @@ -481,12 +486,12 @@ { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; - p[2] = (base >> 8) & 0xff; - p[3] = ((base >> 8) >> 8) & 0xff; p[4] = (base >> 8) & 0xff; p[5] = ((base >> 8) >> 8) & 0xff; - p[8] = (len >> 8) & 0xff; - p[9] = ((len >> 8) >> 8) & 0xff; + p[6] = (base >> 8) & 0xff; + p[7] = ((base >> 8) >> 8) & 0xff; + p[10] = (len >> 8) & 0xff; + p[11] = ((len >> 8) >> 8) & 0xff; return; } @@ -494,32 +499,32 @@ { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; - p[2] = base & 0xff; - p[3] = (base >> 8) & 0xff; - p[4] = (base >> 16) & 0xff; - p[5] = (base >> 24) & 0xff; - p[6] = base & 0xff; - p[7] = (base >> 8) & 0xff; - p[8] = (base >> 16) & 0xff; - p[9] = (base >> 24) & 0xff; - p[14] = len & 0xff; - p[15] = (len >> 8) & 0xff; - p[16] = (len >> 16) & 0xff; - p[17] = (len >> 24) & 0xff; + p[4] = base & 0xff; + p[5] = (base >> 8) & 0xff; + p[6] = (base >> 16) & 0xff; + p[7] = (base >> 24) & 0xff; + p[8] = base & 0xff; + p[9] = (base >> 8) & 0xff; + p[10] = (base >> 16) & 0xff; + p[11] = (base >> 24) & 0xff; + p[16] = len & 0xff; + p[17] = (len >> 8) & 0xff; + p[18] = (len >> 16) & 0xff; + p[19] = (len >> 24) & 0xff; return; } static void write_fixed_mem32(unsigned char *p, struct resource * res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; - p[2] = base & 0xff; - p[3] = (base >> 8) & 0xff; - p[4] = (base >> 16) & 0xff; - p[5] = (base >> 24) & 0xff; - p[6] = len & 0xff; - p[7] = (len >> 8) & 0xff; - p[8] = (len >> 16) & 0xff; - p[9] = (len >> 24) & 0xff; + p[4] = base & 0xff; + p[5] = (base >> 8) & 0xff; + p[6] = (base >> 16) & 0xff; + p[7] = (base >> 24) & 0xff; + p[8] = len & 0xff; + p[9] = (len >> 8) & 0xff; + p[10] = (len >> 16) & 0xff; + p[11] = (len >> 24) & 0xff; return; } @@ -630,7 +635,7 @@ { if (len != 2) goto sm_err; - write_dma(p, &res->dma_resource[irq]); + write_dma(p, &res->dma_resource[dma]); dma++; break; } diff -urN linux-2.5.72-bk2/drivers/serial/8250_pnp.c linux-2.5.72-bk3/drivers/serial/8250_pnp.c --- linux-2.5.72-bk2/drivers/serial/8250_pnp.c 2003-06-16 21:19:39.000000000 -0700 +++ linux-2.5.72-bk3/drivers/serial/8250_pnp.c 2003-06-20 04:48:12.000000000 -0700 @@ -315,19 +315,6 @@ MODULE_DEVICE_TABLE(pnp, pnp_dev_table); -static inline void avoid_irq_share(struct pnp_dev *dev) -{ - unsigned int map = 0x1FF8; - struct pnp_irq *irq; - struct pnp_resources *res = dev->possible; - - serial8250_get_irq_map(&map); - - for ( ; res; res = res->dep) - for (irq = res->irq; irq; irq = irq->next) - irq->map = map; -} - static char *modem_names[] __devinitdata = { "MODEM", "Modem", "modem", "FAX", "Fax", "fax", "56K", "56k", "K56", "33.6", "28.8", "14.4", @@ -346,6 +333,29 @@ return 0; } +static int __devinit check_resources(struct pnp_option *option) +{ + struct pnp_option *tmp; + if (!option) + return 0; + + for (tmp = option; tmp; tmp = tmp->next) { + struct pnp_port *port; + for (port = tmp->port; port; port = port->next) + if ((port->size == 8) && + ((port->min == 0x2f8) || + (port->min == 0x3f8) || + (port->min == 0x2e8) || +#ifdef CONFIG_X86_PC9800 + (port->min == 0x8b0) || +#endif + (port->min == 0x3e8))) + return 1; + } + + return 0; +} + /* * Given a complete unknown PnP device, try to use some heuristics to * detect modems. Currently use such heuristic set: @@ -357,30 +367,16 @@ * PnP modems, alternatively we must hardcode all modems in pnp_devices[] * table. */ -static int serial_pnp_guess_board(struct pnp_dev *dev, int *flags) +static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags) { - struct pnp_resources *res = dev->possible; - struct pnp_resources *resa; - if (!(check_name(dev->dev.name) || (dev->card && check_name(dev->card->dev.name)))) return -ENODEV; - if (!res) - return -ENODEV; + if (check_resources(dev->independent)) + return 0; - for (resa = res->dep; resa; resa = resa->dep) { - struct pnp_port *port; - for (port = res->port; port; port = port->next) - if ((port->size == 8) && - ((port->min == 0x2f8) || - (port->min == 0x3f8) || - (port->min == 0x2e8) || -#ifdef CONFIG_X86_PC9800 - (port->min == 0x8b0) || -#endif - (port->min == 0x3e8))) - return 0; - } + if (check_resources(dev->dependent)) + return 0; return -ENODEV; } @@ -395,8 +391,6 @@ if (ret < 0) return ret; } - if (flags & SPCI_FL_NO_SHIRQ) - avoid_irq_share(dev); memset(&serial_req, 0, sizeof(serial_req)); serial_req.irq = pnp_irq(dev,0); serial_req.port = pnp_port_start(dev, 0); diff -urN linux-2.5.72-bk2/include/asm-alpha/smp.h linux-2.5.72-bk3/include/asm-alpha/smp.h --- linux-2.5.72-bk2/include/asm-alpha/smp.h 2003-06-16 21:20:23.000000000 -0700 +++ linux-2.5.72-bk3/include/asm-alpha/smp.h 2003-06-20 04:48:12.000000000 -0700 @@ -57,6 +57,15 @@ return hweight64(cpu_online_map); } +extern inline int +any_online_cpu(unsigned int mask) +{ + if (mask & cpu_online_map) + return __ffs(mask & cpu_online_map); + + return -1; +} + extern int smp_call_function_on_cpu(void (*func) (void *info), void *info,int retry, int wait, unsigned long cpu); #else /* CONFIG_SMP */ diff -urN linux-2.5.72-bk2/include/asm-alpha/unistd.h linux-2.5.72-bk3/include/asm-alpha/unistd.h --- linux-2.5.72-bk2/include/asm-alpha/unistd.h 2003-06-16 21:20:00.000000000 -0700 +++ linux-2.5.72-bk3/include/asm-alpha/unistd.h 2003-06-20 04:48:12.000000000 -0700 @@ -593,13 +593,7 @@ return sys_read(fd, buf, nr); } -extern int __kernel_execve(char *, char **, char **, struct pt_regs *); -static inline long execve(char * file, char ** argvp, char ** envp) -{ - struct pt_regs regs; - memset(®s, 0, sizeof(regs)); - return __kernel_execve(file, argvp, envp, ®s); -} +extern long execve(char *, char **, char **); extern long sys_setsid(void); static inline long setsid(void) diff -urN linux-2.5.72-bk2/include/asm-alpha/xor.h linux-2.5.72-bk3/include/asm-alpha/xor.h --- linux-2.5.72-bk2/include/asm-alpha/xor.h 2003-06-16 21:20:20.000000000 -0700 +++ linux-2.5.72-bk3/include/asm-alpha/xor.h 2003-06-20 04:48:12.000000000 -0700 @@ -822,19 +822,19 @@ "); static struct xor_block_template xor_block_alpha = { - name: "alpha", - do_2: xor_alpha_2, - do_3: xor_alpha_3, - do_4: xor_alpha_4, - do_5: xor_alpha_5, + .name = "alpha", + .do_2 = xor_alpha_2, + .do_3 = xor_alpha_3, + .do_4 = xor_alpha_4, + .do_5 = xor_alpha_5, }; static struct xor_block_template xor_block_alpha_prefetch = { - name: "alpha prefetch", - do_2: xor_alpha_prefetch_2, - do_3: xor_alpha_prefetch_3, - do_4: xor_alpha_prefetch_4, - do_5: xor_alpha_prefetch_5, + .name = "alpha prefetch", + .do_2 = xor_alpha_prefetch_2, + .do_3 = xor_alpha_prefetch_3, + .do_4 = xor_alpha_prefetch_4, + .do_5 = xor_alpha_prefetch_5, }; /* For grins, also test the generic routines. */ diff -urN linux-2.5.72-bk2/include/linux/firmware.h linux-2.5.72-bk3/include/linux/firmware.h --- linux-2.5.72-bk2/include/linux/firmware.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.72-bk3/include/linux/firmware.h 2003-06-20 04:48:12.000000000 -0700 @@ -0,0 +1,19 @@ +#ifndef _LINUX_FIRMWARE_H +#define _LINUX_FIRMWARE_H +#include +#include +#define FIRMWARE_NAME_MAX 30 +struct firmware { + size_t size; + u8 *data; +}; +int request_firmware(const struct firmware **fw, const char *name, + struct device *device); +int request_firmware_nowait( + struct module *module, + const char *name, struct device *device, void *context, + void (*cont)(const struct firmware *fw, void *context)); + +void release_firmware(const struct firmware *fw); +void register_firmware(const char *name, const u8 *data, size_t size); +#endif diff -urN linux-2.5.72-bk2/include/linux/isdn.h linux-2.5.72-bk3/include/linux/isdn.h --- linux-2.5.72-bk2/include/linux/isdn.h 2003-06-16 21:20:27.000000000 -0700 +++ linux-2.5.72-bk3/include/linux/isdn.h 2003-06-20 04:48:12.000000000 -0700 @@ -283,7 +283,7 @@ #endif int mdmcmdl; /* Length of Modem-Commandbuffer */ int pluscount; /* Counter for +++ sequence */ - int lastplus; /* Timestamp of last + */ + unsigned long lastplus; /* Timestamp of last + */ char mdmcmd[255]; /* Modem-Commandbuffer */ unsigned int charge; /* Charge units of current connection */ } atemu; diff -urN linux-2.5.72-bk2/include/linux/isdn_ppp.h linux-2.5.72-bk3/include/linux/isdn_ppp.h --- linux-2.5.72-bk2/include/linux/isdn_ppp.h 2003-06-16 21:19:43.000000000 -0700 +++ linux-2.5.72-bk3/include/linux/isdn_ppp.h 2003-06-20 04:48:12.000000000 -0700 @@ -95,7 +95,8 @@ * check the original include for more information */ struct isdn_ppp_compressor { - struct isdn_ppp_compressor *next, *prev; + struct module *owner; + struct list_head list; int num; /* CCP compression protocol number */ void *(*alloc) (struct isdn_ppp_comp_data *); diff -urN linux-2.5.72-bk2/include/linux/netdevice.h linux-2.5.72-bk3/include/linux/netdevice.h --- linux-2.5.72-bk2/include/linux/netdevice.h 2003-06-16 21:20:23.000000000 -0700 +++ linux-2.5.72-bk3/include/linux/netdevice.h 2003-06-20 04:48:12.000000000 -0700 @@ -195,8 +195,14 @@ int hh_len; /* length of header */ int (*hh_output)(struct sk_buff *skb); rwlock_t hh_lock; + /* cached hardware header; allow for machine alignment needs. */ - unsigned long hh_data[16/sizeof(unsigned long)]; +#define HH_DATA_MOD 16 +#define HH_DATA_OFF(__len) \ + (HH_DATA_MOD - ((__len) & (HH_DATA_MOD - 1))) +#define HH_DATA_ALIGN(__len) \ + (((__len)+(HH_DATA_MOD-1))&~(HH_DATA_MOD - 1)) + unsigned long hh_data[HH_DATA_ALIGN(LL_MAX_HEADER)]; }; /* These flag bits are private to the generic network queueing diff -urN linux-2.5.72-bk2/include/linux/netfilter_arp.h linux-2.5.72-bk3/include/linux/netfilter_arp.h --- linux-2.5.72-bk2/include/linux/netfilter_arp.h 2003-06-16 21:19:40.000000000 -0700 +++ linux-2.5.72-bk3/include/linux/netfilter_arp.h 2003-06-20 04:48:12.000000000 -0700 @@ -14,6 +14,7 @@ /* ARP Hooks */ #define NF_ARP_IN 0 #define NF_ARP_OUT 1 -#define NF_ARP_NUMHOOKS 2 +#define NF_ARP_FORWARD 2 +#define NF_ARP_NUMHOOKS 3 #endif /* __LINUX_ARP_NETFILTER_H */ diff -urN linux-2.5.72-bk2/include/linux/pci_ids.h linux-2.5.72-bk3/include/linux/pci_ids.h --- linux-2.5.72-bk2/include/linux/pci_ids.h 2003-06-16 21:20:00.000000000 -0700 +++ linux-2.5.72-bk3/include/linux/pci_ids.h 2003-06-20 04:48:12.000000000 -0700 @@ -602,6 +602,8 @@ #define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 #define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A #define PCI_DEVICE_ID_HP_DIVA_MAESTRO 0x104B +#define PCI_DEVICE_ID_HP_REO_SBA 0x10f0 +#define PCI_DEVICE_ID_HP_REO_IOC 0x10f1 #define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b #define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223 #define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226 diff -urN linux-2.5.72-bk2/include/linux/pnp.h linux-2.5.72-bk3/include/linux/pnp.h --- linux-2.5.72-bk2/include/linux/pnp.h 2003-06-16 21:20:27.000000000 -0700 +++ linux-2.5.72-bk3/include/linux/pnp.h 2003-06-20 04:48:12.000000000 -0700 @@ -102,22 +102,13 @@ #define PNP_RES_PRIORITY_FUNCTIONAL 2 #define PNP_RES_PRIORITY_INVALID 65535 -struct pnp_resources { +struct pnp_option { unsigned short priority; /* priority */ struct pnp_port *port; /* first port */ struct pnp_irq *irq; /* first IRQ */ struct pnp_dma *dma; /* first DMA */ struct pnp_mem *mem; /* first memory resource */ - struct pnp_dev *dev; /* parent */ - struct pnp_resources *dep; /* dependent resources */ -}; - -struct pnp_rule_table { - int depnum; - struct pnp_port *port[PNP_MAX_PORT]; - struct pnp_irq *irq[PNP_MAX_IRQ]; - struct pnp_dma *dma[PNP_MAX_DMA]; - struct pnp_mem *mem[PNP_MAX_MEM]; + struct pnp_option *next; /* used to chain dependent resources */ }; struct pnp_resource_table { @@ -187,8 +178,6 @@ struct pnp_dev { struct device dev; /* Driver Model device interface */ unsigned char number; /* used as an index, must be unique */ - int active; - int capabilities; int status; struct list_head global_list; /* node in global list of devices */ @@ -201,11 +190,13 @@ struct pnp_driver * driver; struct pnp_card_link * card_link; - struct pnp_id * id; /* supported EISA IDs*/ - struct pnp_resource_table res; /* contains the currently chosen resources */ - struct pnp_resources * possible; /* a list of possible resources */ - struct pnp_rule_table * rule; /* the current possible resource set */ - int config_mode; /* flags that determine how the device's resources should be configured */ + struct pnp_id * id; /* supported EISA IDs*/ + + int active; + int capabilities; + struct pnp_option * independent; + struct pnp_option * dependent; + struct pnp_resource_table res; void * protocol_data; /* Used to store protocol specific data */ unsigned short regs; /* ISAPnP: supported registers */ @@ -252,11 +243,9 @@ void (*quirk_function)(struct pnp_dev *dev); /* fixup function */ }; -/* config modes */ -#define PNP_CONFIG_AUTO 0x0001 /* Use the Resource Configuration Engine to determine resource settings */ -#define PNP_CONFIG_MANUAL 0x0002 /* the config has been manually specified */ -#define PNP_CONFIG_FORCE 0x0004 /* disables validity checking */ -#define PNP_CONFIG_INVALID 0x0008 /* If this flag is set, the pnp layer will refuse to activate the device */ +/* config parameters */ +#define PNP_CONFIG_NORMAL 0x0001 +#define PNP_CONFIG_FORCE 0x0002 /* disables validity checking */ /* capabilities */ #define PNP_READ 0x0001 @@ -271,7 +260,7 @@ ((dev)->capabilities & PNP_WRITE)) #define pnp_can_disable(dev) (((dev)->protocol) && ((dev)->protocol->disable) && \ ((dev)->capabilities & PNP_DISABLE)) -#define pnp_can_configure(dev) ((!(dev)->active) && ((dev)->config_mode & PNP_CONFIG_AUTO) && \ +#define pnp_can_configure(dev) ((!(dev)->active) && \ ((dev)->capabilities & PNP_CONFIGURABLE)) #ifdef CONFIG_ISAPNP @@ -383,7 +372,7 @@ #if defined(CONFIG_PNP) -/* core */ +/* device management */ int pnp_register_protocol(struct pnp_protocol *protocol); void pnp_unregister_protocol(struct pnp_protocol *protocol); int pnp_add_device(struct pnp_dev *dev); @@ -392,7 +381,7 @@ void pnp_device_detach(struct pnp_dev *pnp_dev); extern struct list_head pnp_global; -/* card */ +/* multidevice card support */ int pnp_add_card(struct pnp_card *card); void pnp_remove_card(struct pnp_card *card); int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); @@ -404,41 +393,35 @@ void pnp_unregister_card_driver(struct pnp_card_driver * drv); extern struct list_head pnp_cards; -/* resource */ -struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent); -struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum); -int pnp_get_max_depnum(struct pnp_dev *dev); -int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data); -int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_dma *data); -int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_port *data); -int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_mem *data); -void pnp_init_resource_table(struct pnp_resource_table *table); -int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule); - -/* manager */ +/* resource management */ +struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev); +struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int priority); +int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data); +int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data); +int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data); +int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data); +void pnp_init_resources(struct pnp_resource_table *table); +int pnp_assign_resources(struct pnp_dev *dev, int depnum); +int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode); +int pnp_auto_config_dev(struct pnp_dev *dev); +int pnp_validate_config(struct pnp_dev *dev); int pnp_activate_dev(struct pnp_dev *dev); int pnp_disable_dev(struct pnp_dev *dev); void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size); -int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode); -int pnp_auto_config_dev(struct pnp_dev *dev); - -/* driver */ -int compare_pnp_id(struct pnp_id * pos, const char * id); -int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev); -int pnp_register_driver(struct pnp_driver *drv); -void pnp_unregister_driver(struct pnp_driver *drv); -/* support */ +/* protocol helpers */ int pnp_is_active(struct pnp_dev * dev); unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res); unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev * dev); unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res); +int compare_pnp_id(struct pnp_id * pos, const char * id); +int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev); +int pnp_register_driver(struct pnp_driver *drv); +void pnp_unregister_driver(struct pnp_driver *drv); #else -/* just in case anyone decides to call these without PnP Support Enabled */ - -/* core */ +/* device management */ static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return -ENODEV; } static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { } static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; } @@ -447,7 +430,7 @@ static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; } static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; } -/* card */ +/* multidevice card support */ static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; } static inline void pnp_remove_card(struct pnp_card *card) { ; } static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; } @@ -458,35 +441,31 @@ static inline int pnp_register_card_driver(struct pnp_card_driver * drv) { return -ENODEV; } static inline void pnp_unregister_card_driver(struct pnp_card_driver * drv) { ; } -/* resource */ -static inline struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) { return NULL; } -static inline struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) { return NULL; } -static inline int pnp_get_max_depnum(struct pnp_dev *dev) { return -ENODEV; } -static inline int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; } -static inline int pnp_add_dma_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; } -static inline int pnp_add_port_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; } -static inline int pnp_add_mem_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data) { return -ENODEV; } -static inline void pnp_init_resource_table(struct pnp_resource_table *table) { ; } -static inline int pnp_generate_rule(struct pnp_dev * dev, int depnum, struct pnp_rule_table * rule) { return -ENODEV; } - -/* manager */ -static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; } -static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; } -static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { ; } +/* resource management */ +static inline struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev) { return NULL; } +static inline struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int priority) { return NULL; } +static inline int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) { return -ENODEV; } +static inline int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) { return -ENODEV; } +static inline int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) { return -ENODEV; } +static inline int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; } +static inline void pnp_init_resources(struct pnp_resource_table *table) { } +static inline int pnp_assign_resources(struct pnp_dev *dev, int depnum) { return -ENODEV; } static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; } static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } +static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; } +static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; } +static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; } +static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { } -/* driver */ -static inline int compare_pnp_id(struct list_head * id_list, const char * id) { return -ENODEV; } -static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; } -static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; } -static inline void pnp_unregister_driver(struct pnp_driver *drv) { ; } - -/* support */ -static inline int pnp_is_active(struct pnp_dev * dev) { return -ENODEV; } +/* protocol helpers */ +static inline int pnp_is_active(struct pnp_dev * dev) { return 0; } static inline unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) { return NULL; } static inline unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char * end, struct pnp_dev * dev) { return NULL; } static inline unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) { return NULL; } +static inline int compare_pnp_id(struct pnp_id * pos, const char * id) { return -ENODEV; } +static inline int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { return -ENODEV; } +static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; } +static inline void pnp_unregister_driver(struct pnp_driver *drv) { ; } #endif /* CONFIG_PNP */ diff -urN linux-2.5.72-bk2/include/linux/skbuff.h linux-2.5.72-bk3/include/linux/skbuff.h --- linux-2.5.72-bk2/include/linux/skbuff.h 2003-06-20 04:48:06.000000000 -0700 +++ linux-2.5.72-bk3/include/linux/skbuff.h 2003-06-20 04:48:12.000000000 -0700 @@ -803,12 +803,9 @@ skb_shinfo(skb)->nr_frags = i+1; } -#define SKB_PAGE_ASSERT(skb) do { if (skb_shinfo(skb)->nr_frags) \ - BUG(); } while (0) -#define SKB_FRAG_ASSERT(skb) do { if (skb_shinfo(skb)->frag_list) \ - BUG(); } while (0) -#define SKB_LINEAR_ASSERT(skb) do { if (skb_is_nonlinear(skb)) \ - BUG(); } while (0) +#define SKB_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags) +#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_shinfo(skb)->frag_list) +#define SKB_LINEAR_ASSERT(skb) BUG_ON(skb_is_nonlinear(skb)) /* * Add data to an sk_buff @@ -837,7 +834,7 @@ SKB_LINEAR_ASSERT(skb); skb->tail += len; skb->len += len; - if (skb->tail>skb->end) + if (unlikely(skb->tail>skb->end)) skb_over_panic(skb, len, current_text_addr()); return tmp; } @@ -862,7 +859,7 @@ { skb->data -= len; skb->len += len; - if (skb->datahead) + if (unlikely(skb->datahead)) skb_under_panic(skb, len, current_text_addr()); return skb->data; } @@ -870,8 +867,7 @@ static inline char *__skb_pull(struct sk_buff *skb, unsigned int len) { skb->len -= len; - if (skb->len < skb->data_len) - BUG(); + BUG_ON(skb->len < skb->data_len); return skb->data += len; } @@ -1137,8 +1133,7 @@ static inline void *kmap_skb_frag(const skb_frag_t *frag) { #ifdef CONFIG_HIGHMEM - if (in_irq()) - BUG(); + BUG_ON(in_irq()); local_bh_disable(); #endif @@ -1154,9 +1149,9 @@ } #define skb_queue_walk(queue, skb) \ - for (skb = (queue)->next; \ + for (skb = (queue)->next, prefetch(skb->next); \ (skb != (struct sk_buff *)(queue)); \ - skb = skb->next) + skb = skb->next, prefetch(skb->next)) extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, diff -urN linux-2.5.72-bk2/include/linux/sysdev.h linux-2.5.72-bk3/include/linux/sysdev.h --- linux-2.5.72-bk2/include/linux/sysdev.h 2003-06-16 21:20:05.000000000 -0700 +++ linux-2.5.72-bk3/include/linux/sysdev.h 2003-06-20 04:48:12.000000000 -0700 @@ -72,7 +72,6 @@ u32 id; struct sysdev_class * cls; struct kobject kobj; - struct list_head entry; }; extern int sys_device_register(struct sys_device *); diff -urN linux-2.5.72-bk2/kernel/ksyms.c linux-2.5.72-bk3/kernel/ksyms.c --- linux-2.5.72-bk2/kernel/ksyms.c 2003-06-20 04:48:06.000000000 -0700 +++ linux-2.5.72-bk3/kernel/ksyms.c 2003-06-20 04:48:12.000000000 -0700 @@ -592,7 +592,6 @@ /* init task, for moving kthread roots - ought to export a function ?? */ EXPORT_SYMBOL(init_task); -EXPORT_SYMBOL(init_thread_union); EXPORT_SYMBOL(tasklist_lock); EXPORT_SYMBOL(find_task_by_pid); diff -urN linux-2.5.72-bk2/lib/kobject.c linux-2.5.72-bk3/lib/kobject.c --- linux-2.5.72-bk2/lib/kobject.c 2003-06-16 21:20:22.000000000 -0700 +++ linux-2.5.72-bk3/lib/kobject.c 2003-06-20 04:48:12.000000000 -0700 @@ -100,6 +100,9 @@ #define BUFFER_SIZE 1024 /* should be enough memory for the env */ #define NUM_ENVP 32 /* number of env pointers */ +static unsigned long sequence_num; +static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED; + static void kset_hotplug(const char *action, struct kset *kset, struct kobject *kobj) { @@ -112,6 +115,7 @@ int kobj_path_length; char *kobj_path = NULL; char *name = NULL; + unsigned long seq; /* If the kset has a filter operation, call it. If it returns failure, no hotplug event is required. */ @@ -152,6 +156,13 @@ envp [i++] = scratch; scratch += sprintf(scratch, "ACTION=%s", action) + 1; + spin_lock(&sequence_lock); + seq = sequence_num++; + spin_unlock(&sequence_lock); + + envp [i++] = scratch; + scratch += sprintf(scratch, "SEQNUM=%ld", seq) + 1; + kobj_path_length = get_kobj_path_length (kset, kobj); kobj_path = kmalloc (kobj_path_length, GFP_KERNEL); if (!kobj_path) diff -urN linux-2.5.72-bk2/net/bridge/br_netfilter.c linux-2.5.72-bk3/net/bridge/br_netfilter.c --- linux-2.5.72-bk2/net/bridge/br_netfilter.c 2003-06-16 21:20:26.000000000 -0700 +++ linux-2.5.72-bk3/net/bridge/br_netfilter.c 2003-06-20 04:48:12.000000000 -0700 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -304,31 +305,36 @@ return NF_ACCEPT; } - /* PF_BRIDGE/FORWARD *************************************************/ static int br_nf_forward_finish(struct sk_buff *skb) { struct nf_bridge_info *nf_bridge = skb->nf_bridge; + struct net_device *in; #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug ^= (1 << NF_BR_FORWARD); #endif - if (nf_bridge->mask & BRNF_PKT_TYPE) { - skb->pkt_type = PACKET_OTHERHOST; - nf_bridge->mask ^= BRNF_PKT_TYPE; + if (skb->protocol == __constant_htons(ETH_P_IP)) { + in = nf_bridge->physindev; + if (nf_bridge->mask & BRNF_PKT_TYPE) { + skb->pkt_type = PACKET_OTHERHOST; + nf_bridge->mask ^= BRNF_PKT_TYPE; + } + } else { + in = *((struct net_device **)(skb->cb)); } - NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, nf_bridge->physindev, + NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, skb->dev, br_forward_finish, 1); - return 0; } -/* This is the 'purely bridged' case. We pass the packet to +/* This is the 'purely bridged' case. For IP, we pass the packet to * netfilter with indev and outdev set to the bridge device, * but we are still able to filter on the 'real' indev/outdev - * because of the ipt_physdev.c module. + * because of the ipt_physdev.c module. For ARP, indev and outdev are the + * bridge ports. */ static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, @@ -337,24 +343,33 @@ struct sk_buff *skb = *pskb; struct nf_bridge_info *nf_bridge; - if (skb->protocol != __constant_htons(ETH_P_IP)) + if (skb->protocol != __constant_htons(ETH_P_IP) && + skb->protocol != __constant_htons(ETH_P_ARP)) return NF_ACCEPT; #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug ^= (1 << NF_BR_FORWARD); #endif + if (skb->protocol == __constant_htons(ETH_P_IP)) { + nf_bridge = skb->nf_bridge; + if (skb->pkt_type == PACKET_OTHERHOST) { + skb->pkt_type = PACKET_HOST; + nf_bridge->mask |= BRNF_PKT_TYPE; + } - nf_bridge = skb->nf_bridge; - if (skb->pkt_type == PACKET_OTHERHOST) { - skb->pkt_type = PACKET_HOST; - nf_bridge->mask |= BRNF_PKT_TYPE; - } + /* The physdev module checks on this */ + nf_bridge->mask |= BRNF_BRIDGED; + nf_bridge->physoutdev = skb->dev; - nf_bridge->mask |= BRNF_BRIDGED; /* The physdev module checks on this */ - nf_bridge->physoutdev = skb->dev; + NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(in), + bridge_parent(out), br_nf_forward_finish); + } else { + struct net_device **d = (struct net_device **)(skb->cb); - NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(nf_bridge->physindev), - bridge_parent(skb->dev), br_nf_forward_finish); + *d = (struct net_device *)in; + NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in, + (struct net_device *)out, br_nf_forward_finish); + } return NF_STOLEN; } diff -urN linux-2.5.72-bk2/net/core/flow.c linux-2.5.72-bk3/net/core/flow.c --- linux-2.5.72-bk2/net/core/flow.c 2003-06-16 21:19:39.000000000 -0700 +++ linux-2.5.72-bk3/net/core/flow.c 2003-06-20 04:48:12.000000000 -0700 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -301,7 +300,8 @@ local_bh_disable(); smp_call_function(flow_cache_flush_per_cpu, &info, 1, 0); - flow_cache_flush_tasklet((unsigned long)&info); + if (test_bit(smp_processor_id(), &info.cpumap)) + flow_cache_flush_tasklet((unsigned long)&info); local_bh_enable(); wait_for_completion(&info.completion); @@ -309,13 +309,11 @@ up(&flow_flush_sem); } -static void __devinit flow_cache_cpu_online(int cpu) +static int __devinit flow_cache_cpu_prepare(int cpu) { struct tasklet_struct *tasklet; unsigned long order; - flow_hash_rnd_recalc(cpu) = 1; - for (order = 0; (PAGE_SIZE << order) < (sizeof(struct flow_cache_entry *)*flow_hash_size); @@ -325,15 +323,28 @@ flow_table(cpu) = (struct flow_cache_entry **) __get_free_pages(GFP_KERNEL, order); + if (!flow_table(cpu)) + return NOTIFY_BAD; + memset(flow_table(cpu), 0, PAGE_SIZE << order); + flow_hash_rnd_recalc(cpu) = 1; + flow_count(cpu) = 0; + tasklet = flow_flush_tasklet(cpu); tasklet_init(tasklet, flow_cache_flush_tasklet, 0); + return NOTIFY_OK; +} + +static int __devinit flow_cache_cpu_online(int cpu) +{ down(&flow_cache_cpu_sem); set_bit(cpu, &flow_cache_cpu_map); flow_cache_cpu_count++; up(&flow_cache_cpu_sem); + + return NOTIFY_OK; } static int __devinit flow_cache_cpu_notify(struct notifier_block *self, @@ -342,7 +353,10 @@ unsigned long cpu = (unsigned long)cpu; switch (action) { case CPU_UP_PREPARE: - flow_cache_cpu_online(cpu); + return flow_cache_cpu_prepare(cpu); + break; + case CPU_ONLINE: + return flow_cache_cpu_online(cpu); break; } return NOTIFY_OK; @@ -354,6 +368,8 @@ static int __init flow_cache_init(void) { + int i; + flow_cachep = kmem_cache_create("flow_cache", sizeof(struct flow_cache_entry), 0, SLAB_HWCACHE_ALIGN, @@ -371,8 +387,12 @@ flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; add_timer(&flow_hash_rnd_timer); - flow_cache_cpu_online(smp_processor_id()); register_cpu_notifier(&flow_cache_cpu_nb); + for (i = 0; i < NR_CPUS; i++) + if (cpu_online(i)) { + flow_cache_cpu_prepare(i); + flow_cache_cpu_online(i); + } return 0; } diff -urN linux-2.5.72-bk2/net/ethernet/eth.c linux-2.5.72-bk3/net/ethernet/eth.c --- linux-2.5.72-bk2/net/ethernet/eth.c 2003-06-16 21:20:02.000000000 -0700 +++ linux-2.5.72-bk3/net/ethernet/eth.c 2003-06-20 04:48:12.000000000 -0700 @@ -216,9 +216,12 @@ int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh) { unsigned short type = hh->hh_type; - struct ethhdr *eth = (struct ethhdr*)(((u8*)hh->hh_data) + 2); + struct ethhdr *eth; struct net_device *dev = neigh->dev; + eth = (struct ethhdr*) + (((u8*)hh->hh_data) + (HH_DATA_OFF(sizeof(*eth)))); + if (type == __constant_htons(ETH_P_802_3)) return -1; @@ -235,5 +238,6 @@ void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr) { - memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len); + memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)), + haddr, dev->addr_len); } diff -urN linux-2.5.72-bk2/net/ipv4/ip_output.c linux-2.5.72-bk3/net/ipv4/ip_output.c --- linux-2.5.72-bk2/net/ipv4/ip_output.c 2003-06-16 21:20:26.000000000 -0700 +++ linux-2.5.72-bk3/net/ipv4/ip_output.c 2003-06-20 04:48:12.000000000 -0700 @@ -193,8 +193,11 @@ #endif /*CONFIG_NETFILTER_DEBUG*/ if (hh) { + int hh_alen; + read_lock_bh(&hh->hh_lock); - memcpy(skb->data - 16, hh->hh_data, 16); + hh_alen = HH_DATA_ALIGN(hh->hh_len); + memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); read_unlock_bh(&hh->hh_lock); skb_push(skb, hh->hh_len); return hh->hh_output(skb); diff -urN linux-2.5.72-bk2/net/ipv4/netfilter/arptable_filter.c linux-2.5.72-bk3/net/ipv4/netfilter/arptable_filter.c --- linux-2.5.72-bk2/net/ipv4/netfilter/arptable_filter.c 2003-06-16 21:19:37.000000000 -0700 +++ linux-2.5.72-bk3/net/ipv4/netfilter/arptable_filter.c 2003-06-20 04:48:12.000000000 -0700 @@ -8,7 +8,8 @@ #include #include -#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT)) +#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ + (1 << NF_ARP_FORWARD)) /* Standard entry. */ struct arpt_standard @@ -32,15 +33,17 @@ static struct { struct arpt_replace repl; - struct arpt_standard entries[2]; + struct arpt_standard entries[3]; struct arpt_error term; } initial_table __initdata -= { { "filter", FILTER_VALID_HOOKS, 3, - sizeof(struct arpt_standard) * 2 + sizeof(struct arpt_error), += { { "filter", FILTER_VALID_HOOKS, 4, + sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error), { [NF_ARP_IN] = 0, - [NF_ARP_OUT] = sizeof(struct arpt_standard) }, + [NF_ARP_OUT] = sizeof(struct arpt_standard), + [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), }, { [NF_ARP_IN] = 0, - [NF_ARP_OUT] = sizeof(struct arpt_standard), }, + [NF_ARP_OUT] = sizeof(struct arpt_standard), + [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), }, 0, NULL, { } }, { /* ARP_IN */ @@ -84,6 +87,27 @@ { 0, 0 }, { } }, { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } }, -NF_ACCEPT - 1 } + }, + /* ARP_FORWARD */ + { + { + { + { 0 }, { 0 }, { 0 }, { 0 }, + 0, 0, + { { 0, }, { 0, } }, + { { 0, }, { 0, } }, + 0, 0, + 0, 0, + 0, 0, + "", "", { 0 }, { 0 }, + 0, 0 + }, + sizeof(struct arpt_entry), + sizeof(struct arpt_standard), + 0, + { 0, 0 }, { } }, + { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } }, + -NF_ACCEPT - 1 } } }, /* ERROR */ @@ -142,35 +166,34 @@ .owner = THIS_MODULE, .pf = NF_ARP, .hooknum = NF_ARP_OUT, - } + }, + { + .hook = arpt_hook, + .owner = THIS_MODULE, + .pf = NF_ARP, + .hooknum = NF_ARP_FORWARD, + }, }; static int __init init(void) { - int ret; + int ret, i; /* Register table */ ret = arpt_register_table(&packet_filter); if (ret < 0) return ret; - /* Register hooks */ - ret = nf_register_hook(&arpt_ops[0]); - if (ret < 0) - goto cleanup_table; - - ret = nf_register_hook(&arpt_ops[1]); - if (ret < 0) - goto cleanup_hook0; - + for (i = 0; i < ARRAY_SIZE(arpt_ops); i++) + if ((ret = nf_register_hook(&arpt_ops[i])) < 0) + goto cleanup_hooks; return ret; -cleanup_hook0: - nf_unregister_hook(&arpt_ops[0]); +cleanup_hooks: + while (--i >= 0) + nf_unregister_hook(&arpt_ops[i]); -cleanup_table: arpt_unregister_table(&packet_filter); - return ret; } @@ -178,7 +201,7 @@ { unsigned int i; - for (i = 0; i < sizeof(arpt_ops)/sizeof(struct nf_hook_ops); i++) + for (i = 0; i < ARRAY_SIZE(arpt_ops); i++) nf_unregister_hook(&arpt_ops[i]); arpt_unregister_table(&packet_filter); diff -urN linux-2.5.72-bk2/net/ipv4/netfilter/ipt_MIRROR.c linux-2.5.72-bk3/net/ipv4/netfilter/ipt_MIRROR.c --- linux-2.5.72-bk2/net/ipv4/netfilter/ipt_MIRROR.c 2003-06-16 21:20:27.000000000 -0700 +++ linux-2.5.72-bk3/net/ipv4/netfilter/ipt_MIRROR.c 2003-06-20 04:48:12.000000000 -0700 @@ -90,8 +90,11 @@ struct hh_cache *hh = dst->hh; if (hh) { + int hh_alen; + read_lock_bh(&hh->hh_lock); - memcpy(skb->data - 16, hh->hh_data, 16); + hh_alen = HH_DATA_ALIGN(hh->hh_len); + memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); read_unlock_bh(&hh->hh_lock); skb_push(skb, hh->hh_len); hh->hh_output(skb); diff -urN linux-2.5.72-bk2/net/ipv6/ip6_output.c linux-2.5.72-bk3/net/ipv6/ip6_output.c --- linux-2.5.72-bk2/net/ipv6/ip6_output.c 2003-06-16 21:19:40.000000000 -0700 +++ linux-2.5.72-bk3/net/ipv6/ip6_output.c 2003-06-20 04:48:13.000000000 -0700 @@ -76,8 +76,11 @@ struct hh_cache *hh = dst->hh; if (hh) { + int hh_alen; + read_lock_bh(&hh->hh_lock); - memcpy(skb->data - 16, hh->hh_data, 16); + hh_alen = HH_DATA_ALIGN(hh->hh_len); + memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); read_unlock_bh(&hh->hh_lock); skb_push(skb, hh->hh_len); return hh->hh_output(skb); diff -urN linux-2.5.72-bk2/net/sched/sch_htb.c linux-2.5.72-bk3/net/sched/sch_htb.c --- linux-2.5.72-bk2/net/sched/sch_htb.c 2003-06-16 21:20:06.000000000 -0700 +++ linux-2.5.72-bk3/net/sched/sch_htb.c 2003-06-20 04:48:13.000000000 -0700 @@ -9,6 +9,8 @@ * Authors: Martin Devera, * * Credits (in time order) for older HTB versions: + * Stef Coene + * HTB support at LARTC mailing list * Ondrej Kraus, * found missing INIT_QDISC(htb) * Vladimir Smelhaus, Aamer Akhter, Bert Hubert @@ -19,7 +21,7 @@ * created test case so that I was able to fix nasty bug * and many others. thanks. * - * $Id: sch_htb.c,v 1.17 2003/01/29 09:22:18 devik Exp devik $ + * $Id: sch_htb.c,v 1.20 2003/06/18 19:55:49 devik Exp devik $ */ #include #include @@ -71,7 +73,7 @@ #define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */ #define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock) #define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock) -#define HTB_VER 0x3000a /* major must be matched with number suplied by TC as version */ +#define HTB_VER 0x3000c /* major must be matched with number suplied by TC as version */ #if HTB_VER >> 16 != TC_HTB_PROTOVER #error "Mismatched sch_htb.c and pkt_sch.h" @@ -217,6 +219,9 @@ /* time of nearest event per level (row) */ unsigned long near_ev_cache[TC_HTB_MAXDEPTH]; + /* cached value of jiffies in dequeue */ + unsigned long jiffies; + /* whether we hit non-work conserving class during this dequeue; we use */ int nwc_hit; /* this to disable mindelay complaint in dequeue */ @@ -336,7 +341,7 @@ static void htb_debug_dump (struct htb_sched *q) { int i,p; - printk(KERN_DEBUG "htb*g j=%lu\n",jiffies); + printk(KERN_DEBUG "htb*g j=%lu lj=%lu\n",jiffies,q->jiffies); /* rows */ for (i=TC_HTB_MAXDEPTH-1;i>=0;i--) { printk(KERN_DEBUG "htb*r%d m=%x",i,q->row_mask[i]); @@ -419,8 +424,8 @@ if ((delay <= 0 || delay > cl->mbuffer) && net_ratelimit()) printk(KERN_ERR "HTB: suspicious delay in wait_tree d=%ld cl=%X h=%d\n",delay,cl->classid,debug_hint); #endif - cl->pq_key = jiffies + PSCHED_US2JIFFIE(delay); - if (cl->pq_key == jiffies) + cl->pq_key = q->jiffies + PSCHED_US2JIFFIE(delay); + if (cl->pq_key == q->jiffies) cl->pq_key++; /* update the nearest event cache */ @@ -587,7 +592,7 @@ long toks; if ((toks = (cl->ctokens + *diff)) < ( -#ifdef HTB_HYSTERESIS +#if HTB_HYSTERESIS cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : #endif 0)) { @@ -595,7 +600,7 @@ return HTB_CANT_SEND; } if ((toks = (cl->tokens + *diff)) >= ( -#ifdef HTB_HYSTERESIS +#if HTB_HYSTERESIS cl->cmode == HTB_CAN_SEND ? -cl->buffer : #endif 0)) @@ -798,7 +803,7 @@ cl->classid, diff, (unsigned long long) q->now, (unsigned long long) cl->t_c, - jiffies); + q->jiffies); diff = 1000; } #endif @@ -841,6 +846,7 @@ * * Scans event queue for pending events and applies them. Returns jiffies to * next pending event (0 for no event in pq). + * Note: Aplied are events whose have cl->pq_key <= jiffies. */ static long htb_do_events(struct htb_sched *q,int level) { @@ -855,9 +861,9 @@ while (p->rb_left) p = p->rb_left; cl = rb_entry(p, struct htb_class, pq_node); - if (cl->pq_key - (jiffies+1) < 0x80000000) { - HTB_DBG(8,3,"htb_do_ev_ret delay=%ld\n",cl->pq_key - jiffies); - return cl->pq_key - jiffies; + if (cl->pq_key - (q->jiffies+1) < 0x80000000) { + HTB_DBG(8,3,"htb_do_ev_ret delay=%ld\n",cl->pq_key - q->jiffies); + return cl->pq_key - q->jiffies; } htb_safe_rb_erase(p,q->wait_pq+level); diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer, 0); @@ -868,7 +874,7 @@ cl->classid, diff, (unsigned long long) q->now, (unsigned long long) cl->t_c, - jiffies); + q->jiffies); diff = 1000; } #endif @@ -975,7 +981,8 @@ printk(KERN_INFO "HTB delay %ld > 5sec\n", delay); delay = 5*HZ; } - mod_timer(&q->timer, jiffies + delay); + /* why don't use jiffies here ? because expires can be in past */ + mod_timer(&q->timer, q->jiffies + delay); sch->flags |= TCQ_F_THROTTLED; sch->stats.overlimits++; HTB_DBG(3,1,"htb_deq t_delay=%ld\n",delay); @@ -991,6 +998,7 @@ int evs_used = 0; #endif + q->jiffies = jiffies; HTB_DBG(3,1,"htb_deq dircnt=%d qlen=%d\n",skb_queue_len(&q->direct_queue), sch->q.qlen); @@ -1010,14 +1018,14 @@ /* common case optimization - skip event handler quickly */ int m; long delay; - if (jiffies - q->near_ev_cache[level] < 0x80000000 || 0) { + if (q->jiffies - q->near_ev_cache[level] < 0x80000000 || 0) { delay = htb_do_events(q,level); - q->near_ev_cache[level] += delay ? delay : HZ; + q->near_ev_cache[level] = q->jiffies + (delay ? delay : HZ); #ifdef HTB_DEBUG evs_used++; #endif } else - delay = q->near_ev_cache[level] - jiffies; + delay = q->near_ev_cache[level] - q->jiffies; if (delay && min_delay > delay) min_delay = delay; @@ -1036,8 +1044,8 @@ #ifdef HTB_DEBUG if (!q->nwc_hit && min_delay >= 10*HZ && net_ratelimit()) { if (min_delay == LONG_MAX) { - printk(KERN_ERR "HTB: dequeue bug (%d), report it please !\n", - evs_used); + printk(KERN_ERR "HTB: dequeue bug (%d,%lu,%lu), report it please !\n", + evs_used,q->jiffies,jiffies); htb_debug_dump(q); } else printk(KERN_WARNING "HTB: mindelay=%ld, some class has " @@ -1046,7 +1054,7 @@ #endif htb_delay_by (sch,min_delay > 5*HZ ? 5*HZ : min_delay); fin: - HTB_DBG(3,1,"htb_deq_end %s j=%lu skb=%p\n",sch->dev->name,jiffies,skb); + HTB_DBG(3,1,"htb_deq_end %s j=%lu skb=%p\n",sch->dev->name,q->jiffies,skb); return skb; } @@ -1409,7 +1417,7 @@ parent = parentid == TC_H_ROOT ? NULL : htb_find (parentid,sch); hopt = RTA_DATA(tb[TCA_HTB_PARMS-1]); - HTB_DBG(0,1,"htb_chg cl=%p, clid=%X, opt/prio=%d, rate=%u, buff=%d, quant=%d\n", cl,cl?cl->classid:0,(int)hopt->prio,hopt->rate.rate,hopt->buffer,hopt->quantum); + HTB_DBG(0,1,"htb_chg cl=%p(%X), clid=%X, parid=%X, opt/prio=%d, rate=%u, buff=%d, quant=%d\n", cl,cl?cl->classid:0,classid,parentid,(int)hopt->prio,hopt->rate.rate,hopt->buffer,hopt->quantum); rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB-1]); ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB-1]); if (!rtab || !ctab) goto failure;