From: Greg Kroah-Hartman Date: Mon, 29 Jun 2009 19:02:59 +0000 (-0700) Subject: more .30 patches X-Git-Tag: v2.6.27.26~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=793c699bcce265b7450bcfa4ef18980575e04372;p=thirdparty%2Fkernel%2Fstable-queue.git more .30 patches --- diff --git a/queue-2.6.30/char-moxa-prevent-opening-unavailable-ports.patch b/queue-2.6.30/char-moxa-prevent-opening-unavailable-ports.patch new file mode 100644 index 00000000000..dcc25bf2e2b --- /dev/null +++ b/queue-2.6.30/char-moxa-prevent-opening-unavailable-ports.patch @@ -0,0 +1,51 @@ +From a90b037583d5f1ae3e54e9c687c79df82d1d34a4 Mon Sep 17 00:00:00 2001 +From: Dirk Eibach +Date: Thu, 18 Jun 2009 16:49:15 -0700 +Subject: char: moxa, prevent opening unavailable ports + +From: Dirk Eibach + +commit a90b037583d5f1ae3e54e9c687c79df82d1d34a4 upstream. + +In moxa.c there are 32 minor numbers reserved for each device. The number +of ports actually available per device is stored in +moxa_board_conf->numPorts. This number is not considered in moxa_open(). +Opening a port that is not available results in a kernel oops. This patch +adds a test to moxa_open() that prevents opening unavailable ports. + +[akpm@linux-foundation.org: avoid multiple returns] +Signed-off-by: Dirk Eibach +Signed-off-by: Jiri Slaby +Cc: Alan Cox +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/moxa.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/char/moxa.c ++++ b/drivers/char/moxa.c +@@ -1184,6 +1184,11 @@ static int moxa_open(struct tty_struct * + return -ENODEV; + } + ++ if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) { ++ retval = -ENODEV; ++ goto out_unlock; ++ } ++ + ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; + ch->port.count++; + tty->driver_data = ch; +@@ -1208,8 +1213,8 @@ static int moxa_open(struct tty_struct * + moxa_close_port(tty); + } else + ch->port.flags |= ASYNC_NORMAL_ACTIVE; ++out_unlock: + mutex_unlock(&moxa_openlock); +- + return retval; + } + diff --git a/queue-2.6.30/dma-debug-change-hash_bucket_find-from-first-fit-to-best-fit.patch b/queue-2.6.30/dma-debug-change-hash_bucket_find-from-first-fit-to-best-fit.patch new file mode 100644 index 00000000000..be9004bd5c7 --- /dev/null +++ b/queue-2.6.30/dma-debug-change-hash_bucket_find-from-first-fit-to-best-fit.patch @@ -0,0 +1,93 @@ +From 7caf6a49bb17d0377210693af5737563b31aa5ee Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Fri, 5 Jun 2009 12:01:35 +0200 +Subject: dma-debug: change hash_bucket_find from first-fit to best-fit + +From: Joerg Roedel + +commit 7caf6a49bb17d0377210693af5737563b31aa5ee upstream. + +Some device drivers map the same physical address multiple times to a +dma address. Without an IOMMU this results in the same dma address being +put into the dma-debug hash multiple times. With a first-fit match in +hash_bucket_find() this function may return the wrong dma_debug_entry. + +This can result in false positive warnings. This patch fixes it by +changing the first-fit behavior of hash_bucket_find() into a best-fit +algorithm. + +Reported-by: Torsten Kaiser +Reported-by: FUJITA Tomonori +Signed-off-by: Joerg Roedel +Cc: lethal@linux-sh.org +Cc: just.for.lkml@googlemail.com +Cc: hancockrwd@gmail.com +Cc: jens.axboe@oracle.com +Cc: bharrosh@panasas.com +Cc: FUJITA Tomonori +Cc: Linus Torvalds +LKML-Reference: <20090605104132.GE24836@amd.com> +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + lib/dma-debug.c | 43 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 39 insertions(+), 4 deletions(-) + +--- a/lib/dma-debug.c ++++ b/lib/dma-debug.c +@@ -185,15 +185,50 @@ static void put_hash_bucket(struct hash_ + static struct dma_debug_entry *hash_bucket_find(struct hash_bucket *bucket, + struct dma_debug_entry *ref) + { +- struct dma_debug_entry *entry; ++ struct dma_debug_entry *entry, *ret = NULL; ++ int matches = 0, match_lvl, last_lvl = 0; + + list_for_each_entry(entry, &bucket->list, list) { +- if ((entry->dev_addr == ref->dev_addr) && +- (entry->dev == ref->dev)) ++ if ((entry->dev_addr != ref->dev_addr) || ++ (entry->dev != ref->dev)) ++ continue; ++ ++ /* ++ * Some drivers map the same physical address multiple ++ * times. Without a hardware IOMMU this results in the ++ * same device addresses being put into the dma-debug ++ * hash multiple times too. This can result in false ++ * positives being reported. Therfore we implement a ++ * best-fit algorithm here which returns the entry from ++ * the hash which fits best to the reference value ++ * instead of the first-fit. ++ */ ++ matches += 1; ++ match_lvl = 0; ++ entry->size == ref->size ? ++match_lvl : match_lvl; ++ entry->type == ref->type ? ++match_lvl : match_lvl; ++ entry->direction == ref->direction ? ++match_lvl : match_lvl; ++ ++ if (match_lvl == 3) { ++ /* perfect-fit - return the result */ + return entry; ++ } else if (match_lvl > last_lvl) { ++ /* ++ * We found an entry that fits better then the ++ * previous one ++ */ ++ last_lvl = match_lvl; ++ ret = entry; ++ } + } + +- return NULL; ++ /* ++ * If we have multiple matches but no perfect-fit, just return ++ * NULL. ++ */ ++ ret = (matches == 1) ? ret : NULL; ++ ++ return ret; + } + + /* diff --git a/queue-2.6.30/epca-fix-test_bit-parameters.patch b/queue-2.6.30/epca-fix-test_bit-parameters.patch new file mode 100644 index 00000000000..d2cc058cdf1 --- /dev/null +++ b/queue-2.6.30/epca-fix-test_bit-parameters.patch @@ -0,0 +1,54 @@ +From c3301a5c04800bcf8afc8a815bf9e570a4e25a08 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Thu, 11 Jun 2009 12:41:05 +0100 +Subject: epca: fix test_bit parameters + +From: Jiri Slaby + +commit c3301a5c04800bcf8afc8a815bf9e570a4e25a08 upstream. + +Switch from ASYNC_* to ASYNCB_*, because test_bit expects +bit number, not mask. + +Signed-off-by: Jiri Slaby +Signed-off-by: Alan Cox +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/epca.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/char/epca.c ++++ b/drivers/char/epca.c +@@ -1518,7 +1518,7 @@ static void doevent(int crd) + if (event & MODEMCHG_IND) { + /* A modem signal change has been indicated */ + ch->imodem = mstat; +- if (test_bit(ASYNC_CHECK_CD, &ch->port.flags)) { ++ if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) { + /* We are now receiving dcd */ + if (mstat & ch->dcd) + wake_up_interruptible(&ch->port.open_wait); +@@ -1765,9 +1765,9 @@ static void epcaparam(struct tty_struct + * that the driver will wait on carrier detect. + */ + if (ts->c_cflag & CLOCAL) +- clear_bit(ASYNC_CHECK_CD, &ch->port.flags); ++ clear_bit(ASYNCB_CHECK_CD, &ch->port.flags); + else +- set_bit(ASYNC_CHECK_CD, &ch->port.flags); ++ set_bit(ASYNCB_CHECK_CD, &ch->port.flags); + mval = ch->m_dtr | ch->m_rts; + } /* End CBAUD not detected */ + iflag = termios2digi_i(ch, ts->c_iflag); +@@ -2244,7 +2244,8 @@ static void do_softint(struct work_struc + if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { + tty_hangup(tty); + wake_up_interruptible(&ch->port.open_wait); +- clear_bit(ASYNC_NORMAL_ACTIVE, &ch->port.flags); ++ clear_bit(ASYNCB_NORMAL_ACTIVE, ++ &ch->port.flags); + } + } + tty_kref_put(tty); diff --git a/queue-2.6.30/rocket-fix-test_bit-parameters.patch b/queue-2.6.30/rocket-fix-test_bit-parameters.patch new file mode 100644 index 00000000000..eceff9e248e --- /dev/null +++ b/queue-2.6.30/rocket-fix-test_bit-parameters.patch @@ -0,0 +1,50 @@ +From a391ad0f09014856bbc4eeea309593eba977b3b0 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Thu, 11 Jun 2009 12:40:17 +0100 +Subject: rocket: fix test_bit parameters + +From: Jiri Slaby + +commit a391ad0f09014856bbc4eeea309593eba977b3b0 upstream. + +Switch from ASYNC_* to ASYNCB_*, because {test,set}_bit expect +bit number, not mask. + +Signed-off-by: Jiri Slaby +Signed-off-by: Alan Cox +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/rocket.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/char/rocket.c ++++ b/drivers/char/rocket.c +@@ -934,7 +934,7 @@ static int rp_open(struct tty_struct *tt + /* + * Info->count is now 1; so it's safe to sleep now. + */ +- if (!test_bit(ASYNC_INITIALIZED, &port->flags)) { ++ if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { + cp = &info->channel; + sSetRxTrigger(cp, TRIG_1); + if (sGetChanStatus(cp) & CD_ACT) +@@ -958,7 +958,7 @@ static int rp_open(struct tty_struct *tt + sEnRxFIFO(cp); + sEnTransmit(cp); + +- set_bit(ASYNC_INITIALIZED, &info->port.flags); ++ set_bit(ASYNCB_INITIALIZED, &info->port.flags); + + /* + * Set up the tty->alt_speed kludge +@@ -1641,7 +1641,7 @@ static int rp_write(struct tty_struct *t + /* Write remaining data into the port's xmit_buf */ + while (1) { + /* Hung up ? */ +- if (!test_bit(ASYNC_NORMAL_ACTIVE, &info->port.flags)) ++ if (!test_bit(ASYNCB_NORMAL_ACTIVE, &info->port.flags)) + goto end; + c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); + c = min(c, XMIT_BUF_SIZE - info->xmit_head); diff --git a/queue-2.6.30/serial-refactor-async_-flags.patch b/queue-2.6.30/serial-refactor-async_-flags.patch new file mode 100644 index 00000000000..c460541ac52 --- /dev/null +++ b/queue-2.6.30/serial-refactor-async_-flags.patch @@ -0,0 +1,166 @@ +From 70beaed22cbe12979e55d99b370e147e2e168562 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Thu, 11 Jun 2009 12:39:12 +0100 +Subject: serial: refactor ASYNC_ flags + +From: Jiri Slaby + +commit 70beaed22cbe12979e55d99b370e147e2e168562 upstream. + +Define ASYNCB_* flags which are bit numbers of the ASYNC_* flags. +This is useful for {test,set,clear}_bit. + +Also convert each ASYNC_% to be (1 << ASYNCB_%) and define masks +with the macros, not constants. + +Tested with: +#include "PATH_TO_KERNEL/include/linux/serial.h" +static struct { + unsigned int new, old; +} as[] = { + { ASYNC_HUP_NOTIFY, 0x0001 }, + { ASYNC_FOURPORT, 0x0002 }, +... + { ASYNC_BOOT_ONLYMCA, 0x00400000 }, + { ASYNC_INTERNAL_FLAGS, 0xFFC00000 } +}; +... + for (a = 0; a < ARRAY_SIZE(as); a++) + if (as[a].old != as[a].new) + printf("%.8x != %.8x\n", as[a].old, as[a].new); + +Signed-off-by: Jiri Slaby +Signed-off-by: Alan Cox +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/serial.h | 116 +++++++++++++++++++++++++++++-------------------- + 1 file changed, 69 insertions(+), 47 deletions(-) + +--- a/include/linux/serial.h ++++ b/include/linux/serial.h +@@ -96,54 +96,76 @@ struct serial_uart_config { + + /* + * Definitions for async_struct (and serial_struct) flags field ++ * ++ * Define ASYNCB_* for convenient use with {test,set,clear}_bit. + */ +-#define ASYNC_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes +- on the callout port */ +-#define ASYNC_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ +-#define ASYNC_SAK 0x0004 /* Secure Attention Key (Orange book) */ +-#define ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ +- +-#define ASYNC_SPD_MASK 0x1030 +-#define ASYNC_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ +- +-#define ASYNC_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ +-#define ASYNC_SPD_CUST 0x0030 /* Use user-specified divisor */ +- +-#define ASYNC_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ +-#define ASYNC_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ +-#define ASYNC_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +-#define ASYNC_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ +-#define ASYNC_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ +- +-#define ASYNC_HARDPPS_CD 0x0800 /* Call hardpps when CD goes high */ +- +-#define ASYNC_SPD_SHI 0x1000 /* Use 230400 instead of 38400 bps */ +-#define ASYNC_SPD_WARP 0x1010 /* Use 460800 instead of 38400 bps */ +- +-#define ASYNC_LOW_LATENCY 0x2000 /* Request low latency behaviour */ +- +-#define ASYNC_BUGGY_UART 0x4000 /* This is a buggy UART, skip some safety +- * checks. Note: can be dangerous! */ +- +-#define ASYNC_AUTOPROBE 0x8000 /* Port was autoprobed by PCI or PNP code */ +- +-#define ASYNC_FLAGS 0x7FFF /* Possible legal async flags */ +-#define ASYNC_USR_MASK 0x3430 /* Legal flags that non-privileged +- * users can set or reset */ +- +-/* Internal flags used only by kernel/chr_drv/serial.c */ +-#define ASYNC_INITIALIZED 0x80000000 /* Serial port was initialized */ +-#define ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +-#define ASYNC_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +-#define ASYNC_CLOSING 0x08000000 /* Serial port is closing */ +-#define ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ +-#define ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */ +-#define ASYNC_SHARE_IRQ 0x01000000 /* for multifunction cards +- --- no longer used */ +-#define ASYNC_CONS_FLOW 0x00800000 /* flow control for console */ +- +-#define ASYNC_BOOT_ONLYMCA 0x00400000 /* Probe only if MCA bus */ +-#define ASYNC_INTERNAL_FLAGS 0xFFC00000 /* Internal flags */ ++#define ASYNCB_HUP_NOTIFY 0 /* Notify getty on hangups and closes ++ * on the callout port */ ++#define ASYNCB_FOURPORT 1 /* Set OU1, OUT2 per AST Fourport settings */ ++#define ASYNCB_SAK 2 /* Secure Attention Key (Orange book) */ ++#define ASYNCB_SPLIT_TERMIOS 3 /* Separate termios for dialin/callout */ ++#define ASYNCB_SPD_HI 4 /* Use 56000 instead of 38400 bps */ ++#define ASYNCB_SPD_VHI 5 /* Use 115200 instead of 38400 bps */ ++#define ASYNCB_SKIP_TEST 6 /* Skip UART test during autoconfiguration */ ++#define ASYNCB_AUTO_IRQ 7 /* Do automatic IRQ during ++ * autoconfiguration */ ++#define ASYNCB_SESSION_LOCKOUT 8 /* Lock out cua opens based on session */ ++#define ASYNCB_PGRP_LOCKOUT 9 /* Lock out cua opens based on pgrp */ ++#define ASYNCB_CALLOUT_NOHUP 10 /* Don't do hangups for cua device */ ++#define ASYNCB_HARDPPS_CD 11 /* Call hardpps when CD goes high */ ++#define ASYNCB_SPD_SHI 12 /* Use 230400 instead of 38400 bps */ ++#define ASYNCB_LOW_LATENCY 13 /* Request low latency behaviour */ ++#define ASYNCB_BUGGY_UART 14 /* This is a buggy UART, skip some safety ++ * checks. Note: can be dangerous! */ ++#define ASYNCB_AUTOPROBE 15 /* Port was autoprobed by PCI or PNP code */ ++#define ASYNCB_LAST_USER 15 ++ ++/* Internal flags used only by kernel */ ++#define ASYNCB_INITIALIZED 31 /* Serial port was initialized */ ++#define ASYNCB_NORMAL_ACTIVE 29 /* Normal device is active */ ++#define ASYNCB_BOOT_AUTOCONF 28 /* Autoconfigure port on bootup */ ++#define ASYNCB_CLOSING 27 /* Serial port is closing */ ++#define ASYNCB_CTS_FLOW 26 /* Do CTS flow control */ ++#define ASYNCB_CHECK_CD 25 /* i.e., CLOCAL */ ++#define ASYNCB_SHARE_IRQ 24 /* for multifunction cards, no longer used */ ++#define ASYNCB_CONS_FLOW 23 /* flow control for console */ ++#define ASYNCB_BOOT_ONLYMCA 22 /* Probe only if MCA bus */ ++#define ASYNCB_FIRST_KERNEL 22 ++ ++#define ASYNC_HUP_NOTIFY (1U << ASYNCB_HUP_NOTIFY) ++#define ASYNC_FOURPORT (1U << ASYNCB_FOURPORT) ++#define ASYNC_SAK (1U << ASYNCB_SAK) ++#define ASYNC_SPLIT_TERMIOS (1U << ASYNCB_SPLIT_TERMIOS) ++#define ASYNC_SPD_HI (1U << ASYNCB_SPD_HI) ++#define ASYNC_SPD_VHI (1U << ASYNCB_SPD_VHI) ++#define ASYNC_SKIP_TEST (1U << ASYNCB_SKIP_TEST) ++#define ASYNC_AUTO_IRQ (1U << ASYNCB_AUTO_IRQ) ++#define ASYNC_SESSION_LOCKOUT (1U << ASYNCB_SESSION_LOCKOUT) ++#define ASYNC_PGRP_LOCKOUT (1U << ASYNCB_PGRP_LOCKOUT) ++#define ASYNC_CALLOUT_NOHUP (1U << ASYNCB_CALLOUT_NOHUP) ++#define ASYNC_HARDPPS_CD (1U << ASYNCB_HARDPPS_CD) ++#define ASYNC_SPD_SHI (1U << ASYNCB_SPD_SHI) ++#define ASYNC_LOW_LATENCY (1U << ASYNCB_LOW_LATENCY) ++#define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART) ++#define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE) ++ ++#define ASYNC_FLAGS ((1U << ASYNCB_LAST_USER) - 1) ++#define ASYNC_USR_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI| \ ++ ASYNC_CALLOUT_NOHUP|ASYNC_SPD_SHI|ASYNC_LOW_LATENCY) ++#define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI) ++#define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI) ++#define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI) ++ ++#define ASYNC_INITIALIZED (1U << ASYNCB_INITIALIZED) ++#define ASYNC_NORMAL_ACTIVE (1U << ASYNCB_NORMAL_ACTIVE) ++#define ASYNC_BOOT_AUTOCONF (1U << ASYNCB_BOOT_AUTOCONF) ++#define ASYNC_CLOSING (1U << ASYNCB_CLOSING) ++#define ASYNC_CTS_FLOW (1U << ASYNCB_CTS_FLOW) ++#define ASYNC_CHECK_CD (1U << ASYNCB_CHECK_CD) ++#define ASYNC_SHARE_IRQ (1U << ASYNCB_SHARE_IRQ) ++#define ASYNC_CONS_FLOW (1U << ASYNCB_CONS_FLOW) ++#define ASYNC_BOOT_ONLYMCA (1U << ASYNCB_BOOT_ONLYMCA) ++#define ASYNC_INTERNAL_FLAGS (~((1U << ASYNCB_FIRST_KERNEL) - 1)) + + /* + * Multiport serial configuration structure --- external structure diff --git a/queue-2.6.30/series b/queue-2.6.30/series index e00978286ce..185ea4d7586 100644 --- a/queue-2.6.30/series +++ b/queue-2.6.30/series @@ -20,3 +20,9 @@ tun-fix-unregister-race.patch via-velocity-fix-velocity-driver-unmapping-incorrect-size.patch x25-fix-sleep-from-timer-on-socket-destroy.patch bonding-fix-multiple-module-load-problem.patch +dma-debug-change-hash_bucket_find-from-first-fit-to-best-fit.patch +char-moxa-prevent-opening-unavailable-ports.patch +serial-refactor-async_-flags.patch +rocket-fix-test_bit-parameters.patch +epca-fix-test_bit-parameters.patch +x86-detect-use-of-extended-apic-id-for-amd-cpus.patch diff --git a/queue-2.6.30/x86-detect-use-of-extended-apic-id-for-amd-cpus.patch b/queue-2.6.30/x86-detect-use-of-extended-apic-id-for-amd-cpus.patch new file mode 100644 index 00000000000..8045f0b475b --- /dev/null +++ b/queue-2.6.30/x86-detect-use-of-extended-apic-id-for-amd-cpus.patch @@ -0,0 +1,100 @@ +From 42937e81a82b6bbc51a309c83da140b3a7ca5945 Mon Sep 17 00:00:00 2001 +From: Andreas Herrmann +Date: Mon, 8 Jun 2009 15:55:09 +0200 +Subject: x86: Detect use of extended APIC ID for AMD CPUs + +From: Andreas Herrmann + +commit 42937e81a82b6bbc51a309c83da140b3a7ca5945 upstream. + +Booting a 32-bit kernel on Magny-Cours results in the following panic: + + ... + Using APIC driver default + ... + Overriding APIC driver with bigsmp + ... + Getting VERSION: 80050010 + Getting VERSION: 80050010 + Getting ID: 10000000 + Getting ID: ef000000 + Getting LVT0: 700 + Getting LVT1: 10000 + Kernel panic - not syncing: Boot APIC ID in local APIC unexpected (16 vs 0) + Pid: 1, comm: swapper Not tainted 2.6.30-rcX #2 + Call Trace: + [] ? panic+0x38/0xd3 + [] ? native_smp_prepare_cpus+0x259/0x31f + [] ? kernel_init+0x3e/0x141 + [] ? kernel_init+0x0/0x141 + [] ? kernel_thread_helper+0x7/0x10 + +The reason is that default_get_apic_id handled extension of local APIC +ID field just in case of XAPIC. + +Thus for this AMD CPU, default_get_apic_id() returns 0 and +bigsmp_get_apic_id() returns 16 which leads to the respective kernel +panic. + +This patch introduces a Linux specific feature flag to indicate +support for extended APIC id (8 bits instead of 4 bits width) and sets +the flag on AMD CPUs if applicable. + +Signed-off-by: Andreas Herrmann +LKML-Reference: <20090608135509.GA12431@alberich.amd.com> +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/apic.h | 2 +- + arch/x86/include/asm/cpufeature.h | 1 + + arch/x86/kernel/cpu/amd.c | 10 ++++++++++ + 3 files changed, 12 insertions(+), 1 deletion(-) + +--- a/arch/x86/include/asm/apic.h ++++ b/arch/x86/include/asm/apic.h +@@ -410,7 +410,7 @@ static inline unsigned default_get_apic_ + { + unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); + +- if (APIC_XAPIC(ver)) ++ if (APIC_XAPIC(ver) || boot_cpu_has(X86_FEATURE_EXTD_APICID)) + return (x >> 24) & 0xFF; + else + return (x >> 24) & 0x0F; +--- a/arch/x86/include/asm/cpufeature.h ++++ b/arch/x86/include/asm/cpufeature.h +@@ -94,6 +94,7 @@ + #define X86_FEATURE_TSC_RELIABLE (3*32+23) /* TSC is known to be reliable */ + #define X86_FEATURE_NONSTOP_TSC (3*32+24) /* TSC does not stop in C states */ + #define X86_FEATURE_CLFLUSH_MONITOR (3*32+25) /* "" clflush reqd with monitor */ ++#define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */ + + /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ + #define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */ +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_X86_64 + # include +@@ -351,6 +352,15 @@ static void __cpuinit early_init_amd(str + (c->x86_model == 8 && c->x86_mask >= 8)) + set_cpu_cap(c, X86_FEATURE_K6_MTRR); + #endif ++#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI) ++ /* check CPU config space for extended APIC ID */ ++ if (c->x86 >= 0xf) { ++ unsigned int val; ++ val = read_pci_config(0, 24, 0, 0x68); ++ if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18))) ++ set_cpu_cap(c, X86_FEATURE_EXTD_APICID); ++ } ++#endif + } + + static void __cpuinit init_amd(struct cpuinfo_x86 *c)