Commit 1ca721cd authored by Len Brown's avatar Len Brown

Merge branches 'release', 'bugzilla-8570', 'bugzilla-9966', 'bugzilla-9998',...

Merge branches 'release', 'bugzilla-8570', 'bugzilla-9966', 'bugzilla-9998', 'bugzilla-10100', 'bugzilla-10132', 'bugzilla-10138' and 'bugzilla-10206' into release
...@@ -129,6 +129,7 @@ static struct acpi_ec { ...@@ -129,6 +129,7 @@ static struct acpi_ec {
struct mutex lock; struct mutex lock;
wait_queue_head_t wait; wait_queue_head_t wait;
struct list_head list; struct list_head list;
atomic_t irq_count;
u8 handlers_installed; u8 handlers_installed;
} *boot_ec, *first_ec; } *boot_ec, *first_ec;
...@@ -181,6 +182,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) ...@@ -181,6 +182,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
{ {
int ret = 0; int ret = 0;
atomic_set(&ec->irq_count, 0);
if (unlikely(event == ACPI_EC_EVENT_OBF_1 && if (unlikely(event == ACPI_EC_EVENT_OBF_1 &&
test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags)))
force_poll = 1; force_poll = 1;
...@@ -227,6 +230,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) ...@@ -227,6 +230,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
while (time_before(jiffies, delay)) { while (time_before(jiffies, delay)) {
if (acpi_ec_check_status(ec, event)) if (acpi_ec_check_status(ec, event))
goto end; goto end;
msleep(5);
} }
} }
pr_err(PREFIX "acpi_ec_wait timeout," pr_err(PREFIX "acpi_ec_wait timeout,"
...@@ -529,6 +533,13 @@ static u32 acpi_ec_gpe_handler(void *data) ...@@ -529,6 +533,13 @@ static u32 acpi_ec_gpe_handler(void *data)
struct acpi_ec *ec = data; struct acpi_ec *ec = data;
pr_debug(PREFIX "~~~> interrupt\n"); pr_debug(PREFIX "~~~> interrupt\n");
atomic_inc(&ec->irq_count);
if (atomic_read(&ec->irq_count) > 5) {
pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR);
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
return ACPI_INTERRUPT_HANDLED;
}
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
wake_up(&ec->wait); wake_up(&ec->wait);
...@@ -943,11 +954,7 @@ int __init acpi_ec_ecdt_probe(void) ...@@ -943,11 +954,7 @@ int __init acpi_ec_ecdt_probe(void)
boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->data_addr = ecdt_ptr->data.address;
boot_ec->gpe = ecdt_ptr->gpe; boot_ec->gpe = ecdt_ptr->gpe;
if (ACPI_FAILURE(acpi_get_handle(NULL, ecdt_ptr->id,
&boot_ec->handle))) {
pr_info("Failed to locate handle for boot EC\n");
boot_ec->handle = ACPI_ROOT_OBJECT; boot_ec->handle = ACPI_ROOT_OBJECT;
}
} else { } else {
/* This workaround is needed only on some broken machines, /* This workaround is needed only on some broken machines,
* which require early EC, but fail to provide ECDT */ * which require early EC, but fail to provide ECDT */
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
*/ */
#include <linux/dmi.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -76,6 +77,101 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment, ...@@ -76,6 +77,101 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
return NULL; return NULL;
} }
/* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
static struct dmi_system_id medion_md9580[] = {
{
.ident = "Medion MD9580-F laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
DMI_MATCH(DMI_PRODUCT_NAME, "A555"),
},
},
{ }
};
/* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */
static struct dmi_system_id dell_optiplex[] = {
{
.ident = "Dell Optiplex GX1",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX1 600S+"),
},
},
{ }
};
/* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */
static struct dmi_system_id hp_t5710[] = {
{
.ident = "HP t5710",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "hp t5000 series"),
DMI_MATCH(DMI_BOARD_NAME, "098Ch"),
},
},
{ }
};
struct prt_quirk {
struct dmi_system_id *system;
unsigned int segment;
unsigned int bus;
unsigned int device;
unsigned char pin;
char *source; /* according to BIOS */
char *actual_source;
};
/*
* These systems have incorrect _PRT entries. The BIOS claims the PCI
* interrupt at the listed segment/bus/device/pin is connected to the first
* link device, but it is actually connected to the second.
*/
static struct prt_quirk prt_quirks[] = {
{ medion_md9580, 0, 0, 9, 'A',
"\\_SB_.PCI0.ISA.LNKA",
"\\_SB_.PCI0.ISA.LNKB"},
{ dell_optiplex, 0, 0, 0xd, 'A',
"\\_SB_.LNKB",
"\\_SB_.LNKA"},
{ hp_t5710, 0, 0, 1, 'A',
"\\_SB_.PCI0.LNK1",
"\\_SB_.PCI0.LNK3"},
};
static void
do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt)
{
int i;
struct prt_quirk *quirk;
for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) {
quirk = &prt_quirks[i];
/* All current quirks involve link devices, not GSIs */
if (!prt->source)
continue;
if (dmi_check_system(quirk->system) &&
entry->id.segment == quirk->segment &&
entry->id.bus == quirk->bus &&
entry->id.device == quirk->device &&
entry->pin + 'A' == quirk->pin &&
!strcmp(prt->source, quirk->source) &&
strlen(prt->source) >= strlen(quirk->actual_source)) {
printk(KERN_WARNING PREFIX "firmware reports "
"%04x:%02x:%02x[%c] connected to %s; "
"changing to %s\n",
entry->id.segment, entry->id.bus,
entry->id.device, 'A' + entry->pin,
prt->source, quirk->actual_source);
strcpy(prt->source, quirk->actual_source);
}
}
}
static int static int
acpi_pci_irq_add_entry(acpi_handle handle, acpi_pci_irq_add_entry(acpi_handle handle,
int segment, int bus, struct acpi_pci_routing_table *prt) int segment, int bus, struct acpi_pci_routing_table *prt)
...@@ -96,6 +192,8 @@ acpi_pci_irq_add_entry(acpi_handle handle, ...@@ -96,6 +192,8 @@ acpi_pci_irq_add_entry(acpi_handle handle,
entry->id.function = prt->address & 0xFFFF; entry->id.function = prt->address & 0xFFFF;
entry->pin = prt->pin; entry->pin = prt->pin;
do_prt_fixups(entry, prt);
/* /*
* Type 1: Dynamic * Type 1: Dynamic
* --------------- * ---------------
......
...@@ -840,17 +840,19 @@ static int is_processor_present(acpi_handle handle) ...@@ -840,17 +840,19 @@ static int is_processor_present(acpi_handle handle)
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
/*
* if a processor object does not have an _STA object,
* OSPM assumes that the processor is present.
*/
if (status == AE_NOT_FOUND)
return 1;
if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
return 1; return 1;
ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); /*
* _STA is mandatory for a processor that supports hot plug
*/
if (status == AE_NOT_FOUND)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Processor does not support hot plug\n"));
else
ACPI_EXCEPTION((AE_INFO, status,
"Processor Device is not present"));
return 0; return 0;
} }
......
...@@ -432,7 +432,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, ...@@ -432,7 +432,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
* element -- which is legal) * element -- which is legal)
*/ */
if (!internal_object) { if (!internal_object) {
*obj_length = 0; *obj_length = sizeof(union acpi_object);
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
......
...@@ -713,7 +713,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) ...@@ -713,7 +713,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
kfree(obj); kfree(obj);
if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ if (device->cap._BCL && device->cap._BCM && max_level > 0) {
int result; int result;
static int count = 0; static int count = 0;
char *name; char *name;
......
...@@ -447,7 +447,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free) ...@@ -447,7 +447,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
* of @bm->cur_zone_bm are updated. * of @bm->cur_zone_bm are updated.
*/ */
static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
void **addr, unsigned int *bit_nr) void **addr, unsigned int *bit_nr)
{ {
struct zone_bitmap *zone_bm; struct zone_bitmap *zone_bm;
...@@ -461,7 +461,8 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, ...@@ -461,7 +461,8 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) { while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) {
zone_bm = zone_bm->next; zone_bm = zone_bm->next;
BUG_ON(!zone_bm); if (!zone_bm)
return -EFAULT;
} }
bm->cur.zone_bm = zone_bm; bm->cur.zone_bm = zone_bm;
} }
...@@ -479,23 +480,40 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn, ...@@ -479,23 +480,40 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
pfn -= bb->start_pfn; pfn -= bb->start_pfn;
*bit_nr = pfn % BM_BITS_PER_CHUNK; *bit_nr = pfn % BM_BITS_PER_CHUNK;
*addr = bb->data + pfn / BM_BITS_PER_CHUNK; *addr = bb->data + pfn / BM_BITS_PER_CHUNK;
return 0;
} }
static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn) static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
{ {
void *addr; void *addr;
unsigned int bit; unsigned int bit;
int error;
memory_bm_find_bit(bm, pfn, &addr, &bit); error = memory_bm_find_bit(bm, pfn, &addr, &bit);
BUG_ON(error);
set_bit(bit, addr); set_bit(bit, addr);
} }
static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn)
{
void *addr;
unsigned int bit;
int error;
error = memory_bm_find_bit(bm, pfn, &addr, &bit);
if (!error)
set_bit(bit, addr);
return error;
}
static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
{ {
void *addr; void *addr;
unsigned int bit; unsigned int bit;
int error;
memory_bm_find_bit(bm, pfn, &addr, &bit); error = memory_bm_find_bit(bm, pfn, &addr, &bit);
BUG_ON(error);
clear_bit(bit, addr); clear_bit(bit, addr);
} }
...@@ -503,8 +521,10 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) ...@@ -503,8 +521,10 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
{ {
void *addr; void *addr;
unsigned int bit; unsigned int bit;
int error;
memory_bm_find_bit(bm, pfn, &addr, &bit); error = memory_bm_find_bit(bm, pfn, &addr, &bit);
BUG_ON(error);
return test_bit(bit, addr); return test_bit(bit, addr);
} }
...@@ -709,8 +729,15 @@ static void mark_nosave_pages(struct memory_bitmap *bm) ...@@ -709,8 +729,15 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
region->end_pfn << PAGE_SHIFT); region->end_pfn << PAGE_SHIFT);
for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++) for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
if (pfn_valid(pfn)) if (pfn_valid(pfn)) {
memory_bm_set_bit(bm, pfn); /*
* It is safe to ignore the result of
* mem_bm_set_bit_check() here, since we won't
* touch the PFNs for which the error is
* returned anyway.
*/
mem_bm_set_bit_check(bm, pfn);
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment