---------------------------
+What: /proc/acpi/event
+When: February 2008
+Why: /proc/acpi/event has been replaced by events via the input layer
+ and netlink since 2.6.23.
+Who: Len Brown <len.brown@intel.com>
+
+---------------------------
+
What: Compaq touchscreen device emulation
When: Oct 2007
Files: drivers/input/tsdev.c
Format: <1-256>
maxcpus= [SMP] Maximum number of processors that an SMP kernel
- should make use of.
- Using "nosmp" or "maxcpus=0" will disable SMP
- entirely (the MPS table probe still happens, though).
- A command-line option of "maxcpus=<NUM>", where <NUM>
- is an integer greater than 0, limits the maximum number
- of CPUs activated in SMP mode to <NUM>.
- Using "maxcpus=1" on an SMP kernel is the trivial
- case of an SMP kernel with only one CPU.
+ should make use of. maxcpus=n : n >= 0 limits the
+ kernel to using 'n' processors. n=0 is a special case,
+ it is equivalent to "nosmp", which also disables
+ the IO APIC.
max_addr=[KMG] [KNL,BOOT,ia64] All physical memory greater than or
equal to this physical address is ignored.
nosep [BUGS=X86-32] Disables x86 SYSENTER/SYSEXIT support.
- nosmp [SMP] Tells an SMP kernel to act as a UP kernel.
+ nosmp [SMP] Tells an SMP kernel to act as a UP kernel,
+ and disable the IO APIC. legacy for "maxcpus=0".
nosoftlockup [KNL] Disable the soft-lockup detector.
-1: disable all active trip points in all thermal zones
<degrees C>: override all lowest active trip points
+ thermal.crt= [HW,ACPI]
+ -1: disable all critical trip points in all thermal zones
+ <degrees C>: lower all critical trip points
+
thermal.nocrt= [HW,ACPI]
Set to disable actions on ACPI thermal zone
critical and hot trip points.
static inline u16 fs(void)
{
u16 seg;
- asm("movw %%fs,%0" : "=rm" (seg));
+ asm volatile("movw %%fs,%0" : "=rm" (seg));
return seg;
}
static inline u16 gs(void)
{
u16 seg;
- asm("movw %%gs,%0" : "=rm" (seg));
+ asm volatile("movw %%gs,%0" : "=rm" (seg));
return seg;
}
static inline u8 rdfs8(addr_t addr)
{
u8 v;
- asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
+ asm volatile("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
return v;
}
static inline u16 rdfs16(addr_t addr)
{
u16 v;
- asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+ asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
return v;
}
static inline u32 rdfs32(addr_t addr)
{
u32 v;
- asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+ asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
return v;
}
static inline u8 rdgs8(addr_t addr)
{
u8 v;
- asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
+ asm volatile("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
return v;
}
static inline u16 rdgs16(addr_t addr)
{
u16 v;
- asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+ asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
return v;
}
static inline u32 rdgs32(addr_t addr)
{
u32 v;
- asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+ asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
return v;
}
static inline int memcmp_fs(const void *s1, addr_t s2, size_t len)
{
u8 diff;
- asm("fs; repe; cmpsb; setnz %0"
- : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+ asm volatile("fs; repe; cmpsb; setnz %0"
+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
return diff;
}
static inline int memcmp_gs(const void *s1, addr_t s2, size_t len)
{
u8 diff;
- asm("gs; repe; cmpsb; setnz %0"
- : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+ asm volatile("gs; repe; cmpsb; setnz %0"
+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
return diff;
}
asm volatile("movl %0,%%cr0" : : "r" (cr0));
}
- asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw));
+ asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
+ : "+m" (fsw), "+m" (fcw));
return fsw == 0 && (fcw & 0x103f) == 0x003f;
}
cx = 0x0001; /* Sector 0-0-1 */
dx = devno;
bx = (size_t)buf;
- asm("pushfl; stc; int $0x13; setc %%al; popfl"
- : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx)
- : : "esi", "edi", "memory");
+ asm volatile("pushfl; stc; int $0x13; setc %%al; popfl"
+ : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx)
+ : : "esi", "edi", "memory");
return -(u8)ax; /* 0 or -1 */
}
u16 ax = 0x0200;
u16 cx, dx;
- asm("int $0x1a"
- : "+a" (ax), "=c" (cx), "=d" (dx)
- : : "ebx", "esi", "edi");
+ asm volatile("int $0x1a"
+ : "+a" (ax), "=c" (cx), "=d" (dx)
+ : : "ebx", "esi", "edi");
return dx >> 8;
}
int getchar(void)
{
u16 ax = 0;
- asm("int $0x16" : "+a" (ax));
+ asm volatile("int $0x16" : "+a" (ax));
return ax & 0xff;
}
static int kbd_pending(void)
{
u8 pending;
- asm("int $0x16; setnz %0"
- : "=rm" (pending)
- : "a" (0x0100));
+ asm volatile("int $0x16; setnz %0"
+ : "=rm" (pending)
+ : "a" (0x0100));
return pending;
}
#ifdef CONFIG_VIDEO_400_HACK
if (adapter >= ADAPTER_VGA) {
- asm(INT10
- : : "a" (0x1202), "b" (0x0030)
- : "ecx", "edx", "esi", "edi");
+ asm volatile(INT10
+ : : "a" (0x1202), "b" (0x0030)
+ : "ecx", "edx", "esi", "edi");
}
#endif
ax = 0x0f00;
- asm(INT10
- : "+a" (ax)
- : : "ebx", "ecx", "edx", "esi", "edi");
+ asm volatile(INT10
+ : "+a" (ax)
+ : : "ebx", "ecx", "edx", "esi", "edi");
mode = (u8)ax;
mode = 3;
/* Set the mode */
+ ax = mode;
asm volatile(INT10
- : : "a" (mode)
- : "ebx", "ecx", "edx", "esi", "edi");
+ : "+a" (ax)
+ : : "ebx", "ecx", "edx", "esi", "edi");
do_restore = 1;
return mode;
}
static int pirqs_enabled;
int skip_ioapic_setup;
-static int __init ioapic_setup(char *str)
-{
- skip_ioapic_setup = 1;
- return 1;
-}
-
-__setup("noapic", ioapic_setup);
-
static int __init ioapic_pirq_setup(char *str)
{
int i, max;
return err;
}
-struct linux32_dirent {
- u32 d_ino;
- compat_off_t d_off;
- u16 d_reclen;
- char d_name[1];
-};
-
-struct old_linux32_dirent {
- u32 d_ino;
- u32 d_offset;
- u16 d_namlen;
- char d_name[1];
-};
-
-struct getdents32_callback {
- struct linux32_dirent __user * current_dir;
- struct linux32_dirent __user * previous;
- int count;
- int error;
-};
-
-struct readdir32_callback {
- struct old_linux32_dirent __user * dirent;
- int count;
-};
-
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-static int filldir32 (void *__buf, const char *name, int namlen,
- loff_t offset, u64 ino, unsigned int d_type)
-{
- struct linux32_dirent __user * dirent;
- struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
- int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, 4);
- u32 d_ino;
-
- buf->error = -EINVAL; /* only used if we fail.. */
- if (reclen > buf->count)
- return -EINVAL;
- d_ino = ino;
- if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
- return -EOVERFLOW;
- dirent = buf->previous;
- if (dirent)
- put_user(offset, &dirent->d_off);
- dirent = buf->current_dir;
- buf->previous = dirent;
- put_user(d_ino, &dirent->d_ino);
- put_user(reclen, &dirent->d_reclen);
- copy_to_user(dirent->d_name, name, namlen);
- put_user(0, dirent->d_name + namlen);
- dirent = ((void __user *)dirent) + reclen;
- buf->current_dir = dirent;
- buf->count -= reclen;
- return 0;
-}
-
-asmlinkage long
-sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
-{
- struct file * file;
- struct linux32_dirent __user * lastdirent;
- struct getdents32_callback buf;
- int error;
-
- error = -EFAULT;
- if (!access_ok(VERIFY_WRITE, dirent, count))
- goto out;
-
- error = -EBADF;
- file = fget(fd);
- if (!file)
- goto out;
-
- buf.current_dir = (struct linux32_dirent __user *) dirent;
- buf.previous = NULL;
- buf.count = count;
- buf.error = 0;
-
- error = vfs_readdir(file, filldir32, &buf);
- if (error < 0)
- goto out_putf;
- error = buf.error;
- lastdirent = buf.previous;
- if (lastdirent) {
- if (put_user(file->f_pos, &lastdirent->d_off))
- error = -EFAULT;
- else
- error = count - buf.count;
- }
-
-out_putf:
- fput(file);
-out:
- return error;
-}
-
-static int fillonedir32(void * __buf, const char * name, int namlen,
- loff_t offset, u64 ino, unsigned int d_type)
-{
- struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
- struct old_linux32_dirent __user * dirent;
- u32 d_ino;
-
- if (buf->count)
- return -EINVAL;
- d_ino = ino;
- if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
- return -EOVERFLOW;
- buf->count++;
- dirent = buf->dirent;
- put_user(d_ino, &dirent->d_ino);
- put_user(offset, &dirent->d_offset);
- put_user(namlen, &dirent->d_namlen);
- copy_to_user(dirent->d_name, name, namlen);
- put_user(0, dirent->d_name + namlen);
- return 0;
-}
-
-asmlinkage long
-sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count)
-{
- int error;
- struct file * file;
- struct readdir32_callback buf;
-
- error = -EBADF;
- file = fget(fd);
- if (!file)
- goto out;
-
- buf.count = 0;
- buf.dirent = dirent;
-
- error = vfs_readdir(file, fillonedir32, &buf);
- if (error >= 0)
- error = buf.count;
- fput(file);
-out:
- return error;
-}
-
/*** copied from mips64 ***/
/*
* Ooo, nasty. We need here to frob 32-bit unsigned longs to
ENTRY_SAME(setfsgid)
/* I think this might work */
ENTRY_SAME(llseek) /* 140 */
- /* struct linux_dirent has longs, like 'unsigned long d_ino' which
- * almost definitely should be 'ino_t d_ino' but it's too late now */
- ENTRY_DIFF(getdents)
+ ENTRY_COMP(getdents)
/* it is POSSIBLE that select will be OK because even though fd_set
* contains longs, the macros and sizes are clever. */
ENTRY_COMP(select)
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
+ NOTES
+
__start___unwind = .; /* unwind info */
.PARISC.unwind : { *(.PARISC.unwind) }
__stop___unwind = .;
int skip_ioapic_setup;
int ioapic_force;
-/* dummy parsing: see setup.c */
-
-static int __init disable_ioapic_setup(char *str)
+static int __init parse_noapic(char *str)
{
- skip_ioapic_setup = 1;
+ disable_ioapic_setup();
return 0;
}
-early_param("noapic", disable_ioapic_setup);
+early_param("noapic", parse_noapic);
/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
static int __init disable_timer_pin_setup(char *arg)
Say N to delete /proc/acpi/ files that have moved to /sys/
+config ACPI_PROC_EVENT
+ bool "Deprecated /proc/acpi/event support"
+ depends on PROC_FS
+ ---help---
+ A user-space daemon, acpi, typically read /proc/acpi/event
+ and handled all ACPI sub-system generated events.
+
+ These events are now delivered to user-space via
+ either the input layer, or as netlink events.
+
+ This build option enables the old code for for legacy
+ user-space implementation. After some time, this will
+ be moved under CONFIG_ACPI_PROCFS, and then deleted.
+
config ACPI_AC
tristate "AC Adapter"
depends on X86
case ACPI_NOTIFY_BUS_CHECK:
case ACPI_NOTIFY_DEVICE_CHECK:
acpi_ac_get_state(ac);
- acpi_bus_generate_event(device, event, (u32) ac->state);
+ acpi_bus_generate_proc_event(device, event, (u32) ac->state);
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ device->dev.bus_id, event,
+ (u32) ac->state);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
hotk->brightness = (event & ~((u32) BR_DOWN));
}
- acpi_bus_generate_event(hotk->device, event,
+ acpi_bus_generate_proc_event(hotk->device, event,
hotk->event_count[event % 128]++);
return;
acpi_string oem_info;
};
-enum acpi_battery_files {
+enum acpi_battery_files{
ACPI_BATTERY_INFO = 0,
ACPI_BATTERY_STATE,
ACPI_BATTERY_ALARM,
};
struct acpi_battery {
+ struct mutex mutex;
struct acpi_device *device;
struct acpi_battery_flags flags;
struct acpi_buffer bif_data;
struct acpi_buffer bst_data;
- struct mutex lock;
unsigned long alarm;
unsigned long update_time[ACPI_BATTERY_NUMFILES];
-
};
inline int acpi_battery_present(struct acpi_battery *battery)
return 0;
/* Evaluate _BIF */
- mutex_lock(&battery->lock);
- status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF",
- NULL, &buffer);
- mutex_unlock(&battery->lock);
+
+ status =
+ acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL,
+ &buffer);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
return -ENODEV;
return 0;
/* Evaluate _BST */
- mutex_lock(&battery->lock);
- status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST",
- NULL, &buffer);
- mutex_unlock(&battery->lock);
+
+ status =
+ acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL,
+ &buffer);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
return -ENODEV;
arg0.integer.value = alarm;
- mutex_lock(&battery->lock);
- status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
+ status =
+ acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
&arg_list, NULL);
- mutex_unlock(&battery->lock);
if (ACPI_FAILURE(status))
return -ENODEV;
if (!battery || (count > sizeof(alarm_string) - 1))
return -EINVAL;
+ mutex_lock(&battery->mutex);
+
result = acpi_battery_update(battery, 1, &update_result);
if (result) {
result = -ENODEV;
acpi_battery_check_result(battery, result);
if (!result)
- return count;
+ result = count;
+
+ mutex_unlock(&battery->mutex);
return result;
}
int update_result = ACPI_BATTERY_NONE_UPDATE;
int update = 0;
+ mutex_lock(&battery->mutex);
+
update = (get_seconds() - battery->update_time[fid] >= update_time);
update = (update | battery->flags.update[fid]);
result = acpi_read_funcs[fid].print(seq, result);
acpi_battery_check_result(battery, result);
battery->flags.update[fid] = result;
+ mutex_unlock(&battery->mutex);
return result;
}
case ACPI_NOTIFY_DEVICE_CHECK:
device = battery->device;
acpi_battery_notify_update(battery);
- acpi_bus_generate_event(device, event,
+ acpi_bus_generate_proc_event(device, event,
acpi_battery_present(battery));
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ device->dev.bus_id, event,
+ acpi_battery_present(battery));
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
if (!battery)
return -ENOMEM;
- mutex_init(&battery->lock);
+ mutex_init(&battery->mutex);
+
+ mutex_lock(&battery->mutex);
+
battery->device = device;
strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
kfree(battery);
}
+ mutex_unlock(&battery->mutex);
return result;
}
battery = acpi_driver_data(device);
+ mutex_lock(&battery->mutex);
+
status = acpi_remove_notify_handler(device->handle,
ACPI_ALL_NOTIFY,
acpi_battery_notify);
kfree(battery->bst_data.pointer);
- mutex_destroy(&battery->lock);
+ mutex_unlock(&battery->mutex);
+
+ mutex_destroy(&battery->mutex);
kfree(battery);
Event Management
-------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_PROC_EVENT
static DEFINE_SPINLOCK(acpi_bus_event_lock);
LIST_HEAD(acpi_bus_event_list);
extern int event_is_open;
-int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data)
+int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
{
struct acpi_bus_event *event = NULL;
unsigned long flags = 0;
if (!device)
return -EINVAL;
- if (acpi_bus_generate_genetlink_event(device, type, data))
- printk(KERN_WARNING PREFIX
- "Failed to generate an ACPI event via genetlink!\n");
-
/* drop event on the floor if no one's listening */
if (!event_is_open)
return 0;
return 0;
}
-EXPORT_SYMBOL(acpi_bus_generate_event);
+EXPORT_SYMBOL(acpi_bus_generate_proc_event);
int acpi_bus_receive_event(struct acpi_bus_event *event)
{
}
EXPORT_SYMBOL(acpi_bus_receive_event);
+#endif /* CONFIG_ACPI_PROC_EVENT */
/* --------------------------------------------------------------------------
Notification Handling
}
input_sync(input);
- acpi_bus_generate_event(button->device, event,
+ acpi_bus_generate_proc_event(button->device, event,
++button->pushed);
break;
default:
return AE_CTRL_TERMINATE;
}
-static void ec_remove_handlers(struct acpi_ec *ec)
-{
- acpi_remove_address_space_handler(ec->handle,
- ACPI_ADR_SPACE_EC,
- &acpi_ec_space_handler);
- acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
-}
-
static int acpi_ec_add(struct acpi_device *device)
{
struct acpi_ec *ec = NULL;
/* Check if we found the boot EC */
if (boot_ec) {
if (boot_ec->gpe == ec->gpe) {
- ec_remove_handlers(boot_ec);
- mutex_destroy(&boot_ec->lock);
- kfree(boot_ec);
- first_ec = boot_ec = NULL;
+ /* We might have incorrect info for GL at boot time */
+ mutex_lock(&boot_ec->lock);
+ boot_ec->global_lock = ec->global_lock;
+ /* Copy handlers from new ec into boot ec */
+ list_splice(&ec->list, &boot_ec->list);
+ mutex_unlock(&boot_ec->lock);
+ kfree(ec);
+ ec = boot_ec;
}
- }
- if (!first_ec)
+ } else
first_ec = ec;
ec->handle = device->handle;
acpi_driver_data(device) = ec;
if (ec == first_ec)
first_ec = NULL;
+ /* Don't touch boot EC */
+ if (boot_ec != ec)
+ kfree(ec);
return 0;
}
if (!ec)
return -EINVAL;
- ret = ec_install_handlers(ec);
+ /* Boot EC is already working */
+ if (ec != boot_ec)
+ ret = ec_install_handlers(ec);
/* EC is fully operational, allow queries */
atomic_set(&ec->query_pending, 0);
static int acpi_ec_stop(struct acpi_device *device, int type)
{
+ acpi_status status;
struct acpi_ec *ec;
if (!device)
ec = acpi_driver_data(device);
if (!ec)
return -EINVAL;
- ec_remove_handlers(ec);
+
+ /* Don't touch boot EC */
+ if (ec == boot_ec)
+ return 0;
+
+ status = acpi_remove_address_space_handler(ec->handle,
+ ACPI_ADR_SPACE_EC,
+ &acpi_ec_space_handler);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
return 0;
}
#define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("event");
+#ifdef CONFIG_ACPI_PROC_EVENT
/* Global vars for handling event proc entry */
static DEFINE_SPINLOCK(acpi_system_event_lock);
int event_is_open = 0;
.release = acpi_system_close_event,
.poll = acpi_system_poll_event,
};
+#endif /* CONFIG_ACPI_PROC_EVENT */
#ifdef CONFIG_NET
static unsigned int acpi_event_seqnum;
.name = ACPI_GENL_MCAST_GROUP_NAME,
};
-int acpi_bus_generate_genetlink_event(struct acpi_device *device,
+int acpi_bus_generate_netlink_event(const char *device_class,
+ const char *bus_id,
u8 type, int data)
{
struct sk_buff *skb;
memset(event, 0, sizeof(struct acpi_genl_event));
- strcpy(event->device_class, device->pnp.device_class);
- strcpy(event->bus_id, device->dev.bus_id);
+ strcpy(event->device_class, device_class);
+ strcpy(event->bus_id, bus_id);
event->type = type;
event->data = data;
return 0;
}
+EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
+
static int acpi_event_genetlink_init(void)
{
int result;
}
#else
-int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type,
- int data)
+int acpi_bus_generate_netlink_event(const char *device_class,
+ const char *bus_id,
+ u8 type, int data)
{
return 0;
}
+EXPORT_SYMBOL(acpi_generate_netlink_event);
+
static int acpi_event_genetlink_init(void)
{
return -ENODEV;
static int __init acpi_event_init(void)
{
+#ifdef CONFIG_ACPI_PROC_EVENT
struct proc_dir_entry *entry;
+#endif
int error = 0;
if (acpi_disabled)
printk(KERN_WARNING PREFIX
"Failed to create genetlink family for ACPI event\n");
+#ifdef CONFIG_ACPI_PROC_EVENT
/* 'event' [R] */
entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);
if (entry)
entry->proc_fops = &acpi_system_event_ops;
else
return -ENODEV;
+#endif
return 0;
}
ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
}
- status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK"));
- }
- /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
-
/*
+ * GPEs must be enabled before _WAK is called as GPEs
+ * might get fired there
+ *
* Restore the GPEs:
* 1) Disable/Clear all GPEs
* 2) Enable all runtime GPEs
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- acpi_gbl_system_awake_and_running = TRUE;
-
status = acpi_hw_enable_all_runtime_gpes();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
+ status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK"));
+ }
+ /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
+
+ acpi_gbl_system_awake_and_running = TRUE;
+
/* Enable power button */
(void)
******************************************************************************/
acpi_status
-acpi_get_devices(char *HID,
+acpi_get_devices(const char *HID,
acpi_walk_callback user_function,
void *context, void **return_value)
{
switch (event) {
case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
acpi_processor_ppc_has_changed(pr);
- acpi_bus_generate_event(device, event,
+ acpi_bus_generate_proc_event(device, event,
pr->performance_platform_limit);
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ device->dev.bus_id, event,
+ pr->performance_platform_limit);
break;
case ACPI_PROCESSOR_NOTIFY_POWER:
acpi_processor_cst_has_changed(pr);
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_proc_event(device, event, 0);
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ device->dev.bus_id, event, 0);
break;
case ACPI_PROCESSOR_NOTIFY_THROTTLING:
acpi_processor_tstate_has_changed(pr);
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_proc_event(device, event, 0);
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ device->dev.bus_id, event, 0);
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
strcpy(acpi_device_bid(device), bid);
strcpy(acpi_device_class(device), class);
- result = acpi_bus_generate_event(device, event, state);
+ result = acpi_bus_generate_proc_event(device, event, state);
strcpy(acpi_device_bid(device), bid_saved);
strcpy(acpi_device_class(device), class_saved);
+ acpi_bus_generate_netlink_event(class, bid, event, state);
return result;
}
* e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
* char *modalias: "acpi:IBM0001:ACPI0001"
*/
-int create_modalias(struct acpi_device *acpi_dev, char *modalias, int size){
-
+static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
+ int size)
+{
int len;
if (!acpi_dev->flags.hardware_id)
unsigned long d_min, d_max;
if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
- printk(KERN_ERR "ACPI handle has no context!\n");
+ printk(KERN_DEBUG "ACPI handle has no context!\n");
return -ENODEV;
}
static acpi_physical_address
acpi_tb_get_root_table_entry(u8 * table_entry,
acpi_native_uint table_entry_size);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_check_xsdt
+ *
+ * PARAMETERS: address - Pointer to the XSDT
+ *
+ * RETURN: status
+ * AE_OK - XSDT is okay
+ * AE_NO_MEMORY - can't map XSDT
+ * AE_INVALID_TABLE_LENGTH - invalid table length
+ * AE_NULL_ENTRY - XSDT has NULL entry
+ *
+ * DESCRIPTION: validate XSDT
+******************************************************************************/
+
+static acpi_status
+acpi_tb_check_xsdt(acpi_physical_address address)
+{
+ struct acpi_table_header *table;
+ u32 length;
+ u64 xsdt_entry_address;
+ u8 *table_entry;
+ u32 table_count;
+ int i;
+
+ table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
+ if (!table)
+ return AE_NO_MEMORY;
+
+ length = table->length;
+ acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+ if (length < sizeof(struct acpi_table_header))
+ return AE_INVALID_TABLE_LENGTH;
+
+ table = acpi_os_map_memory(address, length);
+ if (!table)
+ return AE_NO_MEMORY;
+
+ /* Calculate the number of tables described in XSDT */
+ table_count =
+ (u32) ((table->length -
+ sizeof(struct acpi_table_header)) / sizeof(u64));
+ table_entry =
+ ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
+ for (i = 0; i < table_count; i++) {
+ ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry);
+ if (!xsdt_entry_address) {
+ /* XSDT has NULL entry */
+ break;
+ }
+ table_entry += sizeof(u64);
+ }
+ acpi_os_unmap_memory(table, length);
+
+ if (i < table_count)
+ return AE_NULL_ENTRY;
+ else
+ return AE_OK;
+}
/*******************************************************************************
*
u32 table_count;
struct acpi_table_header *table;
acpi_physical_address address;
+ acpi_physical_address rsdt_address;
u32 length;
u8 *table_entry;
acpi_status status;
*/
address = (acpi_physical_address) rsdp->xsdt_physical_address;
table_entry_size = sizeof(u64);
+ rsdt_address = (acpi_physical_address)
+ rsdp->rsdt_physical_address;
} else {
/* Root table is an RSDT (32-bit physical addresses) */
*/
acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
+ if (table_entry_size == sizeof(u64)) {
+ if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) {
+ /* XSDT has NULL entry, RSDT is used */
+ address = rsdt_address;
+ table_entry_size = sizeof(u32);
+ ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry,"
+ "using RSDT"));
+ }
+ }
/* Map the RSDT/XSDT table header to get the full table length */
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
static int act;
module_param(act, int, 0644);
-MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.\n");
+MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.");
+
+static int crt;
+module_param(crt, int, 0644);
+MODULE_PARM_DESC(crt, "Disable or lower all critical trip points.");
static int tzp;
module_param(tzp, int, 0444);
-MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
+MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
static int nocrt;
module_param(nocrt, int, 0);
-MODULE_PARM_DESC(nocrt, "Set to disable action on ACPI thermal zone critical and hot trips.\n");
+MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
static int off;
module_param(off, int, 0);
-MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.\n");
+MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
static int psv;
module_param(psv, int, 0644);
-MODULE_PARM_DESC(psv, "Disable or override all passive trip points.\n");
+MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
static int acpi_thermal_add(struct acpi_device *device);
static int acpi_thermal_remove(struct acpi_device *device, int type);
tz->trips.critical.temperature));
}
+ if (tz->trips.critical.flags.valid == 1) {
+ if (crt == -1) {
+ tz->trips.critical.flags.valid = 0;
+ } else if (crt > 0) {
+ unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
+
+ /*
+ * Allow override to lower critical threshold
+ */
+ if (crt_k < tz->trips.critical.temperature)
+ tz->trips.critical.temperature = crt_k;
+ }
+ }
+
/* Critical Sleep (optional) */
status =
printk(KERN_EMERG
"Critical temperature reached (%ld C), shutting down.\n",
KELVIN_TO_CELSIUS(tz->temperature));
- acpi_bus_generate_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
+ acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
tz->trips.critical.flags.enabled);
+ acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
+ tz->device->dev.bus_id,
+ ACPI_THERMAL_NOTIFY_CRITICAL,
+ tz->trips.critical.flags.enabled);
orderly_poweroff(true);
} else if (tz->trips.hot.flags.enabled)
tz->trips.hot.flags.enabled = 0;
- acpi_bus_generate_event(tz->device, ACPI_THERMAL_NOTIFY_HOT,
+ acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT,
tz->trips.hot.flags.enabled);
+ acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
+ tz->device->dev.bus_id,
+ ACPI_THERMAL_NOTIFY_HOT,
+ tz->trips.hot.flags.enabled);
/* TBD: Call user-mode "sleep(S4)" function */
entry->owner = THIS_MODULE;
}
- /* 'trip_points' [R/W] */
+ /* 'trip_points' [R] */
entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
- S_IFREG | S_IRUGO | S_IWUSR,
+ S_IRUGO,
acpi_device_dir(device));
if (!entry)
return -ENODEV;
case ACPI_THERMAL_NOTIFY_THRESHOLDS:
acpi_thermal_get_trip_points(tz);
acpi_thermal_check(tz);
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_proc_event(device, event, 0);
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ device->dev.bus_id, event, 0);
break;
case ACPI_THERMAL_NOTIFY_DEVICES:
if (tz->flags.devices)
acpi_thermal_get_devices(tz);
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_proc_event(device, event, 0);
+ acpi_bus_generate_netlink_event(device->pnp.device_class,
+ device->dev.bus_id, event, 0);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
}
return 0;
}
+static int thermal_nocrt(struct dmi_system_id *d) {
+
+ printk(KERN_NOTICE "ACPI: %s detected: "
+ "disabling all critical thermal trip point actions.\n", d->ident);
+ nocrt = 1;
+ return 0;
+}
static int thermal_tzp(struct dmi_system_id *d) {
if (tzp == 0) {
DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
},
},
+ {
+ .callback = thermal_nocrt,
+ .ident = "Gigabyte GA-7ZX",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
+ DMI_MATCH(DMI_BOARD_NAME, "7ZX"),
+ },
+ },
{}
};
#endif /* CONFIG_DMI */
"Unknown exception code: 0x%8.8X", status));
exception = "UNKNOWN_STATUS_CODE";
+ dump_stack();
}
return (ACPI_CAST_PTR(const char, exception));
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-
+#include <linux/input.h>
#include <linux/backlight.h>
#include <linux/video_output.h>
#include <asm/uaccess.h>
struct semaphore sem;
struct list_head video_device_list;
struct proc_dir_entry *dir;
+ struct input_dev *input;
+ char phys[32]; /* for input device */
};
struct acpi_video_device_flags {
{
struct acpi_video_bus *video = data;
struct acpi_device *device = NULL;
+ struct input_dev *input;
+ int keycode;
+
printk("video bus notify\n");
return;
device = video->device;
+ input = video->input;
switch (event) {
case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch,
* most likely via hotkey. */
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_SWITCHVIDEOMODE;
break;
case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
acpi_video_device_enumerate(video);
acpi_video_device_rebind(video);
acpi_video_switch_output(video, event);
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_SWITCHVIDEOMODE;
break;
case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */
+ acpi_video_switch_output(video, event);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_SWITCHVIDEOMODE;
+ break;
case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
+ acpi_video_switch_output(video, event);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_VIDEO_NEXT;
+ break;
case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
acpi_video_switch_output(video, event);
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_VIDEO_PREV;
break;
default:
+ keycode = KEY_UNKNOWN;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
break;
}
+ input_report_key(input, keycode, 1);
+ input_sync(input);
+ input_report_key(input, keycode, 0);
+ input_sync(input);
+
return;
}
{
struct acpi_video_device *video_device = data;
struct acpi_device *device = NULL;
+ struct acpi_video_bus *bus;
+ struct input_dev *input;
+ int keycode;
if (!video_device)
return;
device = video_device->dev;
+ bus = video_device->video;
+ input = bus->input;
switch (event) {
- case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */
- case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
- acpi_bus_generate_event(device, event, 0);
- break;
case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
+ acpi_video_switch_brightness(video_device, event);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_BRIGHTNESS_CYCLE;
+ break;
case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
+ acpi_video_switch_brightness(video_device, event);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_BRIGHTNESSUP;
+ break;
case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
+ acpi_video_switch_brightness(video_device, event);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_BRIGHTNESSDOWN;
+ break;
case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
+ acpi_video_switch_brightness(video_device, event);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_BRIGHTNESS_ZERO;
+ break;
case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
acpi_video_switch_brightness(video_device, event);
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_proc_event(device, event, 0);
+ keycode = KEY_DISPLAY_OFF;
break;
default:
+ keycode = KEY_UNKNOWN;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
break;
}
+
+ input_report_key(input, keycode, 1);
+ input_sync(input);
+ input_report_key(input, keycode, 0);
+ input_sync(input);
+
return;
}
+static int instance;
static int acpi_video_bus_add(struct acpi_device *device)
{
int result = 0;
acpi_status status = 0;
struct acpi_video_bus *video = NULL;
+ struct input_dev *input;
if (!device)
if (!video)
return -ENOMEM;
+ /* a hack to fix the duplicate name "VID" problem on T61 */
+ if (!strcmp(device->pnp.bus_id, "VID")) {
+ if (instance)
+ device->pnp.bus_id[3] = '0' + instance;
+ instance ++;
+ }
+
video->device = device;
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
goto end;
}
+
+ video->input = input = input_allocate_device();
+
+ snprintf(video->phys, sizeof(video->phys),
+ "%s/video/input0", acpi_device_hid(video->device));
+
+ input->name = acpi_device_name(video->device);
+ input->phys = video->phys;
+ input->id.bustype = BUS_HOST;
+ input->id.product = 0x06;
+ input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
+ set_bit(KEY_VIDEO_NEXT, input->keybit);
+ set_bit(KEY_VIDEO_PREV, input->keybit);
+ set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
+ set_bit(KEY_BRIGHTNESSUP, input->keybit);
+ set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
+ set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
+ set_bit(KEY_DISPLAY_OFF, input->keybit);
+ set_bit(KEY_UNKNOWN, input->keybit);
+ result = input_register_device(input);
+ if (result) {
+ acpi_remove_notify_handler(video->device->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_video_bus_notify);
+ acpi_video_bus_stop_devices(video);
+ acpi_video_bus_put_devices(video);
+ kfree(video->attached_array);
+ acpi_video_bus_remove_fs(device);
+ goto end;
+ }
+
+
printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
video->flags.multihead ? "yes" : "no",
acpi_video_bus_put_devices(video);
acpi_video_bus_remove_fs(device);
+ input_unregister_device(video->input);
kfree(video->attached_array);
kfree(video);
pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
+ if (!amd_irongate_private.registers)
+ return -ENOMEM;
/* Write out the address of the gatt table */
writel(agp_bridge->gatt_bus_addr, amd_irongate_private.registers+AMD_ATTBASE);
temp = (temp & 0xfffff000);
ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
+ if (!ati_generic_private.registers)
+ return -ENOMEM;
+
if (is_r200())
pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
else
if (!r->start && r->end) {
if (pci_assign_resource(pdev, 0)) {
printk(KERN_ERR PFX "could not assign resource 0\n");
+ agp_put_bridge(bridge);
return -ENODEV;
}
}
*/
if (pci_enable_device(pdev)) {
printk(KERN_ERR PFX "Unable to Enable PCI device\n");
+ agp_put_bridge(bridge);
return -ENODEV;
}
if (cap != PCI_CAP_ID_AGP) {
printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n",
cap, hp->lba_cap_offset);
+ iounmap(hp->lba_regs);
return -ENODEV;
}
num_entries = A_SIZE_8(temp)->num_entries;
i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order);
+ if (!i460.gatt) {
+ printk(KERN_ERR PFX "ioremap failed\n");
+ return -ENOMEM;
+ }
/* These are no good, the should be removed from the agp_bridge strucure... */
agp_bridge->gatt_table_real = NULL;
temp &= 0xfff80000;
intel_private.registers = ioremap(temp,128 * 4096);
- if (!intel_private.registers)
+ if (!intel_private.registers) {
+ iounmap(intel_private.gtt);
return -ENOMEM;
+ }
temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ? */
temp &= 0xfff00000;
intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
- if (!intel_private.gtt)
- return -ENOMEM;
+ if (!intel_private.gtt)
+ return -ENOMEM;
intel_private.registers = ioremap(temp,128 * 4096);
- if (!intel_private.registers)
- return -ENOMEM;
+ if (!intel_private.registers) {
+ iounmap(intel_private.gtt);
+ return -ENOMEM;
+ }
temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ? */
nvidia_private.aperture =
(volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE);
+ if (!nvidia_private.aperture)
+ return -ENOMEM;
+
return 0;
}
.device_id = PCI_DEVICE_ID_VIA_P4M890,
.chipset_name = "P4M890",
},
+ /* P4M900 */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_VT3364,
+ .chipset_name = "P4M900",
+ },
{ }, /* dummy final entry, always present */
};
MTRR_TYPE_WRCOMB, 1);
}
}
- if (map->type == _DRM_REGISTERS)
+ if (map->type == _DRM_REGISTERS) {
map->handle = ioremap(map->offset, map->size);
+ if (!map->handle) {
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -ENOMEM;
+ }
+ }
+
break;
case _DRM_SHM:
list = drm_find_matching_map(dev, map);
return -EINVAL;
}
- if (!map) {
- mutex_unlock(&dev->struct_mutex);
- return -EINVAL;
- }
-
/* Register and framebuffer maps are permanent */
if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
mutex_unlock(&dev->struct_mutex);
blitq->head = 0;
blitq->cur = 0;
blitq->serviced = 0;
- blitq->num_free = VIA_NUM_BLIT_SLOTS;
+ blitq->num_free = VIA_NUM_BLIT_SLOTS - 1;
blitq->num_outstanding = 0;
blitq->is_active = 0;
blitq->aborting = 0;
#ifdef CONFIG_ACPI
if (sonypi_acpi_device)
- acpi_bus_generate_event(sonypi_acpi_device, 1, event);
+ acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event);
#endif
kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
/* Set up the dummy driver. */
card->driver = &dummy_driver;
- fw_flush_transactions(card);
-
fw_destroy_nodes(card);
+ flush_scheduled_work();
+
+ fw_flush_transactions(card);
+ del_timer_sync(&card->flush_timer);
fw_card_put(card);
}
struct sbp2_orb {
struct fw_transaction t;
+ struct kref kref;
dma_addr_t request_bus;
int rcode;
struct sbp2_pointer pointer;
};
static void
+free_orb(struct kref *kref)
+{
+ struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref);
+
+ kfree(orb);
+}
+
+static void
sbp2_status_write(struct fw_card *card, struct fw_request *request,
int tcode, int destination, int source,
int generation, int speed,
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry(orb, &sd->orb_list, link) {
if (STATUS_GET_ORB_HIGH(status) == 0 &&
- STATUS_GET_ORB_LOW(status) == orb->request_bus &&
- orb->rcode == RCODE_COMPLETE) {
+ STATUS_GET_ORB_LOW(status) == orb->request_bus) {
+ orb->rcode = RCODE_COMPLETE;
list_del(&orb->link);
break;
}
else
fw_error("status write for unknown orb\n");
+ kref_put(&orb->kref, free_orb);
+
fw_send_response(card, request, RCODE_COMPLETE);
}
struct sbp2_orb *orb = data;
unsigned long flags;
- orb->rcode = rcode;
- if (rcode != RCODE_COMPLETE) {
- spin_lock_irqsave(&card->lock, flags);
+ /*
+ * This is a little tricky. We can get the status write for
+ * the orb before we get this callback. The status write
+ * handler above will assume the orb pointer transaction was
+ * successful and set the rcode to RCODE_COMPLETE for the orb.
+ * So this callback only sets the rcode if it hasn't already
+ * been set and only does the cleanup if the transaction
+ * failed and we didn't already get a status write.
+ */
+ spin_lock_irqsave(&card->lock, flags);
+
+ if (orb->rcode == -1)
+ orb->rcode = rcode;
+ if (orb->rcode != RCODE_COMPLETE) {
list_del(&orb->link);
- spin_unlock_irqrestore(&card->lock, flags);
orb->callback(orb, NULL);
}
+
+ spin_unlock_irqrestore(&card->lock, flags);
+
+ kref_put(&orb->kref, free_orb);
}
static void
list_add_tail(&orb->link, &sd->orb_list);
spin_unlock_irqrestore(&device->card->lock, flags);
+ /* Take a ref for the orb list and for the transaction callback. */
+ kref_get(&orb->kref);
+ kref_get(&orb->kref);
+
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
node_id, generation, device->max_speed, offset,
&orb->pointer, sizeof(orb->pointer),
if (orb == NULL)
return -ENOMEM;
+ kref_init(&orb->base.kref);
orb->response_bus =
dma_map_single(device->card->device, &orb->response,
sizeof(orb->response), DMA_FROM_DEVICE);
if (response)
fw_memcpy_from_be32(response,
orb->response, sizeof(orb->response));
- kfree(orb);
+ kref_put(&orb->base.kref, free_orb);
return retval;
}
orb->cmd->result = result;
orb->done(orb->cmd);
- kfree(orb);
}
static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
/* Initialize rcode to something not RCODE_COMPLETE. */
orb->base.rcode = -1;
+ kref_init(&orb->base.kref);
orb->unit = unit;
orb->done = done;
sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
sd->command_block_agent_address + SBP2_ORB_POINTER);
+ kref_put(&orb->base.kref, free_orb);
return 0;
fail_mapping:
- kfree(orb);
+ kref_put(&orb->base.kref, free_orb);
fail_alloc:
return SCSI_MLQUEUE_HOST_BUSY;
}
return 0;
}
-static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu)
+static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
+ struct hpsb_host *host)
{
- struct hpsb_host *host = lu->hi->host;
struct list_head *lh, *next;
struct sbp2_command_info *cmd;
unsigned long flags;
if (!lu)
return;
-
hi = lu->hi;
+ if (!hi)
+ goto no_hi;
if (lu->shost) {
scsi_remove_host(lu->shost);
scsi_host_put(lu->shost);
}
flush_scheduled_work();
- sbp2util_remove_command_orb_pool(lu);
+ sbp2util_remove_command_orb_pool(lu, hi->host);
list_del(&lu->lu_list);
lu->ud->device.driver_data = NULL;
- if (hi)
- module_put(hi->host->driver->owner);
-
+ module_put(hi->host->driver->owner);
+no_hi:
kfree(lu);
}
config DM_MULTIPATH_RDAC
tristate "LSI/Engenio RDAC multipath support (EXPERIMENTAL)"
- depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+ depends on DM_MULTIPATH && BLK_DEV_DM && SCSI && EXPERIMENTAL
---help---
Multipath support for LSI/Engenio RDAC.
lcd_blank(FB_BLANK_POWERDOWN);
}
- acpi_bus_generate_event(hotk->device, event,
+ acpi_bus_generate_proc_event(hotk->device, event,
hotk->event_count[event % 128]++);
return;
}
#define ASUS_LED_UNREGISTER(object) \
- led_classdev_unregister(&object##_led)
+ if (object##_led.dev) \
+ led_classdev_unregister(&object##_led)
static void asus_led_exit(void)
{
},
},
{
+ .ident = "Sony Vaio FZ Series",
+ .callback = sony_nc_C_enable,
+ .driver_data = sony_C_events,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"),
+ },
+ },
+ {
.ident = "Sony Vaio C Series",
.callback = sony_nc_C_enable,
.driver_data = sony_C_events,
dprintk("sony_acpi_notify, event: 0x%.2x\n", ev);
sony_laptop_report_input_event(ev);
- acpi_bus_generate_event(sony_nc_acpi_device, 1, ev);
+ acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
}
static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
found:
sony_laptop_report_input_event(device_event);
- acpi_bus_generate_event(spic_dev.acpi_dev, 1, device_event);
+ acpi_bus_generate_proc_event(spic_dev.acpi_dev, 1, device_event);
sonypi_compat_report_event(device_event);
return IRQ_HANDLED;
struct sony_pic_ioport *io, *tmp_io;
struct sony_pic_irq *irq, *tmp_irq;
- sonypi_compat_exit();
-
if (sony_pic_disable(device)) {
printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
return -ENXIO;
release_region(spic_dev.cur_ioport->io.minimum,
spic_dev.cur_ioport->io.address_length);
+ sonypi_compat_exit();
+
sony_laptop_remove_input();
/* pf attrs */
goto err_free_resources;
}
+ if (sonypi_compat_init())
+ goto err_remove_input;
+
/* request io port */
list_for_each_entry(io, &spic_dev.ioports, list) {
if (request_region(io->io.minimum, io->io.address_length,
if (!spic_dev.cur_ioport) {
printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
result = -ENODEV;
- goto err_remove_input;
+ goto err_remove_compat;
}
/* request IRQ */
if (result)
goto err_remove_pf;
- if (sonypi_compat_init())
- goto err_remove_pf;
-
return 0;
err_remove_pf:
release_region(spic_dev.cur_ioport->io.minimum,
spic_dev.cur_ioport->io.address_length);
+err_remove_compat:
+ sonypi_compat_exit();
+
err_remove_input:
sony_laptop_remove_input();
}
if (sendacpi)
- acpi_bus_generate_event(ibm->acpi->device, event, hkey);
+ acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
} else {
printk(IBM_ERR "unknown hotkey notification event %d\n", event);
- acpi_bus_generate_event(ibm->acpi->device, event, 0);
+ acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
}
}
int docked = dock_docked();
int pci = ibm->acpi->hid && ibm->acpi->device &&
acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids);
+ int data;
if (event == 1 && !pci) /* 570 */
- acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */
+ data = 1; /* button */
else if (event == 1 && pci) /* 570 */
- acpi_bus_generate_event(ibm->acpi->device, event, 3); /* dock */
+ data = 3; /* dock */
else if (event == 3 && docked)
- acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */
+ data = 1; /* button */
else if (event == 3 && !docked)
- acpi_bus_generate_event(ibm->acpi->device, event, 2); /* undock */
+ data = 2; /* undock */
else if (event == 0 && docked)
- acpi_bus_generate_event(ibm->acpi->device, event, 3); /* dock */
+ data = 3; /* dock */
else {
printk(IBM_ERR "unknown dock event %d, status %d\n",
event, _sta(dock_handle));
- acpi_bus_generate_event(ibm->acpi->device, event, 0); /* unknown */
+ data = 0; /* unknown */
}
+ acpi_bus_generate_proc_event(ibm->acpi->device, event, data);
+ acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
+ ibm->acpi->device->dev.bus_id,
+ event, data);
}
static int dock_read(char *p)
static void bay_notify(struct ibm_struct *ibm, u32 event)
{
- acpi_bus_generate_event(ibm->acpi->device, event, 0);
+ acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
+ acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
+ ibm->acpi->device->dev.bus_id,
+ event, 0);
}
#define bay_occupied(b) (_sta(b##_handle) & 1)
static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ unsigned long flags;
board_info_t *db = (board_info_t *) dev->priv;
PRINTK3("dm9000_start_xmit\n");
if (db->tx_pkt_cnt > 1)
return 1;
- netif_stop_queue(dev);
-
- /* Disable all interrupts */
- iow(db, DM9000_IMR, IMR_PAR);
+ spin_lock_irqsave(&db->lock, flags);
/* Move data to DM9000 TX RAM */
writeb(DM9000_MWCMD, db->io_addr);
(db->outblk)(db->io_data, skb->data, skb->len);
db->stats.tx_bytes += skb->len;
+ db->tx_pkt_cnt++;
/* TX control: First packet immediately send, second packet queue */
- if (db->tx_pkt_cnt == 0) {
-
- /* First Packet */
- db->tx_pkt_cnt++;
-
+ if (db->tx_pkt_cnt == 1) {
/* Set TX length to DM9000 */
iow(db, DM9000_TXPLL, skb->len & 0xff);
iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff);
iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
dev->trans_start = jiffies; /* save the time stamp */
-
} else {
/* Second packet */
- db->tx_pkt_cnt++;
db->queue_pkt_len = skb->len;
+ netif_stop_queue(dev);
}
+ spin_unlock_irqrestore(&db->lock, flags);
+
/* free this SKB */
dev_kfree_skb(skb);
- /* Re-enable resource check */
- if (db->tx_pkt_cnt == 1)
- netif_wake_queue(dev);
-
- /* Re-enable interrupt */
- iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
-
return 0;
}
MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue "
"[2^x - 1], x = [6..14]. Default = "
__MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")");
-MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
+MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 ");
static int port_name_cnt = 0;
static LIST_HEAD(adapter_list);
struct device_attribute *attr, char *buf)
{
struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
- return sprintf(buf, "0x%X", port->logical_port_id);
+ return sprintf(buf, "%d", port->logical_port_id);
}
static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id,
u32 logical_port_id;
- sscanf(buf, "%X", &logical_port_id);
+ sscanf(buf, "%d", &logical_port_id);
port = ehea_get_port(adapter, logical_port_id);
int i;
u32 logical_port_id;
- sscanf(buf, "%X", &logical_port_id);
+ sscanf(buf, "%d", &logical_port_id);
port = ehea_get_port(adapter, logical_port_id);
if (!cq)
return 0;
+ hcp_epas_dtor(&cq->epas);
+
if ((hret = ehea_destroy_cq_res(cq, NORMAL_FREE)) == H_R_STATE) {
ehea_error_data(cq->adapter, cq->fw_handle);
hret = ehea_destroy_cq_res(cq, FORCE_FREE);
if (!eq)
return 0;
+ hcp_epas_dtor(&eq->epas);
+
if ((hret = ehea_destroy_eq_res(eq, NORMAL_FREE)) == H_R_STATE) {
ehea_error_data(eq->adapter, eq->fw_handle);
hret = ehea_destroy_eq_res(eq, FORCE_FREE);
if (!qp)
return 0;
+ hcp_epas_dtor(&qp->epas);
+
if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
ehea_error_data(qp->adapter, qp->fw_handle);
hret = ehea_destroy_qp_res(qp, FORCE_FREE);
#define PHY_OUI_MARVELL 0x5043
#define PHY_OUI_CICADA 0x03f1
#define PHY_OUI_VITESSE 0x01c1
-#define PHY_OUI_REALTEK 0x01c1
+#define PHY_OUI_REALTEK 0x0732
#define PHYID1_OUI_MASK 0x03ff
#define PHYID1_OUI_SHFT 6
#define PHYID2_OUI_MASK 0xfc00
priv->stats.rx_length_errors++;
skb = priv->rx_skbs[priv->rx_write];
} else {
- skb = alloc_skb(METH_RX_BUFF_SIZE, GFP_ATOMIC | GFP_DMA);
+ skb = alloc_skb(METH_RX_BUFF_SIZE, GFP_ATOMIC);
if (!skb) {
/* Ouch! No memory! Drop packet on the floor */
DPRINTK("No mem: dropping packet\n");
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.3.1-1.248"
+#define MYRI10GE_VERSION_STR "1.3.2-1.269"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
{
struct pci_dev *pdev = mgp->pdev;
struct device *dev = &pdev->dev;
- int cap, status;
- u16 val;
+ int status;
mgp->tx.boundary = 4096;
/*
* Verify the max read request size was set to 4KB
* before trying the test with 4KB.
*/
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (cap < 64) {
- dev_err(dev, "Bad PCI_CAP_ID_EXP location %d\n", cap);
- goto abort;
- }
- status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val);
- if (status != 0) {
+ status = pcie_get_readrq(pdev);
+ if (status < 0) {
dev_err(dev, "Couldn't read max read req size: %d\n", status);
goto abort;
}
- if ((val & (5 << 12)) != (5 << 12)) {
- dev_warn(dev, "Max Read Request size != 4096 (0x%x)\n", val);
+ if (status != 4096) {
+ dev_warn(dev, "Max Read Request size != 4096 (%d)\n", status);
mgp->tx.boundary = 2048;
}
/*
size_t bytes;
int i;
int status = -ENXIO;
- int cap;
int dac_enabled;
- u16 val;
netdev = alloc_etherdev(sizeof(*mgp));
if (netdev == NULL) {
= pci_find_capability(pdev, PCI_CAP_ID_VNDR);
/* Set our max read request to 4KB */
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (cap < 64) {
- dev_err(&pdev->dev, "Bad PCI_CAP_ID_EXP location %d\n", cap);
- goto abort_with_netdev;
- }
- status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val);
- if (status != 0) {
- dev_err(&pdev->dev, "Error %d reading PCI_EXP_DEVCTL\n",
- status);
- goto abort_with_netdev;
- }
- val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12);
- status = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, val);
+ status = pcie_set_readrq(pdev, 4096);
if (status != 0) {
dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n",
status);
*/
int genphy_setup_forced(struct phy_device *phydev)
{
- int ctl = BMCR_RESET;
+ int ctl = 0;
phydev->pause = phydev->asym_pause = 0;
return err;
}
-static void __exit sgiseeq_remove(struct platform_device *pdev)
+static int __exit sgiseeq_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct sgiseeq_private *sp = netdev_priv(dev);
free_page((unsigned long) sp->srings);
free_netdev(dev);
platform_set_drvdata(pdev, NULL);
+
+ return 0;
}
static struct platform_driver sgiseeq_driver = {
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.16"
+#define DRV_VERSION "1.17"
#define PFX DRV_NAME " "
/*
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
-static int idle_timeout = 100;
-module_param(idle_timeout, int, 0);
-MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
-
static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
else
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
+ hw->chip_id == CHIP_ID_YUKON_EX) {
u32 reg;
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
reg = sky2_pci_read32(hw, PCI_DEV_REG4);
/* set all bits to 0 except bits 15..12 and 8 */
reg &= P_ASPM_CONTROL_MSK;
reg = sky2_read32(hw, B2_GP_IO);
reg |= GLB_GPIO_STAT_RACE_DIS;
sky2_write32(hw, B2_GP_IO, reg);
+
+ sky2_read32(hw, B2_GP_IO);
}
}
if (netif_msg_ifdown(sky2))
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
+ if (netif_carrier_ok(dev) && --hw->active == 0)
+ del_timer(&hw->watchdog_timer);
+
/* Stop more packets from being queued */
netif_stop_queue(dev);
netif_carrier_on(sky2->netdev);
+ if (hw->active++ == 0)
+ mod_timer(&hw->watchdog_timer, jiffies + 1);
+
+
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
netif_carrier_off(sky2->netdev);
+ /* Stop watchdog if both ports are not active */
+ if (--hw->active == 0)
+ del_timer(&hw->watchdog_timer);
+
+
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK);
}
-/* If idle then force a fake soft NAPI poll once a second
- * to work around cases where sharing an edge triggered interrupt.
- */
-static inline void sky2_idle_start(struct sky2_hw *hw)
-{
- if (idle_timeout > 0)
- mod_timer(&hw->idle_timer,
- jiffies + msecs_to_jiffies(idle_timeout));
-}
-
-static void sky2_idle(unsigned long arg)
+/* Check for lost IRQ once a second */
+static void sky2_watchdog(unsigned long arg)
{
struct sky2_hw *hw = (struct sky2_hw *) arg;
- struct net_device *dev = hw->dev[0];
- if (__netif_rx_schedule_prep(dev))
- __netif_rx_schedule(dev);
+ if (sky2_read32(hw, B0_ISRC)) {
+ struct net_device *dev = hw->dev[0];
+
+ if (__netif_rx_schedule_prep(dev))
+ __netif_rx_schedule(dev);
+ }
- mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout));
+ if (hw->active > 0)
+ mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
}
/* Hardware/software error handling */
struct net_device *dev;
int i, err;
- del_timer_sync(&hw->idle_timer);
-
rtnl_lock();
sky2_write32(hw, B0_IMSK, 0);
sky2_read32(hw, B0_IMSK);
}
}
- sky2_idle_start(hw);
-
rtnl_unlock();
}
sky2_show_addr(dev1);
}
- setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
+ setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw);
INIT_WORK(&hw->restart_work, sky2_restart);
- sky2_idle_start(hw);
-
pci_set_drvdata(pdev, hw);
return 0;
if (!hw)
return;
- del_timer_sync(&hw->idle_timer);
+ del_timer_sync(&hw->watchdog_timer);
flush_scheduled_work();
if (!hw)
return 0;
- del_timer_sync(&hw->idle_timer);
netif_poll_disable(hw->dev[0]);
for (i = 0; i < hw->ports; i++) {
}
netif_poll_enable(hw->dev[0]);
- sky2_idle_start(hw);
+
return 0;
out:
dev_err(&pdev->dev, "resume failed (%d)\n", err);
if (!hw)
return;
- del_timer_sync(&hw->idle_timer);
netif_poll_disable(hw->dev[0]);
for (i = 0; i < hw->ports; i++) {
u8 chip_rev;
u8 pmd_type;
u8 ports;
+ u8 active;
struct sky2_status_le *st_le;
u32 st_idx;
dma_addr_t st_dma;
- struct timer_list idle_timer;
+ struct timer_list watchdog_timer;
struct work_struct restart_work;
int msi;
wait_queue_head_t msi_wait;
if (subevent == 0x80) {
dbg("%s: generationg bus event\n", __FUNCTION__);
- acpi_bus_generate_event(note->device, note->event, detail);
+ acpi_bus_generate_proc_event(note->device, note->event, detail);
+ acpi_bus_generate_netlink_event(note->device->pnp.device_class,
+ note->device->dev.bus_id,
+ note->event, detail);
} else
note->event = event;
}
status = acpi_get_object_info(handle, &info_buffer);
if (ACPI_FAILURE(status)) {
- err("%s: Failed to get device information", __FUNCTION__);
+ err("%s: Failed to get device information\n", __FUNCTION__);
return 0;
}
info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0';
int found;
struct pnp_dev *dev;
- if (i == PNP_MAX_DEVICES
- || !*drv_id->devs[i].id)
+ if (i == PNP_MAX_DEVICES ||
+ !*drv_id->devs[i].id)
return drv_id;
found = 0;
card_for_each_dev(card, dev) {
- if (compare_pnp_id
- (dev->id, drv_id->devs[i].id)) {
+ if (compare_pnp_id(dev->id,
+ drv_id->devs[i].id)) {
found = 1;
break;
}
return 0;
- err_name:
+err_name:
device_remove_file(&card->dev, &dev_attr_name);
return rc;
}
pos = pos->next;
}
- done:
+done:
return NULL;
- found:
+found:
dev->card_link = clink;
dev->dev.driver = &drv->link.driver;
if (pnp_bus_type.probe(&dev->dev))
return dev;
- err_out:
+err_out:
dev->dev.driver = NULL;
dev->card_link = NULL;
return NULL;
int nodenum;
struct list_head *pos;
- if (!protocol)
- return -EINVAL;
-
INIT_LIST_HEAD(&protocol->devices);
INIT_LIST_HEAD(&protocol->cards);
nodenum = 0;
struct pnp_id *id;
struct pnp_id *next;
- if (!dev)
- return;
id = dev->id;
while (id) {
next = id->next;
*/
int pnp_add_device(struct pnp_dev *dev)
{
- if (!dev || !dev->protocol || dev->card)
+ if (dev->card)
return -EINVAL;
dev->dev.parent = &dev->protocol->dev;
sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
goto fail;
return error;
- fail:
+fail:
pnp_device_detach(pnp_dev);
return error;
}
{
struct pnp_id *ptr;
- if (!id)
- return -EINVAL;
- if (!dev)
- return -EINVAL;
id->next = NULL;
ptr = dev->id;
while (ptr && ptr->next)
up(&pnp_res_mutex);
goto done;
}
- done:
+
+done:
if (retval < 0)
return retval;
return count;
return 0;
- err_res:
+err_res:
device_remove_file(&dev->dev, &dev_attr_resources);
- err_opt:
+err_opt:
device_remove_file(&dev->dev, &dev_attr_options);
- err:
+err:
return rc;
}
#if 0
#define ISAPNP_REGION_OK
#endif
-#if 0
-#define ISAPNP_DEBUG
-#endif
int isapnp_disable; /* Disable ISA PnP */
static int isapnp_rdp; /* Read Data Port */
static unsigned char isapnp_checksum_value;
static DEFINE_MUTEX(isapnp_cfg_mutex);
-static int isapnp_detected;
static int isapnp_csn_count;
/* some prototypes */
} else if (iteration > 1) {
break;
}
- __next:
+__next:
if (csn == 255)
break;
checksum = 0x6a;
"isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n",
type, dev->number, card->number);
}
- __skip:
+__skip:
if (size > 0)
isapnp_skip_bytes(size);
}
"isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n",
type, card->number);
}
- __skip:
+__skip:
if (size > 0)
isapnp_skip_bytes(size);
}
EXPORT_SYMBOL(isapnp_present);
EXPORT_SYMBOL(isapnp_cfg_begin);
EXPORT_SYMBOL(isapnp_cfg_end);
-#if 0
-EXPORT_SYMBOL(isapnp_read_byte);
-#endif
EXPORT_SYMBOL(isapnp_write_byte);
static int isapnp_read_resources(struct pnp_dev *dev,
struct pnp_resource_table *res)
{
int ret;
+
pnp_init_resource_table(res);
isapnp_cfg_begin(dev->card->number, dev->number);
ret = isapnp_read_resources(dev, res);
static int isapnp_disable_resources(struct pnp_dev *dev)
{
- if (!dev || !dev->active)
+ if (!dev->active)
return -EINVAL;
isapnp_cfg_begin(dev->card->number, dev->number);
isapnp_deactivate(dev->number);
struct pnp_dev *dev;
if (isapnp_disable) {
- isapnp_detected = 0;
printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");
return 0;
}
}
isapnp_set_rdp();
}
- isapnp_detected = 1;
if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) {
cards = isapnp_isolate();
if (cards < 0 || (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) {
release_region(_PIDXR, 1);
#endif
release_region(_PNPWRP, 1);
- isapnp_detected = 0;
printk(KERN_INFO
"isapnp: No Plug & Play device found\n");
return 0;
}
}
}
- if (cards) {
+ if (cards)
printk(KERN_INFO
"isapnp: %i Plug & Play card%s detected total\n", cards,
cards > 1 ? "s" : "");
- } else {
+ else
printk(KERN_INFO "isapnp: No Plug & Play card found\n");
- }
isapnp_proc_init();
return 0;
return 0;
}
-#ifdef MODULE
-static int __exit isapnp_proc_detach_device(struct pnp_dev *dev)
-{
- struct pnp_card *bus = dev->card;
- struct proc_dir_entry *de;
- char name[16];
-
- if (!(de = bus->procdir))
- return -EINVAL;
- sprintf(name, "%02x", dev->number);
- remove_proc_entry(name, de);
- return 0;
-}
-
-static int __exit isapnp_proc_detach_bus(struct pnp_card *bus)
-{
- struct proc_dir_entry *de;
- char name[16];
-
- if (!(de = bus->procdir))
- return -EINVAL;
- sprintf(name, "%02x", bus->number);
- remove_proc_entry(name, isapnp_proc_bus_dir);
- return 0;
-}
-#endif /* MODULE */
-
int __init isapnp_proc_init(void)
{
struct pnp_dev *dev;
}
return 0;
}
-
-#ifdef MODULE
-int __exit isapnp_proc_done(void)
-{
- struct pnp_dev *dev;
- struct pnp_bus *card;
-
- isapnp_for_each_dev(dev) {
- isapnp_proc_detach_device(dev);
- }
- isapnp_for_each_card(card) {
- isapnp_proc_detach_bus(card);
- }
- if (isapnp_proc_bus_dir)
- remove_proc_entry("isapnp", proc_bus);
- return 0;
-}
-#endif /* MODULE */
resource_size_t *start, *end;
unsigned long *flags;
- if (!dev || !rule)
- return -EINVAL;
-
if (idx >= PNP_MAX_PORT) {
pnp_err
("More than 4 ports is incompatible with pnp specifications.");
resource_size_t *start, *end;
unsigned long *flags;
- if (!dev || !rule)
- return -EINVAL;
-
if (idx >= PNP_MAX_MEM) {
pnp_err
("More than 8 mems is incompatible with pnp specifications.");
5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
};
- if (!dev || !rule)
- return -EINVAL;
-
if (idx >= PNP_MAX_IRQ) {
pnp_err
("More than 2 irqs is incompatible with pnp specifications.");
1, 3, 5, 6, 7, 0, 2, 4
};
- if (!dev || !rule)
- return -EINVAL;
-
if (idx >= PNP_MAX_DMA) {
pnp_err
("More than 2 dmas is incompatible with pnp specifications.");
up(&pnp_res_mutex);
return 1;
- fail:
+fail:
pnp_clean_resource_table(&dev->res);
up(&pnp_res_mutex);
return 0;
int i;
struct pnp_resource_table *bak;
- if (!dev || !res)
- return -EINVAL;
if (!pnp_can_configure(dev))
return -ENODEV;
bak = pnp_alloc(sizeof(struct pnp_resource_table));
kfree(bak);
return 0;
- fail:
+fail:
dev->res = *bak;
up(&pnp_res_mutex);
kfree(bak);
struct pnp_option *dep;
int i = 1;
- if (!dev)
- return -EINVAL;
-
if (!pnp_can_configure(dev)) {
pnp_dbg("Device %s does not support resource configuration.",
dev->dev.bus_id);
{
int error;
- if (!dev)
- return -EINVAL;
if (dev->active)
return 0; /* the device is already active */
{
int error;
- if (!dev)
- return -EINVAL;
if (!dev->active)
return 0; /* the device is already disabled */
void pnp_resource_change(struct resource *resource, resource_size_t start,
resource_size_t size)
{
- if (resource == NULL)
- return;
resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET);
resource->start = start;
resource->end = start + size - 1;
num++;
return AE_OK;
- err1:
+err1:
kfree(dev_id);
- err:
+err:
kfree(dev);
return -EINVAL;
}
*/
static int irq_flags(int triggering, int polarity)
{
- int flag;
if (triggering == ACPI_LEVEL_SENSITIVE) {
if (polarity == ACPI_ACTIVE_LOW)
- flag = IORESOURCE_IRQ_LOWLEVEL;
+ return IORESOURCE_IRQ_LOWLEVEL;
else
- flag = IORESOURCE_IRQ_HIGHLEVEL;
+ return IORESOURCE_IRQ_HIGHLEVEL;
} else {
if (polarity == ACPI_ACTIVE_LOW)
- flag = IORESOURCE_IRQ_LOWEDGE;
+ return IORESOURCE_IRQ_LOWEDGE;
else
- flag = IORESOURCE_IRQ_HIGHEDGE;
+ return IORESOURCE_IRQ_HIGHEDGE;
}
- return flag;
}
static void decode_irq_flags(int flag, int *triggering, int *polarity)
static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
void *data)
{
- struct pnp_resource_table *res_table =
- (struct pnp_resource_table *)data;
+ struct pnp_resource_table *res_table = data;
int i;
switch (res->type) {
void *data)
{
int priority = 0;
- struct acpipnp_parse_option_s *parse_data =
- (struct acpipnp_parse_option_s *)data;
+ struct acpipnp_parse_option_s *parse_data = data;
struct pnp_dev *dev = parse_data->dev;
struct pnp_option *option = parse_data->option;
static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
void *data)
{
- int *res_cnt = (int *)data;
+ int *res_cnt = data;
if (pnpacpi_supported_resource(res))
(*res_cnt)++;
static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
{
- struct acpi_resource **resource = (struct acpi_resource **)data;
+ struct acpi_resource **resource = data;
if (pnpacpi_supported_resource(res)) {
(*resource)->type = res->type;
int i = 0;
/* pnpacpi_build_resource_template allocates extra mem */
int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
- struct acpi_resource *resource =
- (struct acpi_resource *)buffer->pointer;
+ struct acpi_resource *resource = buffer->pointer;
int port = 0, irq = 0, dma = 0, mem = 0;
pnp_dbg("res cnt %d", res_cnt);
static int pnpbios_disabled;
int pnpbios_dont_use_current_config;
-#ifndef MODULE
static int __init pnpbios_setup(char *str)
{
int invert;
}
__setup("pnpbios=", pnpbios_setup);
-#endif
/* PnP BIOS signature: "$PnP" */
#define PNP_SIGNATURE (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
static int __init pnpbios_thread_init(void)
{
struct task_struct *task;
+
#if defined(CONFIG_PPC_MERGE)
if (check_legacy_ioport(PNPBIOS_BASE))
return 0;
return 0;
}
-#ifndef MODULE
-
-/* init/main.c calls pnpbios_init early */
-
/* Start the kernel thread later: */
module_init(pnpbios_thread_init);
-#else
-
-/*
- * N.B.: Building pnpbios as a module hasn't been fully implemented
- */
-
-MODULE_LICENSE("GPL");
-
-static int __init pnpbios_init_all(void)
-{
- int r;
-
- r = pnpbios_init();
- if (r)
- return r;
- r = pnpbios_thread_init();
- if (r)
- return r;
- return 0;
-}
-
-static void __exit pnpbios_exit(void)
-{
-#ifdef CONFIG_HOTPLUG
- unloading = 1;
- wait_for_completion(&unload_sem);
-#endif
- pnpbios_proc_exit();
- /* We ought to free resources here */
- return;
-}
-
-module_init(pnpbios_init_all);
-module_exit(pnpbios_exit);
-
-#endif
-
EXPORT_SYMBOL(pnpbios_protocol);
goto out;
}
ret = count;
- out:
+out:
kfree(node);
return ret;
}
break;
default: /* an unkown tag */
- len_err:
+len_err:
printk(KERN_ERR
"PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
tag, len);
struct pnp_option *option)
{
struct pnp_mem *mem;
+
mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
return p + 2;
default: /* an unkown tag */
- len_err:
+len_err:
printk(KERN_ERR
"PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
tag, len);
break;
default: /* an unkown tag */
- len_err:
+len_err:
printk(KERN_ERR
"PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
tag, len);
break;
default: /* an unkown tag */
- len_err:
+len_err:
printk(KERN_ERR
"PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
tag, len);
{
struct pnp_option *option;
- if (!dev)
- return NULL;
-
option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED);
/* this should never happen but if it does we'll try to continue */
{
struct pnp_option *option;
- if (!dev)
- return NULL;
-
option = pnp_build_option(priority);
if (dev->dependent) {
{
struct pnp_irq *ptr;
- if (!option)
- return -EINVAL;
- if (!data)
- return -EINVAL;
-
ptr = option->irq;
while (ptr && ptr->next)
ptr = ptr->next;
{
struct pnp_dma *ptr;
- if (!option)
- return -EINVAL;
- if (!data)
- return -EINVAL;
-
ptr = option->dma;
while (ptr && ptr->next)
ptr = ptr->next;
{
struct pnp_port *ptr;
- if (!option)
- return -EINVAL;
- if (!data)
- return -EINVAL;
-
ptr = option->port;
while (ptr && ptr->next)
ptr = ptr->next;
{
struct pnp_mem *ptr;
- if (!option)
- return -EINVAL;
- if (!data)
- return -EINVAL;
-
ptr = option->mem;
while (ptr && ptr->next)
ptr = ptr->next;
oriented.
config STI_CONSOLE
- tristate "STI text console"
+ bool "STI text console"
depends on PARISC
default y
help
}
-/* FIXME: Do we have another solution for this ? */
-static void sti_flush(unsigned long from, unsigned long len)
+static void sti_flush(unsigned long start, unsigned long end)
{
- flush_data_cache();
- flush_kernel_dcache_range(from, len);
- flush_icache_range(from, from+len);
+ flush_icache_range(start, end);
}
void __devinit
sti_rom_copy(unsigned long base, unsigned long count, void *dest)
{
- unsigned long dest_len = count;
unsigned long dest_start = (unsigned long) dest;
/* this still needs to be revisited (see arch/parisc/mm/init.c:246) ! */
dest++;
}
- sti_flush(dest_start, dest_len);
+ sti_flush(dest_start, (unsigned long)dest);
}
static void __devinit
sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest)
{
- unsigned long dest_len = count;
unsigned long dest_start = (unsigned long) dest;
while (count) {
base += 4;
dest++;
}
- sti_flush(dest_start, dest_len);
+
+ sti_flush(dest_start, (unsigned long)dest);
}
static struct sti_rom * __devinit
};
extern struct kset acpi_subsys;
-extern int acpi_bus_generate_genetlink_event(struct acpi_device *device,
- u8 type, int data);
+extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
/*
* External Functions
*/
int acpi_bus_get_status(struct acpi_device *device);
int acpi_bus_get_power(acpi_handle handle, int *state);
int acpi_bus_set_power(acpi_handle handle, int state);
-int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data);
+#ifdef CONFIG_ACPI_PROC_EVENT
+int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data);
int acpi_bus_receive_event(struct acpi_bus_event *event);
+#else
+static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
+ { return 0; }
+#endif
int acpi_bus_register_driver(struct acpi_driver *driver);
void acpi_bus_unregister_driver(struct acpi_driver *driver);
int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
void *context, void **return_value);
acpi_status
-acpi_get_devices(char *HID,
+acpi_get_devices(const char *HID,
acpi_walk_callback user_function,
void *context, void **return_value);
struct acpi_get_devices_info {
acpi_walk_callback user_function;
void *context;
- char *hid;
+ const char *hid;
};
union acpi_aml_operands {
#else /* !CONFIG_X86_IO_APIC */
#define io_apic_assign_pci_irqs 0
-static inline void disable_ioapic_setup(void) { }
#endif
#endif
#define virt_to_bus virt_to_phys
#define bus_to_virt phys_to_virt
+static inline unsigned long isa_bus_to_virt(unsigned long addr) {
+ BUG();
+ return 0;
+}
+
+static inline unsigned long isa_virt_to_bus(void *addr) {
+ BUG();
+ return 0;
+}
+
/*
* Memory mapped I/O
*
--- /dev/null
+#ifndef __ASM_PARISC_VGA_H__
+#define __ASM_PARISC_VGA_H__
+
+/* nothing */
+
+#endif __ASM_PARISC_VGA_H__
/* 1 if "noapic" boot option passed */
extern int skip_ioapic_setup;
+static inline void disable_ioapic_setup(void)
+{
+ skip_ioapic_setup = 1;
+}
+
+
/*
* If we use the IO-APIC for IRQ routing, disable automatic
* assignment of PCI IRQ's.
#define KEY_UNKNOWN 240
+#define KEY_VIDEO_NEXT 241 /* drive next video source */
+#define KEY_VIDEO_PREV 242 /* drive previous video source */
+#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */
+#define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */
+#define KEY_DISPLAY_OFF 245 /* display device to off state */
+
#define BTN_MISC 0x100
#define BTN_0 0x100
#define BTN_1 0x101
#define PCI_DEVICE_ID_VIA_VT3324 0x0324
#define PCI_DEVICE_ID_VIA_VT3336 0x0336
#define PCI_DEVICE_ID_VIA_VT3351 0x0351
+#define PCI_DEVICE_ID_VIA_VT3364 0x0364
#define PCI_DEVICE_ID_VIA_8371_0 0x0391
#define PCI_DEVICE_ID_VIA_8501_0 0x0501
#define PCI_DEVICE_ID_VIA_82C561 0x0561
extern void sched_idle_next(void);
-extern unsigned int sysctl_sched_granularity;
+extern unsigned int sysctl_sched_latency;
+extern unsigned int sysctl_sched_min_granularity;
extern unsigned int sysctl_sched_wakeup_granularity;
extern unsigned int sysctl_sched_batch_wakeup_granularity;
extern unsigned int sysctl_sched_stat_granularity;
* greater than 0, limits the maximum number of CPUs activated in
* SMP mode to <NUM>.
*/
+#ifndef CONFIG_X86_IO_APIC
+static inline void disable_ioapic_setup(void) {};
+#endif
+
static int __init nosmp(char *str)
{
max_cpus = 0;
+ disable_ioapic_setup();
return 0;
}
static int __init maxcpus(char *str)
{
get_option(&str, &max_cpus);
- return 1;
+ if (max_cpus == 0)
+ disable_ioapic_setup();
+
+ return 0;
}
-__setup("maxcpus=", maxcpus);
+early_param("maxcpus=", maxcpus);
#else
#define max_cpus NR_CPUS
#endif
if (task_running(rq, p))
return 0;
- /*
- * Aggressive migration if too many balance attempts have failed:
- */
- if (sd->nr_balance_failed > sd->cache_nice_tries)
- return 1;
-
return 1;
}
static inline void sched_init_granularity(void)
{
unsigned int factor = 1 + ilog2(num_online_cpus());
- const unsigned long gran_limit = 100000000;
+ const unsigned long limit = 100000000;
+
+ sysctl_sched_min_granularity *= factor;
+ if (sysctl_sched_min_granularity > limit)
+ sysctl_sched_min_granularity = limit;
- sysctl_sched_granularity *= factor;
- if (sysctl_sched_granularity > gran_limit)
- sysctl_sched_granularity = gran_limit;
+ sysctl_sched_latency *= factor;
+ if (sysctl_sched_latency > limit)
+ sysctl_sched_latency = limit;
- sysctl_sched_runtime_limit = sysctl_sched_granularity * 8;
- sysctl_sched_wakeup_granularity = sysctl_sched_granularity / 2;
+ sysctl_sched_runtime_limit = sysctl_sched_latency;
+ sysctl_sched_wakeup_granularity = sysctl_sched_min_granularity / 2;
}
#ifdef CONFIG_SMP
*
* Scaled math optimizations by Thomas Gleixner
* Copyright (C) 2007, Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Adaptive scheduling granularity, math enhancements by Peter Zijlstra
+ * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
*/
/*
- * Preemption granularity:
- * (default: 2 msec, units: nanoseconds)
+ * Targeted preemption latency for CPU-bound tasks:
+ * (default: 20ms, units: nanoseconds)
*
- * NOTE: this granularity value is not the same as the concept of
- * 'timeslice length' - timeslices in CFS will typically be somewhat
- * larger than this value. (to see the precise effective timeslice
- * length of your workload, run vmstat and monitor the context-switches
- * field)
+ * NOTE: this latency value is not the same as the concept of
+ * 'timeslice length' - timeslices in CFS are of variable length.
+ * (to see the precise effective timeslice length of your workload,
+ * run vmstat and monitor the context-switches field)
*
* On SMP systems the value of this is multiplied by the log2 of the
* number of CPUs. (i.e. factor 2x on 2-way systems, 3x on 4-way
* systems, 4x on 8-way systems, 5x on 16-way systems, etc.)
+ * Targeted preemption latency for CPU-bound tasks:
+ */
+unsigned int sysctl_sched_latency __read_mostly = 20000000ULL;
+
+/*
+ * Minimal preemption granularity for CPU-bound tasks:
+ * (default: 2 msec, units: nanoseconds)
*/
-unsigned int sysctl_sched_granularity __read_mostly = 2000000000ULL/HZ;
+unsigned int sysctl_sched_min_granularity __read_mostly = 2000000ULL;
/*
* SCHED_BATCH wake-up granularity.
- * (default: 10 msec, units: nanoseconds)
+ * (default: 25 msec, units: nanoseconds)
*
* This option delays the preemption effects of decoupled workloads
* and reduces their over-scheduling. Synchronous workloads will still
* have immediate wakeup/sleep latencies.
*/
-unsigned int sysctl_sched_batch_wakeup_granularity __read_mostly =
- 10000000000ULL/HZ;
+unsigned int sysctl_sched_batch_wakeup_granularity __read_mostly = 25000000UL;
/*
* SCHED_OTHER wake-up granularity.
* and reduces their over-scheduling. Synchronous workloads will still
* have immediate wakeup/sleep latencies.
*/
-unsigned int sysctl_sched_wakeup_granularity __read_mostly = 1000000000ULL/HZ;
+unsigned int sysctl_sched_wakeup_granularity __read_mostly = 1000000UL;
unsigned int sysctl_sched_stat_granularity __read_mostly;
/*
- * Initialized in sched_init_granularity():
+ * Initialized in sched_init_granularity() [to 5 times the base granularity]:
*/
unsigned int sysctl_sched_runtime_limit __read_mostly;
*/
/*
+ * Calculate the preemption granularity needed to schedule every
+ * runnable task once per sysctl_sched_latency amount of time.
+ * (down to a sensible low limit on granularity)
+ *
+ * For example, if there are 2 tasks running and latency is 10 msecs,
+ * we switch tasks every 5 msecs. If we have 3 tasks running, we have
+ * to switch tasks every 3.33 msecs to get a 10 msecs observed latency
+ * for each task. We do finer and finer scheduling up to until we
+ * reach the minimum granularity value.
+ *
+ * To achieve this we use the following dynamic-granularity rule:
+ *
+ * gran = lat/nr - lat/nr/nr
+ *
+ * This comes out of the following equations:
+ *
+ * kA1 + gran = kB1
+ * kB2 + gran = kA2
+ * kA2 = kA1
+ * kB2 = kB1 - d + d/nr
+ * lat = d * nr
+ *
+ * Where 'k' is key, 'A' is task A (waiting), 'B' is task B (running),
+ * '1' is start of time, '2' is end of time, 'd' is delay between
+ * 1 and 2 (during which task B was running), 'nr' is number of tasks
+ * running, 'lat' is the the period of each task. ('lat' is the
+ * sched_latency that we aim for.)
+ */
+static long
+sched_granularity(struct cfs_rq *cfs_rq)
+{
+ unsigned int gran = sysctl_sched_latency;
+ unsigned int nr = cfs_rq->nr_running;
+
+ if (nr > 1) {
+ gran = gran/nr - gran/nr/nr;
+ gran = max(gran, sysctl_sched_min_granularity);
+ }
+
+ return gran;
+}
+
+/*
* We rescale the rescheduling granularity of tasks according to their
* nice level, but only linearly, not exponentially:
*/
delta_fair = calc_delta_fair(delta_exec, lw);
delta_mine = calc_delta_mine(delta_exec, curr->load.weight, lw);
- if (cfs_rq->sleeper_bonus > sysctl_sched_granularity) {
- delta = min(cfs_rq->sleeper_bonus, (u64)delta_exec);
- delta = calc_delta_mine(delta, curr->load.weight, lw);
- delta = min((u64)delta, cfs_rq->sleeper_bonus);
+ if (cfs_rq->sleeper_bonus > sysctl_sched_latency) {
+ delta = min((u64)delta_mine, cfs_rq->sleeper_bonus);
+ delta = min(delta, (unsigned long)(
+ (long)sysctl_sched_runtime_limit - curr->wait_runtime));
cfs_rq->sleeper_bonus -= delta;
delta_mine -= delta;
}
unsigned long load = cfs_rq->load.weight, delta_fair;
long prev_runtime;
+ /*
+ * Do not boost sleepers if there's too much bonus 'in flight'
+ * already:
+ */
+ if (unlikely(cfs_rq->sleeper_bonus > sysctl_sched_runtime_limit))
+ return;
+
if (sysctl_sched_features & SCHED_FEAT_SLEEPER_LOAD_AVG)
load = rq_of(cfs_rq)->cpu_load[2];
prev_runtime = se->wait_runtime;
__add_wait_runtime(cfs_rq, se, delta_fair);
+ schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
delta_fair = se->wait_runtime - prev_runtime;
/*
* Track the amount of bonus we've given to sleepers:
*/
cfs_rq->sleeper_bonus += delta_fair;
- if (unlikely(cfs_rq->sleeper_bonus > sysctl_sched_runtime_limit))
- cfs_rq->sleeper_bonus = sysctl_sched_runtime_limit;
-
- schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
}
static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
if (next == curr)
return;
- __check_preempt_curr_fair(cfs_rq, next, curr, sysctl_sched_granularity);
+ __check_preempt_curr_fair(cfs_rq, next, curr,
+ sched_granularity(cfs_rq));
}
/**************************************************
* it will preempt the parent:
*/
p->se.fair_key = current->se.fair_key -
- niced_granularity(&rq->curr->se, sysctl_sched_granularity) - 1;
+ niced_granularity(&rq->curr->se, sched_granularity(cfs_rq)) - 1;
/*
* The first wait is dominated by the child-runs-first logic,
* so do not credit it with that waiting time yet:
* -granularity/2, so initialize the task with that:
*/
if (sysctl_sched_features & SCHED_FEAT_START_DEBIT)
- p->se.wait_runtime = -(sysctl_sched_granularity / 2);
+ p->se.wait_runtime = -(sched_granularity(cfs_rq) / 2);
__enqueue_entity(cfs_rq, se);
}
*/
static void set_curr_task_fair(struct rq *rq)
{
- struct sched_entity *se = &rq->curr.se;
+ struct sched_entity *se = &rq->curr->se;
for_each_sched_entity(se)
set_next_entity(cfs_rq_of(se), se);
return;
p->time_slice = static_prio_timeslice(p->static_prio);
- set_tsk_need_resched(p);
- /* put it at the end of the queue: */
- requeue_task_rt(rq, p);
+ /*
+ * Requeue to the end of queue if we are not the only element
+ * on the queue:
+ */
+ if (p->run_list.prev != p->run_list.next) {
+ requeue_task_rt(rq, p);
+ set_tsk_need_resched(p);
+ }
}
static struct sched_class rt_sched_class __read_mostly = {
#ifdef CONFIG_SCHED_DEBUG
{
.ctl_name = CTL_UNNUMBERED,
- .procname = "sched_granularity_ns",
- .data = &sysctl_sched_granularity,
+ .procname = "sched_min_granularity_ns",
+ .data = &sysctl_sched_min_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_sched_granularity_ns,
+ .extra2 = &max_sched_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_latency_ns",
+ .data = &sysctl_sched_latency,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_features",
+ .data = &sysctl_sched_features,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+#endif
#ifdef CONFIG_PROVE_LOCKING
{
.ctl_name = CTL_UNNUMBERED,
},
#endif
{
- .ctl_name = CTL_UNNUMBERED,
- .procname = "sched_features",
- .data = &sysctl_sched_features,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
-#endif
- {
.ctl_name = KERN_PANIC,
.procname = "panic",
.data = &panic_timeout,