From 4b95320fc4d21b0ff2f8604305dd6c851aff6096 Mon Sep 17 00:00:00 2001 From: Wang Zhenyu Date: Wed, 17 Jan 2007 11:07:54 +0800 Subject: [AGPGART] intel_agp: restore graphics device's pci space early in resume Currently in resuming path graphics device's pci space restore is behind host bridge, so resume function wrongly accesses graphics device's space. This makes resuming failure which crashed X. here's a patch to restore device's pci space early, which makes resuming ok with X. Signed-off-by: Wang Zhenyu Signed-off-by: Dave Jones --- drivers/char/agp/intel-agp.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index ab0a9c0ad7c0..a3011de51f7c 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -1955,6 +1955,15 @@ static int agp_intel_resume(struct pci_dev *pdev) pci_restore_state(pdev); + /* We should restore our graphics device's config space, + * as host bridge (00:00) resumes before graphics device (02:00), + * then our access to its pci space can work right. + */ + if (intel_i810_private.i810_dev) + pci_restore_state(intel_i810_private.i810_dev); + if (intel_i830_private.i830_dev) + pci_restore_state(intel_i830_private.i830_dev); + if (bridge->driver == &intel_generic_driver) intel_configure(); else if (bridge->driver == &intel_850_driver) -- cgit v1.2.3 From 79603a35009ff39562cd5634fa1cf513eb080f27 Mon Sep 17 00:00:00 2001 From: Mark Gross Date: Mon, 22 Jan 2007 20:40:44 -0800 Subject: [PATCH] tlclk: bug fix + misc fixes The following patch fixes a few problems with the tlclk driver. * bug in the select_amcb1_transmit_clock * racy read sys call * racy open sys call * use of add_timer where mod_timer would be better * change to the timer data parameter use Signed-off-by: Mark Gross Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tlclk.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 448d5083c381..4fac2bdf6215 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -186,6 +186,7 @@ static int got_event; /* if events processing have been done */ static void switchover_timeout(unsigned long data); static struct timer_list switchover_timer = TIMER_INITIALIZER(switchover_timeout , 0, 0); +static unsigned long tlclk_timer_data; static struct tlclk_alarms *alarm_events; @@ -197,10 +198,19 @@ static irqreturn_t tlclk_interrupt(int irq, void *dev_id); static DECLARE_WAIT_QUEUE_HEAD(wq); +static unsigned long useflags; +static DEFINE_MUTEX(tlclk_mutex); + static int tlclk_open(struct inode *inode, struct file *filp) { int result; + if (test_and_set_bit(0, &useflags)) + return -EBUSY; + /* this legacy device is always one per system and it doesn't + * know how to handle multiple concurrent clients. + */ + /* Make sure there is no interrupt pending while * initialising interrupt handler */ inb(TLCLK_REG6); @@ -221,6 +231,7 @@ static int tlclk_open(struct inode *inode, struct file *filp) static int tlclk_release(struct inode *inode, struct file *filp) { free_irq(telclk_interrupt, tlclk_interrupt); + clear_bit(0, &useflags); return 0; } @@ -230,26 +241,25 @@ static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, { if (count < sizeof(struct tlclk_alarms)) return -EIO; + if (mutex_lock_interruptible(&tlclk_mutex)) + return -EINTR; + wait_event_interruptible(wq, got_event); - if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) + if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) { + mutex_unlock(&tlclk_mutex); return -EFAULT; + } memset(alarm_events, 0, sizeof(struct tlclk_alarms)); got_event = 0; + mutex_unlock(&tlclk_mutex); return sizeof(struct tlclk_alarms); } -static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count, - loff_t *f_pos) -{ - return 0; -} - static const struct file_operations tlclk_fops = { .read = tlclk_read, - .write = tlclk_write, .open = tlclk_open, .release = tlclk_release, @@ -540,7 +550,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d, SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7); switch (val) { case CLK_8_592MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); + SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); break; case CLK_11_184MHz: SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); @@ -549,7 +559,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d, SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); break; case CLK_44_736MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); + SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); break; } } else @@ -839,11 +849,13 @@ static void __exit tlclk_cleanup(void) static void switchover_timeout(unsigned long data) { - if ((data & 1)) { - if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08)) + unsigned long flags = *(unsigned long *) data; + + if ((flags & 1)) { + if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08)) alarm_events->switchover_primary++; } else { - if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08)) + if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08)) alarm_events->switchover_secondary++; } @@ -901,8 +913,9 @@ static irqreturn_t tlclk_interrupt(int irq, void *dev_id) /* TIMEOUT in ~10ms */ switchover_timer.expires = jiffies + msecs_to_jiffies(10); - switchover_timer.data = inb(TLCLK_REG1); - add_timer(&switchover_timer); + tlclk_timer_data = inb(TLCLK_REG1); + switchover_timer.data = (unsigned long) &tlclk_timer_data; + mod_timer(&switchover_timer, switchover_timer.expires); } else { got_event = 1; wake_up(&wq); -- cgit v1.2.3 From 364ca8a897eadb2f0e76b7f0ffe94168f6d83d66 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Mon, 22 Jan 2007 23:01:06 +0900 Subject: [MIPS] Vr41xx: Fix after GENERIC_HARDIRQS_NO__DO_IRQ change Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle --- arch/mips/vr41xx/common/irq.c | 12 +++-- drivers/char/vr41xx_giu.c | 114 +++++++++++++++++++----------------------- 2 files changed, 61 insertions(+), 65 deletions(-) (limited to 'drivers/char') diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 397ba94cd7ec..16decf4ac2f4 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -1,7 +1,7 @@ /* * Interrupt handing routines for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa + * Copyright (C) 2005-2007 Yoichi Yuasa * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -73,13 +73,19 @@ static void irq_dispatch(unsigned int irq) if (cascade->get_irq != NULL) { unsigned int source_irq = irq; desc = irq_desc + source_irq; - desc->chip->ack(source_irq); + if (desc->chip->mask_ack) + desc->chip->mask_ack(source_irq); + else { + desc->chip->mask(source_irq); + desc->chip->ack(source_irq); + } irq = cascade->get_irq(irq); if (irq < 0) atomic_inc(&irq_err_count); else irq_dispatch(irq); - desc->chip->end(source_irq); + if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) + desc->chip->unmask(source_irq); } else do_IRQ(irq); } diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index a744dad9cf45..0cea8d4907df 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 MontaVista Software Inc. * Author: Yoichi Yuasa - * Copyright (C) 2003-2005 Yoichi Yuasa + * Copyright (C) 2003-2007 Yoichi Yuasa * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -125,30 +125,17 @@ static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) return data; } -static unsigned int startup_giuint_low_irq(unsigned int irq) +static void ack_giuint_low(unsigned int irq) { - unsigned int pin; - - pin = GPIO_PIN_OF_IRQ(irq); - giu_write(GIUINTSTATL, 1 << pin); - giu_set(GIUINTENL, 1 << pin); - - return 0; + giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); } -static void shutdown_giuint_low_irq(unsigned int irq) +static void mask_giuint_low(unsigned int irq) { giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); } -static void enable_giuint_low_irq(unsigned int irq) -{ - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); -} - -#define disable_giuint_low_irq shutdown_giuint_low_irq - -static void ack_giuint_low_irq(unsigned int irq) +static void mask_ack_giuint_low(unsigned int irq) { unsigned int pin; @@ -157,46 +144,30 @@ static void ack_giuint_low_irq(unsigned int irq) giu_write(GIUINTSTATL, 1 << pin); } -static void end_giuint_low_irq(unsigned int irq) +static void unmask_giuint_low(unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); + giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); } -static struct hw_interrupt_type giuint_low_irq_type = { - .typename = "GIUINTL", - .startup = startup_giuint_low_irq, - .shutdown = shutdown_giuint_low_irq, - .enable = enable_giuint_low_irq, - .disable = disable_giuint_low_irq, - .ack = ack_giuint_low_irq, - .end = end_giuint_low_irq, +static struct irq_chip giuint_low_irq_chip = { + .name = "GIUINTL", + .ack = ack_giuint_low, + .mask = mask_giuint_low, + .mask_ack = mask_ack_giuint_low, + .unmask = unmask_giuint_low, }; -static unsigned int startup_giuint_high_irq(unsigned int irq) +static void ack_giuint_high(unsigned int irq) { - unsigned int pin; - - pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; - giu_write(GIUINTSTATH, 1 << pin); - giu_set(GIUINTENH, 1 << pin); - - return 0; + giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); } -static void shutdown_giuint_high_irq(unsigned int irq) +static void mask_giuint_high(unsigned int irq) { giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); } -static void enable_giuint_high_irq(unsigned int irq) -{ - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); -} - -#define disable_giuint_high_irq shutdown_giuint_high_irq - -static void ack_giuint_high_irq(unsigned int irq) +static void mask_ack_giuint_high(unsigned int irq) { unsigned int pin; @@ -205,20 +176,17 @@ static void ack_giuint_high_irq(unsigned int irq) giu_write(GIUINTSTATH, 1 << pin); } -static void end_giuint_high_irq(unsigned int irq) +static void unmask_giuint_high(unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); + giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); } -static struct hw_interrupt_type giuint_high_irq_type = { - .typename = "GIUINTH", - .startup = startup_giuint_high_irq, - .shutdown = shutdown_giuint_high_irq, - .enable = enable_giuint_high_irq, - .disable = disable_giuint_high_irq, - .ack = ack_giuint_high_irq, - .end = end_giuint_high_irq, +static struct irq_chip giuint_high_irq_chip = { + .name = "GIUINTH", + .ack = ack_giuint_high, + .mask = mask_giuint_high, + .mask_ack = mask_ack_giuint_high, + .unmask = unmask_giuint_high, }; static int giu_get_irq(unsigned int irq) @@ -282,9 +250,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ break; } } + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_low_irq_chip, + handle_edge_irq); } else { giu_clear(GIUINTTYPL, mask); giu_clear(GIUINTHTSELL, mask); + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_low_irq_chip, + handle_level_irq); } giu_write(GIUINTSTATL, mask); } else if (pin < GIUINT_HIGH_MAX) { @@ -311,9 +285,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ break; } } + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_high_irq_chip, + handle_edge_irq); } else { giu_clear(GIUINTTYPH, mask); giu_clear(GIUINTHTSELH, mask); + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_high_irq_chip, + handle_level_irq); } giu_write(GIUINTSTATH, mask); } @@ -617,10 +597,11 @@ static const struct file_operations gpio_fops = { static int __devinit giu_probe(struct platform_device *dev) { unsigned long start, size, flags = 0; - unsigned int nr_pins = 0; + unsigned int nr_pins = 0, trigger, i, pin; struct resource *res1, *res2 = NULL; void *base; - int retval, i; + struct irq_chip *chip; + int retval; switch (current_cpu_data.cputype) { case CPU_VR4111: @@ -688,11 +669,20 @@ static int __devinit giu_probe(struct platform_device *dev) giu_write(GIUINTENL, 0); giu_write(GIUINTENH, 0); + trigger = giu_read(GIUINTTYPH) << 16; + trigger |= giu_read(GIUINTTYPL); for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { - if (i < GIU_IRQ(GIUINT_HIGH_OFFSET)) - irq_desc[i].chip = &giuint_low_irq_type; + pin = GPIO_PIN_OF_IRQ(i); + if (pin < GIUINT_HIGH_OFFSET) + chip = &giuint_low_irq_chip; else - irq_desc[i].chip = &giuint_high_irq_type; + chip = &giuint_high_irq_chip; + + if (trigger & (1 << pin)) + set_irq_chip_and_handler(i, chip, handle_edge_irq); + else + set_irq_chip_and_handler(i, chip, handle_level_irq); + } return cascade_irq(GIUINT_IRQ, giu_get_irq); -- cgit v1.2.3 From c30efbaeaa9297fb1a35ef952350e0c2bb7a3d47 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 28 Jan 2007 17:39:19 -0500 Subject: [AGPGART] Prevent (unlikely) memory leak in amd_create_gatt_pages() If we fail an alloc, unwind the previous allocs that succeeded. Spotted-by: Alan Grimes Signed-off-by: Dave Jones --- drivers/char/agp/amd-k7-agp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 51d0d562d01e..c85c8cadb6df 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -101,6 +101,11 @@ static int amd_create_gatt_pages(int nr_tables) for (i = 0; i < nr_tables; i++) { entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL); if (entry == NULL) { + while (i > 0) { + kfree(tables[i-1]); + i--; + } + kfree(tables); retval = -ENOMEM; break; } -- cgit v1.2.3 From 87a17f31a3bc9bf0c7e7493add19ef200e741248 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 28 Jan 2007 17:41:37 -0500 Subject: [AGPGART] Remove pointless typedef in ati-agp This seems to exist just to save people typing 'struct' a few times, and doesn't provide any additional value. Signed-off-by: Dave Jones --- drivers/char/agp/ati-agp.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index f244c6682738..0994d3534447 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -41,18 +41,18 @@ static struct gatt_mask ati_generic_masks[] = }; -typedef struct _ati_page_map { +struct ati_page_map { unsigned long *real; unsigned long __iomem *remapped; -} ati_page_map; +}; static struct _ati_generic_private { volatile u8 __iomem *registers; - ati_page_map **gatt_pages; + struct ati_page_map **gatt_pages; int num_tables; } ati_generic_private; -static int ati_create_page_map(ati_page_map *page_map) +static int ati_create_page_map(struct ati_page_map *page_map) { int i, err = 0; @@ -82,7 +82,7 @@ static int ati_create_page_map(ati_page_map *page_map) } -static void ati_free_page_map(ati_page_map *page_map) +static void ati_free_page_map(struct ati_page_map *page_map) { unmap_page_from_agp(virt_to_page(page_map->real)); iounmap(page_map->remapped); @@ -94,8 +94,8 @@ static void ati_free_page_map(ati_page_map *page_map) static void ati_free_gatt_pages(void) { int i; - ati_page_map **tables; - ati_page_map *entry; + struct ati_page_map **tables; + struct ati_page_map *entry; tables = ati_generic_private.gatt_pages; for (i = 0; i < ati_generic_private.num_tables; i++) { @@ -112,17 +112,17 @@ static void ati_free_gatt_pages(void) static int ati_create_gatt_pages(int nr_tables) { - ati_page_map **tables; - ati_page_map *entry; + struct ati_page_map **tables; + struct ati_page_map *entry; int retval = 0; int i; - tables = kzalloc((nr_tables + 1) * sizeof(ati_page_map *),GFP_KERNEL); + tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL); if (tables == NULL) return -ENOMEM; for (i = 0; i < nr_tables; i++) { - entry = kzalloc(sizeof(ati_page_map), GFP_KERNEL); + entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL); if (entry == NULL) { while (i>0) { kfree (tables[i-1]); @@ -340,7 +340,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start, static int ati_create_gatt_table(struct agp_bridge_data *bridge) { struct aper_size_info_lvl2 *value; - ati_page_map page_dir; + struct ati_page_map page_dir; unsigned long addr; int retval; u32 temp; @@ -400,7 +400,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) static int ati_free_gatt_table(struct agp_bridge_data *bridge) { - ati_page_map page_dir; + struct ati_page_map page_dir; page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; -- cgit v1.2.3 From 7707ea3b784195315366e6e4b5c73ca6933ff9b0 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 28 Jan 2007 17:50:17 -0500 Subject: [AGPGART] Remove pointless assignment. No point in clearing local pointers then returning. Also fix up some CodingStyle nits. Signed-off-by: Dave Jones --- drivers/char/agp/ati-agp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 0994d3534447..9987dc2e0c3f 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -124,18 +124,18 @@ static int ati_create_gatt_pages(int nr_tables) for (i = 0; i < nr_tables; i++) { entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL); if (entry == NULL) { - while (i>0) { - kfree (tables[i-1]); + while (i > 0) { + kfree(tables[i-1]); i--; } - kfree (tables); - tables = NULL; + kfree(tables); retval = -ENOMEM; break; } tables[i] = entry; retval = ati_create_page_map(entry); - if (retval != 0) break; + if (retval != 0) + break; } ati_generic_private.num_tables = nr_tables; ati_generic_private.gatt_pages = tables; -- cgit v1.2.3 From 43ed41f648554c9fecaf7597d25e05da63ec7290 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 28 Jan 2007 17:58:33 -0500 Subject: [AGPGART] Add new IDs to VIA AGP. Culled from the VIA codedrop. Also fixes up one ID used in amd64-agp to use the VIA part number instead of the board name in its ID. Signed-off-by: Dave Jones --- drivers/char/agp/amd64-agp.c | 2 +- drivers/char/agp/via-agp.c | 21 +++++++++++++++++++-- include/linux/pci_ids.h | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 979300405c0e..93d2209fee4c 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -655,7 +655,7 @@ static struct pci_device_id agp_amd64_pci_table[] = { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_K8M890CE, + .device = PCI_DEVICE_ID_VIA_VT3336, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index c149ac9ce9a7..2ded7a280d7f 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c @@ -380,9 +380,23 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata = /* P4M800CE */ { .device_id = PCI_DEVICE_ID_VIA_P4M800CE, - .chipset_name = "P4M800CE", + .chipset_name = "VT3314", + }, + /* CX700 */ + { + .device_id = PCI_DEVICE_ID_VIA_CX700, + .chipset_name = "CX700", + }, + /* VT3336 */ + { + .device_id = PCI_DEVICE_ID_VIA_VT3336, + .chipset_name = "VT3336", + }, + /* P4M890 */ + { + .device_id = PCI_DEVICE_ID_VIA_P4M890, + .chipset_name = "P4M890", }, - { }, /* dummy final entry, always present */ }; @@ -524,6 +538,9 @@ static const struct pci_device_id agp_via_pci_table[] = { ID(PCI_DEVICE_ID_VIA_83_87XX_1), ID(PCI_DEVICE_ID_VIA_3296_0), ID(PCI_DEVICE_ID_VIA_P4M800CE), + ID(PCI_DEVICE_ID_VIA_CX700), + ID(PCI_DEVICE_ID_VIA_VT3336), + ID(PCI_DEVICE_ID_VIA_P4M890), { } }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 5c87cd8a56fd..083ad66e6528 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1273,7 +1273,8 @@ #define PCI_DEVICE_ID_VIA_3296_0 0x0296 #define PCI_DEVICE_ID_VIA_8363_0 0x0305 #define PCI_DEVICE_ID_VIA_P4M800CE 0x0314 -#define PCI_DEVICE_ID_VIA_K8M890CE 0x0336 +#define PCI_DEVICE_ID_VIA_P4M890 0x0327 +#define PCI_DEVICE_ID_VIA_VT3336 0x0336 #define PCI_DEVICE_ID_VIA_8371_0 0x0391 #define PCI_DEVICE_ID_VIA_8501_0 0x0501 #define PCI_DEVICE_ID_VIA_82C561 0x0561 -- cgit v1.2.3 From 41c57a87183a7c458d86f78966d69d4bf18ea0b7 Mon Sep 17 00:00:00 2001 From: David Barksdale Date: Tue, 30 Jan 2007 14:36:25 -0800 Subject: [PATCH] IPMI: fix timeout list handling Fix a dangling pointer bug in ipmi_timeout_handler. A list of timedout messages is not re-initialized before reuse, causing the head of the list to point to freed memory. Signed-off-by: David Barksdale Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 4e4691a53890..53582b53da95 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -3649,8 +3649,6 @@ static void ipmi_timeout_handler(long timeout_period) unsigned long flags; int i; - INIT_LIST_HEAD(&timeouts); - rcu_read_lock(); list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { /* See if any waiting messages need to be processed. */ @@ -3671,6 +3669,7 @@ static void ipmi_timeout_handler(long timeout_period) /* Go through the seq table and find any messages that have timed out, putting them in the timeouts list. */ + INIT_LIST_HEAD(&timeouts); spin_lock_irqsave(&intf->seq_lock, flags); for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) check_msg_timeout(intf, &(intf->seq_table[i]), -- cgit v1.2.3 From d346cce308f7fc99c7ffdb62060ed404fa340a1c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 31 Jan 2007 23:48:17 -0800 Subject: [PATCH] sysrq: showBlockedTasks is sysrq-W Change SysRq showBlockedTasks from sysrq-X to sysrq-W and show that in the Help message. It was previously done via X, but X is already used for Xmon on ppc & powerpc platforms and this collision needs to be avoided. All callers of register_sysrq_key() are now marked in the sysrq op/key table. I didn't mark 'h' as Help because Help is just printed for any unknown key, such as '?'. Added some omitted sysrq key entries in the sysrq.txt file. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sysrq.txt | 66 ++++++++++++++++++++++++++----------------------- drivers/char/sysrq.c | 20 ++++++++------- 2 files changed, 46 insertions(+), 40 deletions(-) (limited to 'drivers/char') diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index e0188a23fd5e..61613166981b 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -1,6 +1,6 @@ Linux Magic System Request Key Hacks -Documentation for sysrq.c version 1.15 -Last update: $Date: 2001/01/28 10:15:59 $ +Documentation for sysrq.c +Last update: 2007-JAN-06 * What is the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -35,7 +35,7 @@ You can set the value in the file by the following command: Note that the value of /proc/sys/kernel/sysrq influences only the invocation via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always -allowed. +allowed (by a user with admin privileges). * How do I use the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -58,7 +58,7 @@ On PowerPC - Press 'ALT - Print Screen (or F13) - , On other - If you know of the key combos for other architectures, please let me know so I can add them to this section. -On all - write a character to /proc/sysrq-trigger. eg: +On all - write a character to /proc/sysrq-trigger. e.g.: echo t > /proc/sysrq-trigger @@ -74,6 +74,8 @@ On all - write a character to /proc/sysrq-trigger. eg: 'c' - Will perform a kexec reboot in order to take a crashdump. +'d' - Shows all locks that are held. + 'o' - Will shut your system off (if configured and supported). 's' - Will attempt to sync all mounted filesystems. @@ -87,38 +89,43 @@ On all - write a character to /proc/sysrq-trigger. eg: 'm' - Will dump current memory info to your console. +'n' - Used to make RT tasks nice-able + 'v' - Dumps Voyager SMP processor info to your console. +'w' - Dumps tasks that are in uninterruptable (blocked) state. + +'x' - Used by xmon interface on ppc/powerpc platforms. + '0'-'9' - Sets the console log level, controlling which kernel messages will be printed to your console. ('0', for example would make it so that only emergency messages like PANICs or OOPSes would make it to your console.) -'f' - Will call oom_kill to kill a memory hog process +'f' - Will call oom_kill to kill a memory hog process. 'e' - Send a SIGTERM to all processes, except for init. -'i' - Send a SIGKILL to all processes, except for init. +'g' - Used by kgdb on ppc platforms. -'l' - Send a SIGKILL to all processes, INCLUDING init. (Your system - will be non-functional after this.) +'i' - Send a SIGKILL to all processes, except for init. -'h' - Will display help ( actually any other key than those listed +'h' - Will display help (actually any other key than those listed above will display help. but 'h' is easy to remember :-) * Okay, so what can I use them for? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Well, un'R'aw is very handy when your X server or a svgalib program crashes. -sa'K' (Secure Access Key) is useful when you want to be sure there are no -trojan program is running at console and which could grab your password -when you would try to login. It will kill all programs on given console -and thus letting you make sure that the login prompt you see is actually +sa'K' (Secure Access Key) is useful when you want to be sure there is no +trojan program running at console which could grab your password +when you would try to login. It will kill all programs on given console, +thus letting you make sure that the login prompt you see is actually the one from init, not some trojan program. IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT IMPORTANT: c2 compliant system, and it should not be mistaken as :IMPORTANT IMPORTANT: such. :IMPORTANT - It seems other find it useful as (System Attention Key) which is + It seems others find it useful as (System Attention Key) which is useful when you want to exit a program that will not let you switch consoles. (For example, X or a svgalib program.) @@ -139,8 +146,8 @@ OK or Done message...) Again, the unmount (remount read-only) hasn't taken place until you see the "OK" and "Done" message appear on the screen. -The loglevel'0'-'9' is useful when your console is being flooded with -kernel messages you do not want to see. Setting '0' will prevent all but +The loglevels '0'-'9' are useful when your console is being flooded with +kernel messages you do not want to see. Selecting '0' will prevent all but the most urgent kernel messages from reaching your console. (They will still be logged if syslogd/klogd are alive, though.) @@ -152,7 +159,7 @@ processes. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ That happens to me, also. I've found that tapping shift, alt, and control on both sides of the keyboard, and hitting an invalid sysrq sequence again -will fix the problem. (ie, something like alt-sysrq-z). Switching to another +will fix the problem. (i.e., something like alt-sysrq-z). Switching to another virtual console (ALT+Fn) and then back again should also help. * I hit SysRq, but nothing seems to happen, what's wrong? @@ -174,11 +181,11 @@ handler function you will use, B) a help_msg string, that will print when SysRQ prints help, and C) an action_msg string, that will print right before your handler is called. Your handler must conform to the prototype in 'sysrq.h'. -After the sysrq_key_op is created, you can call the macro -register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in -sysrq.h, this will register the operation pointed to by 'op_p' at table -key 'key', if that slot in the table is blank. At module unload time, you must -call the macro unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which +After the sysrq_key_op is created, you can call the kernel function +register_sysrq_key(int key, struct sysrq_key_op *op_p); this will +register the operation pointed to by 'op_p' at table key 'key', +if that slot in the table is blank. At module unload time, you must call +the function unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which will remove the key op pointed to by 'op_p' from the key 'key', if and only if it is currently registered in that slot. This is in case the slot has been overwritten since you registered it. @@ -186,15 +193,12 @@ overwritten since you registered it. The Magic SysRQ system works by registering key operations against a key op lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has a number of operations registered into it at compile time, but is mutable, -and 4 functions are exported for interface to it: __sysrq_lock_table, -__sysrq_unlock_table, __sysrq_get_key_op, and __sysrq_put_key_op. The -functions __sysrq_swap_key_ops and __sysrq_swap_key_ops_nolock are defined -in the header itself, and the REGISTER and UNREGISTER macros are built from -these. More complex (and dangerous!) manipulations of the table are possible -using these functions, but you must be careful to always lock the table before -you read or write from it, and to unlock it again when you are done. (And of -course, to never ever leave an invalid pointer in the table). Null pointers in -the table are always safe :) +and 2 functions are exported for interface to it: + register_sysrq_key and unregister_sysrq_key. +Of course, never ever leave an invalid pointer in the table. I.e., when +your module that called register_sysrq_key() exits, it must call +unregister_sysrq_key() to clean up the sysrq key table entry that it used. +Null pointers in the table are always safe. :) If for some reason you feel the need to call the handle_sysrq function from within a function called by handle_sysrq, you must be aware that you are in diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 13935235e066..7fd3cd5ddf21 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -215,7 +215,7 @@ static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty) } static struct sysrq_key_op sysrq_showstate_blocked_op = { .handler = sysrq_handle_showstate_blocked, - .help_msg = "showBlockedTasks", + .help_msg = "shoW-blocked-tasks", .action_msg = "Show Blocked State", .enable_mask = SYSRQ_ENABLE_DUMP, }; @@ -315,15 +315,16 @@ static struct sysrq_key_op *sysrq_key_table[36] = { &sysrq_loglevel_op, /* 9 */ /* - * Don't use for system provided sysrqs, it is handled specially on - * sparc and will never arrive + * a: Don't use for system provided sysrqs, it is handled specially on + * sparc and will never arrive. */ NULL, /* a */ &sysrq_reboot_op, /* b */ - &sysrq_crashdump_op, /* c */ + &sysrq_crashdump_op, /* c & ibm_emac driver debug */ &sysrq_showlocks_op, /* d */ &sysrq_term_op, /* e */ &sysrq_moom_op, /* f */ + /* g: May be registered by ppc for kgdb */ NULL, /* g */ NULL, /* h */ &sysrq_kill_op, /* i */ @@ -332,18 +333,19 @@ static struct sysrq_key_op *sysrq_key_table[36] = { NULL, /* l */ &sysrq_showmem_op, /* m */ &sysrq_unrt_op, /* n */ - /* This will often be registered as 'Off' at init time */ + /* o: This will often be registered as 'Off' at init time */ NULL, /* o */ &sysrq_showregs_op, /* p */ NULL, /* q */ - &sysrq_unraw_op, /* r */ + &sysrq_unraw_op, /* r */ &sysrq_sync_op, /* s */ &sysrq_showstate_op, /* t */ &sysrq_mountro_op, /* u */ - /* May be assigned at init time by SMP VOYAGER */ + /* v: May be registered at init time by SMP VOYAGER */ NULL, /* v */ - NULL, /* w */ - &sysrq_showstate_blocked_op, /* x */ + &sysrq_showstate_blocked_op, /* w */ + /* x: May be registered on ppc/powerpc for xmon */ + NULL, /* x */ NULL, /* y */ NULL /* z */ }; -- cgit v1.2.3