From fecfaa04378ed912b016bc8a314b2aaf55055807 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 4 May 2011 15:49:47 -0700 Subject: [PATCH] .38 patches --- ...sa-hda-fix-automute-for-gateway-nv79.patch | 48 +++++ ...a-fix-realtek-s-chained-fixup-checks.patch | 35 ++++ ...-fix-work-event-interrupt-task-races.patch | 84 ++++++++ ...tom-cards-with-hardcoded-edid-record.patch | 38 ++++ ...onfigrom-updates-in-quick-succession.patch | 110 ++++++++++ ...akes-a-number-of-elements-not-an-end.patch | 119 +++++++++++ ...arrays-allow-zero-length-flex-arrays.patch | 55 +++++ ...2c-parport-fix-adapter-list-handling.patch | 100 +++++++++ ...nditional-locking-in-change_protocol.patch | 194 ++++++++++++++++++ ...gn-fix-received-ba-when-not-expected.patch | 68 ++++++ .../iwlwifi-fix-skb-usage-after-free.patch | 55 +++++ ...rescan-and-clock-gate-work-instances.patch | 82 ++++++++ ...heck-mrq-cmd-in-sdhci_tasklet_finish.patch | 39 ++++ ...eck-mrq-null-in-sdhci_tasklet_finish.patch | 39 ++++ ...x-error-case-in-sdhci_pci_probe_slot.patch | 35 ++++ ...t-heap-overflows-and-unchecked-reads.patch | 86 ++++++++ ...pmcraid-reject-negative-request-size.patch | 53 +++++ ...stricter-guards-on-queue-dead-checks.patch | 61 ++++++ ...-hda-fix-pin-config-of-gigabyte-mobo.patch | 104 ++++++++++ ...nting-in-scsi_dh_activate-error-path.patch | 57 +++++ queue-2.6.38/series | 27 +++ ...-free-write-buffers-when-in-r-o-mode.patch | 123 +++++++++++ ...al-heads-to-the-latest-bud-in-replay.patch | 116 +++++++++++ ...sion-in-usbip-by-setting-has_tt-flag.patch | 34 +++ ...e-huawei-modems-with-cdc-ether-ports.patch | 59 ++++++ ...s-supply-a-zeroed-struct-v4l2_subdev.patch | 124 +++++++++++ ...adlock-in-worker_maybe_bind_and_lock.patch | 54 +++++ ...-400-affecting-k8-rev.a-e-processors.patch | 44 ++++ 28 files changed, 2043 insertions(+) create mode 100644 queue-2.6.38/alsa-hda-fix-automute-for-gateway-nv79.patch create mode 100644 queue-2.6.38/alsa-hda-fix-realtek-s-chained-fixup-checks.patch create mode 100644 queue-2.6.38/atl1c-fix-work-event-interrupt-task-races.patch create mode 100644 queue-2.6.38/drm-radeon-fix-regression-on-atom-cards-with-hardcoded-edid-record.patch create mode 100644 queue-2.6.38/firewire-fix-for-broken-configrom-updates-in-quick-succession.patch create mode 100644 queue-2.6.38/flex_array-flex_array_prealloc-takes-a-number-of-elements-not-an-end.patch create mode 100644 queue-2.6.38/flex_arrays-allow-zero-length-flex-arrays.patch create mode 100644 queue-2.6.38/i2c-parport-fix-adapter-list-handling.patch create mode 100644 queue-2.6.38/imon-add-conditional-locking-in-change_protocol.patch create mode 100644 queue-2.6.38/iwlagn-fix-received-ba-when-not-expected.patch create mode 100644 queue-2.6.38/iwlwifi-fix-skb-usage-after-free.patch create mode 100644 queue-2.6.38/mmc-fix-a-race-between-card-detect-rescan-and-clock-gate-work-instances.patch create mode 100644 queue-2.6.38/mmc-sdhci-check-mrq-cmd-in-sdhci_tasklet_finish.patch create mode 100644 queue-2.6.38/mmc-sdhci-check-mrq-null-in-sdhci_tasklet_finish.patch create mode 100644 queue-2.6.38/mmc-sdhci-pci-fix-error-case-in-sdhci_pci_probe_slot.patch create mode 100644 queue-2.6.38/mpt2sas-prevent-heap-overflows-and-unchecked-reads.patch create mode 100644 queue-2.6.38/pmcraid-reject-negative-request-size.patch create mode 100644 queue-2.6.38/put-stricter-guards-on-queue-dead-checks.patch create mode 100644 queue-2.6.38/revert-alsa-hda-fix-pin-config-of-gigabyte-mobo.patch create mode 100644 queue-2.6.38/scsi_dh-fix-reference-counting-in-scsi_dh_activate-error-path.patch create mode 100644 queue-2.6.38/series create mode 100644 queue-2.6.38/ubifs-do-not-free-write-buffers-when-in-r-o-mode.patch create mode 100644 queue-2.6.38/ubifs-seek-journal-heads-to-the-latest-bud-in-replay.patch create mode 100644 queue-2.6.38/usb-fix-regression-in-usbip-by-setting-has_tt-flag.patch create mode 100644 queue-2.6.38/usbnet-add-support-for-some-huawei-modems-with-cdc-ether-ports.patch create mode 100644 queue-2.6.38/v4l-make-sure-drivers-supply-a-zeroed-struct-v4l2_subdev.patch create mode 100644 queue-2.6.38/workqueue-fix-deadlock-in-worker_maybe_bind_and_lock.patch create mode 100644 queue-2.6.38/x86-amd-fix-apic-timer-erratum-400-affecting-k8-rev.a-e-processors.patch diff --git a/queue-2.6.38/alsa-hda-fix-automute-for-gateway-nv79.patch b/queue-2.6.38/alsa-hda-fix-automute-for-gateway-nv79.patch new file mode 100644 index 00000000000..3fdd8aed3de --- /dev/null +++ b/queue-2.6.38/alsa-hda-fix-automute-for-gateway-nv79.patch @@ -0,0 +1,48 @@ +From 94024cd1aefa0f8bcc9dfe46c05bd7ce3f471a1c Mon Sep 17 00:00:00 2001 +From: David Henningsson +Date: Fri, 29 Apr 2011 14:10:55 +0200 +Subject: ALSA: HDA: Fix automute for Gateway NV79 + +From: David Henningsson + +commit 94024cd1aefa0f8bcc9dfe46c05bd7ce3f471a1c upstream. + +The PCI SSID is 1025:031c and the codec SSID is 1025:031d, +so the driver mistakes this for a SKU value, but looking at +the numbers, this is obviously wrong. + +BugLink: http://bugs.launchpad.net/bugs/761861 +Signed-off-by: David Henningsson +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -19556,6 +19556,7 @@ enum { + ALC272_FIXUP_MARIO, + ALC662_FIXUP_CZC_P10T, + ALC662_FIXUP_GIGABYTE, ++ ALC662_FIXUP_SKU_IGNORE, + }; + + static const struct alc_fixup alc662_fixups[] = { +@@ -19591,10 +19592,15 @@ static const struct alc_fixup alc662_fix + { } + } + }, ++ [ALC662_FIXUP_SKU_IGNORE] = { ++ .type = ALC_FIXUP_SKU, ++ .v.sku = ALC_FIXUP_SKU_IGNORE, ++ }, + }; + + static struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), ++ SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), + SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", ALC662_FIXUP_GIGABYTE), diff --git a/queue-2.6.38/alsa-hda-fix-realtek-s-chained-fixup-checks.patch b/queue-2.6.38/alsa-hda-fix-realtek-s-chained-fixup-checks.patch new file mode 100644 index 00000000000..73c6a7ea0e4 --- /dev/null +++ b/queue-2.6.38/alsa-hda-fix-realtek-s-chained-fixup-checks.patch @@ -0,0 +1,35 @@ +From 24af2b1cc418d6791b1d9e56bf6070cccb752db3 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 2 May 2011 13:55:36 +0200 +Subject: ALSA: hda - Fix Realtek's chained fixup checks + +From: Takashi Iwai + +commit 24af2b1cc418d6791b1d9e56bf6070cccb752db3 upstream. + +The check of chained fixup list entry was done against the wrong element. +A stupid mistake during refactoring. + +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -1774,11 +1774,11 @@ static void alc_apply_fixup(struct hda_c + codec->chip_name, fix->type); + break; + } +- if (!fix[id].chained) ++ if (!fix->chained) + break; + if (++depth > 10) + break; +- id = fix[id].chain_id; ++ id = fix->chain_id; + } + } + diff --git a/queue-2.6.38/atl1c-fix-work-event-interrupt-task-races.patch b/queue-2.6.38/atl1c-fix-work-event-interrupt-task-races.patch new file mode 100644 index 00000000000..3cca89f65e5 --- /dev/null +++ b/queue-2.6.38/atl1c-fix-work-event-interrupt-task-races.patch @@ -0,0 +1,84 @@ +From cb771838715b1c470bc5735bdae709b33b18e0ad Mon Sep 17 00:00:00 2001 +From: Tim Gardner +Date: Wed, 20 Apr 2011 09:00:49 +0000 +Subject: atl1c: Fix work event interrupt/task races + +From: Tim Gardner + +commit cb771838715b1c470bc5735bdae709b33b18e0ad upstream. + +The mechanism used to initiate work events from the interrupt +handler has a classic read/modify/write race between the interrupt +handler that sets the condition, and the worker task that reads and +clears the condition. Close these races by using atomic +bit fields. + +Cc: Jie Yang +Signed-off-by: Tim Gardner +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/atl1c/atl1c.h | 6 +++--- + drivers/net/atl1c/atl1c_main.c | 14 +++++--------- + 2 files changed, 8 insertions(+), 12 deletions(-) + +--- a/drivers/net/atl1c/atl1c.h ++++ b/drivers/net/atl1c/atl1c.h +@@ -566,9 +566,9 @@ struct atl1c_adapter { + #define __AT_TESTING 0x0001 + #define __AT_RESETTING 0x0002 + #define __AT_DOWN 0x0003 +- u8 work_event; +-#define ATL1C_WORK_EVENT_RESET 0x01 +-#define ATL1C_WORK_EVENT_LINK_CHANGE 0x02 ++ unsigned long work_event; ++#define ATL1C_WORK_EVENT_RESET 0 ++#define ATL1C_WORK_EVENT_LINK_CHANGE 1 + u32 msg_enable; + + bool have_msi; +--- a/drivers/net/atl1c/atl1c_main.c ++++ b/drivers/net/atl1c/atl1c_main.c +@@ -325,7 +325,7 @@ static void atl1c_link_chg_event(struct + } + } + +- adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE; ++ set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event); + schedule_work(&adapter->common_task); + } + +@@ -337,20 +337,16 @@ static void atl1c_common_task(struct wor + adapter = container_of(work, struct atl1c_adapter, common_task); + netdev = adapter->netdev; + +- if (adapter->work_event & ATL1C_WORK_EVENT_RESET) { +- adapter->work_event &= ~ATL1C_WORK_EVENT_RESET; ++ if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) { + netif_device_detach(netdev); + atl1c_down(adapter); + atl1c_up(adapter); + netif_device_attach(netdev); +- return; + } + +- if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) { +- adapter->work_event &= ~ATL1C_WORK_EVENT_LINK_CHANGE; ++ if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE, ++ &adapter->work_event)) + atl1c_check_link_status(adapter); +- } +- return; + } + + +@@ -369,7 +365,7 @@ static void atl1c_tx_timeout(struct net_ + struct atl1c_adapter *adapter = netdev_priv(netdev); + + /* Do the reset outside of interrupt context */ +- adapter->work_event |= ATL1C_WORK_EVENT_RESET; ++ set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event); + schedule_work(&adapter->common_task); + } + diff --git a/queue-2.6.38/drm-radeon-fix-regression-on-atom-cards-with-hardcoded-edid-record.patch b/queue-2.6.38/drm-radeon-fix-regression-on-atom-cards-with-hardcoded-edid-record.patch new file mode 100644 index 00000000000..87cf560e360 --- /dev/null +++ b/queue-2.6.38/drm-radeon-fix-regression-on-atom-cards-with-hardcoded-edid-record.patch @@ -0,0 +1,38 @@ +From eaa4f5e1d0b816291a59a47917e569c0384f2b6f Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Sun, 1 May 2011 20:16:30 +1000 +Subject: drm/radeon: fix regression on atom cards with hardcoded EDID record. + +From: Dave Airlie + +commit eaa4f5e1d0b816291a59a47917e569c0384f2b6f upstream. + +Since fafcf94e2b5732d1e13b440291c53115d2b172e9 introduced an edid size, it seems to have broken this path. + +This manifest as oops on T500 Lenovo laptops with dual graphics primarily. + +Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33812 + +Reviewed-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_atombios.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -1599,9 +1599,10 @@ struct radeon_encoder_atom_dig *radeon_a + memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], + fake_edid_record->ucFakeEDIDLength); + +- if (drm_edid_is_valid(edid)) ++ if (drm_edid_is_valid(edid)) { + rdev->mode_info.bios_hardcoded_edid = edid; +- else ++ rdev->mode_info.bios_hardcoded_edid_size = edid_size; ++ } else + kfree(edid); + } + } diff --git a/queue-2.6.38/firewire-fix-for-broken-configrom-updates-in-quick-succession.patch b/queue-2.6.38/firewire-fix-for-broken-configrom-updates-in-quick-succession.patch new file mode 100644 index 00000000000..b87a17610cc --- /dev/null +++ b/queue-2.6.38/firewire-fix-for-broken-configrom-updates-in-quick-succession.patch @@ -0,0 +1,110 @@ +From 2e053a27d9d5ad5e0831e002cbf8043836fb2060 Mon Sep 17 00:00:00 2001 +From: B.J. Buchalter +Date: Mon, 2 May 2011 13:33:42 -0400 +Subject: firewire: Fix for broken configrom updates in quick succession + +From: B.J. Buchalter + +commit 2e053a27d9d5ad5e0831e002cbf8043836fb2060 upstream. + +Current implementation of ohci_set_config_rom() uses a deferred +bus reset via fw_schedule_bus_reset(). If clients add multiple +unit descriptors to the config_rom in quick succession, the +deferred bus reset may not have fired before succeeding update +requests have come in. This can lead to an incorrect partial +update of the config_rom for both addition and removal of +config_rom descriptors, as the ohci_set_config_rom() routine +will return -EBUSY if a previous pending update has not been +completed yet; the requested update just gets dropped on the floor. + +This patch recognizes that the "in-flight" update can be modified +until it has been processed by the bus-reset, and the locking +in the bus_reset_tasklet ensures that the update is done atomically +with respect to modifications made by ohci_set_config_rom(). The +-EBUSY error case is simply removed. + +[Stefan R: The bug always existed at least theoretically. But it +became easy to trigger since 2.6.36 commit 02d37bed188c "firewire: core: +integrate software-forced bus resets with bus management" which +introduced long mandatory delays between janitorial bus resets.] + +Signed-off-by: Benjamin Buchalter +Signed-off-by: Stefan Richter (trivial style changes) +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firewire/ohci.c | 39 +++++++++++++++++++++++++-------------- + 1 file changed, 25 insertions(+), 14 deletions(-) + +--- a/drivers/firewire/ohci.c ++++ b/drivers/firewire/ohci.c +@@ -2163,7 +2163,6 @@ static int ohci_set_config_rom(struct fw + { + struct fw_ohci *ohci; + unsigned long flags; +- int ret = -EBUSY; + __be32 *next_config_rom; + dma_addr_t uninitialized_var(next_config_rom_bus); + +@@ -2204,22 +2203,37 @@ static int ohci_set_config_rom(struct fw + + spin_lock_irqsave(&ohci->lock, flags); + ++ /* ++ * If there is not an already pending config_rom update, ++ * push our new allocation into the ohci->next_config_rom ++ * and then mark the local variable as null so that we ++ * won't deallocate the new buffer. ++ * ++ * OTOH, if there is a pending config_rom update, just ++ * use that buffer with the new config_rom data, and ++ * let this routine free the unused DMA allocation. ++ */ ++ + if (ohci->next_config_rom == NULL) { + ohci->next_config_rom = next_config_rom; + ohci->next_config_rom_bus = next_config_rom_bus; ++ next_config_rom = NULL; ++ } + +- copy_config_rom(ohci->next_config_rom, config_rom, length); ++ copy_config_rom(ohci->next_config_rom, config_rom, length); + +- ohci->next_header = config_rom[0]; +- ohci->next_config_rom[0] = 0; ++ ohci->next_header = config_rom[0]; ++ ohci->next_config_rom[0] = 0; + +- reg_write(ohci, OHCI1394_ConfigROMmap, +- ohci->next_config_rom_bus); +- ret = 0; +- } ++ reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); + + spin_unlock_irqrestore(&ohci->lock, flags); + ++ /* If we didn't use the DMA allocation, delete it. */ ++ if (next_config_rom != NULL) ++ dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, ++ next_config_rom, next_config_rom_bus); ++ + /* + * Now initiate a bus reset to have the changes take + * effect. We clean up the old config rom memory and DMA +@@ -2227,13 +2241,10 @@ static int ohci_set_config_rom(struct fw + * controller could need to access it before the bus reset + * takes effect. + */ +- if (ret == 0) +- fw_schedule_bus_reset(&ohci->card, true, true); +- else +- dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, +- next_config_rom, next_config_rom_bus); + +- return ret; ++ fw_schedule_bus_reset(&ohci->card, true, true); ++ ++ return 0; + } + + static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) diff --git a/queue-2.6.38/flex_array-flex_array_prealloc-takes-a-number-of-elements-not-an-end.patch b/queue-2.6.38/flex_array-flex_array_prealloc-takes-a-number-of-elements-not-an-end.patch new file mode 100644 index 00000000000..6d3b4dc106b --- /dev/null +++ b/queue-2.6.38/flex_array-flex_array_prealloc-takes-a-number-of-elements-not-an-end.patch @@ -0,0 +1,119 @@ +From 5d30b10bd68df007e7ae21e77d1e0ce184b53040 Mon Sep 17 00:00:00 2001 +From: Eric Paris +Date: Thu, 28 Apr 2011 15:55:52 -0400 +Subject: flex_array: flex_array_prealloc takes a number of elements, not an end + +From: Eric Paris + +commit 5d30b10bd68df007e7ae21e77d1e0ce184b53040 upstream. + +Change flex_array_prealloc to take the number of elements for which space +should be allocated instead of the last (inclusive) element. Users +and documentation are updated accordingly. flex_arrays got introduced before +they had users. When folks started using it, they ended up needing a +different API than was coded up originally. This swaps over to the API that +folks apparently need. + +Based-on-patch-by: Steffen Klassert +Signed-off-by: Eric Paris +Tested-by: Chris Richards +Acked-by: Dave Hansen +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/flexible-arrays.txt | 4 ++-- + include/linux/flex_array.h | 2 +- + lib/flex_array.c | 13 ++++++++----- + security/selinux/ss/policydb.c | 6 +++--- + 4 files changed, 14 insertions(+), 11 deletions(-) + +--- a/Documentation/flexible-arrays.txt ++++ b/Documentation/flexible-arrays.txt +@@ -66,10 +66,10 @@ trick is to ensure that any needed memor + entering atomic context, using: + + int flex_array_prealloc(struct flex_array *array, unsigned int start, +- unsigned int end, gfp_t flags); ++ unsigned int nr_elements, gfp_t flags); + + This function will ensure that memory for the elements indexed in the range +-defined by start and end has been allocated. Thereafter, a ++defined by start and nr_elements has been allocated. Thereafter, a + flex_array_put() call on an element in that range is guaranteed not to + block. + +--- a/include/linux/flex_array.h ++++ b/include/linux/flex_array.h +@@ -61,7 +61,7 @@ struct flex_array { + struct flex_array *flex_array_alloc(int element_size, unsigned int total, + gfp_t flags); + int flex_array_prealloc(struct flex_array *fa, unsigned int start, +- unsigned int end, gfp_t flags); ++ unsigned int nr_elements, gfp_t flags); + void flex_array_free(struct flex_array *fa); + void flex_array_free_parts(struct flex_array *fa); + int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, +--- a/lib/flex_array.c ++++ b/lib/flex_array.c +@@ -232,10 +232,10 @@ EXPORT_SYMBOL(flex_array_clear); + + /** + * flex_array_prealloc - guarantee that array space exists +- * @fa: the flex array for which to preallocate parts +- * @start: index of first array element for which space is allocated +- * @end: index of last (inclusive) element for which space is allocated +- * @flags: page allocation flags ++ * @fa: the flex array for which to preallocate parts ++ * @start: index of first array element for which space is allocated ++ * @nr_elements: number of elements for which space is allocated ++ * @flags: page allocation flags + * + * This will guarantee that no future calls to flex_array_put() + * will allocate memory. It can be used if you are expecting to +@@ -245,13 +245,16 @@ EXPORT_SYMBOL(flex_array_clear); + * Locking must be provided by the caller. + */ + int flex_array_prealloc(struct flex_array *fa, unsigned int start, +- unsigned int end, gfp_t flags) ++ unsigned int nr_elements, gfp_t flags) + { + int start_part; + int end_part; + int part_nr; ++ unsigned int end; + struct flex_array_part *part; + ++ end = start + nr_elements - 1; ++ + if (start >= fa->total_nr_elements || end >= fa->total_nr_elements) + return -ENOSPC; + if (elements_fit_in_base(fa)) +--- a/security/selinux/ss/policydb.c ++++ b/security/selinux/ss/policydb.c +@@ -497,7 +497,7 @@ static int policydb_index(struct policyd + goto out; + + rc = flex_array_prealloc(p->type_val_to_struct_array, 0, +- p->p_types.nprim - 1, GFP_KERNEL | __GFP_ZERO); ++ p->p_types.nprim, GFP_KERNEL | __GFP_ZERO); + if (rc) + goto out; + +@@ -514,7 +514,7 @@ static int policydb_index(struct policyd + goto out; + + rc = flex_array_prealloc(p->sym_val_to_name[i], +- 0, p->symtab[i].nprim - 1, ++ 0, p->symtab[i].nprim, + GFP_KERNEL | __GFP_ZERO); + if (rc) + goto out; +@@ -2286,7 +2286,7 @@ int policydb_read(struct policydb *p, vo + goto bad; + + /* preallocate so we don't have to worry about the put ever failing */ +- rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1, ++ rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim, + GFP_KERNEL | __GFP_ZERO); + if (rc) + goto bad; diff --git a/queue-2.6.38/flex_arrays-allow-zero-length-flex-arrays.patch b/queue-2.6.38/flex_arrays-allow-zero-length-flex-arrays.patch new file mode 100644 index 00000000000..566a0270a1f --- /dev/null +++ b/queue-2.6.38/flex_arrays-allow-zero-length-flex-arrays.patch @@ -0,0 +1,55 @@ +From bf69d41d198138e3c601e9a6645f4f1369aff7e0 Mon Sep 17 00:00:00 2001 +From: Eric Paris +Date: Thu, 28 Apr 2011 15:55:52 -0400 +Subject: flex_arrays: allow zero length flex arrays + +From: Eric Paris + +commit bf69d41d198138e3c601e9a6645f4f1369aff7e0 upstream. + +Just like kmalloc will allow one to allocate a 0 length segment of memory +flex arrays should do the same thing. It should bomb if you try to use +something, but it should at least allow the allocation. + +This is needed because when SELinux switched to using flex_arrays in 2.6.38 +the inability to allocate a 0 length array resulted in SELinux policy load +returning -ENOSPC when previously it worked. + +Based-on-patch-by: Steffen Klassert +Signed-off-by: Eric Paris +Tested-by: Chris Richards +Signed-off-by: Greg Kroah-Hartman + +--- + lib/flex_array.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/lib/flex_array.c ++++ b/lib/flex_array.c +@@ -253,9 +253,16 @@ int flex_array_prealloc(struct flex_arra + unsigned int end; + struct flex_array_part *part; + ++ if (!start && !nr_elements) ++ return 0; ++ if (start >= fa->total_nr_elements) ++ return -ENOSPC; ++ if (!nr_elements) ++ return 0; ++ + end = start + nr_elements - 1; + +- if (start >= fa->total_nr_elements || end >= fa->total_nr_elements) ++ if (end >= fa->total_nr_elements) + return -ENOSPC; + if (elements_fit_in_base(fa)) + return 0; +@@ -346,6 +353,8 @@ int flex_array_shrink(struct flex_array + int part_nr; + int ret = 0; + ++ if (!fa->total_nr_elements) ++ return 0; + if (elements_fit_in_base(fa)) + return ret; + for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) { diff --git a/queue-2.6.38/i2c-parport-fix-adapter-list-handling.patch b/queue-2.6.38/i2c-parport-fix-adapter-list-handling.patch new file mode 100644 index 00000000000..5a4908e7f15 --- /dev/null +++ b/queue-2.6.38/i2c-parport-fix-adapter-list-handling.patch @@ -0,0 +1,100 @@ +From 56acc7a39ac4ac7638cdc32cd3d0832ebbc834e4 Mon Sep 17 00:00:00 2001 +From: Jean Delvare +Date: Sun, 1 May 2011 18:18:49 +0200 +Subject: i2c-parport: Fix adapter list handling + +From: Jean Delvare + +commit 56acc7a39ac4ac7638cdc32cd3d0832ebbc834e4 upstream. + +Use a standard list with proper locking to handle the list of +adapters. Thankfully it only matters on systems with more than one +parallel port, which are very rare. + +Thanks to Lukasz Kapiec for reporting the problem to me. + +Signed-off-by: Jean Delvare +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/i2c/busses/i2c-parport.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +--- a/drivers/i2c/busses/i2c-parport.c ++++ b/drivers/i2c/busses/i2c-parport.c +@@ -1,7 +1,7 @@ + /* ------------------------------------------------------------------------ * + * i2c-parport.c I2C bus over parallel port * + * ------------------------------------------------------------------------ * +- Copyright (C) 2003-2010 Jean Delvare ++ Copyright (C) 2003-2011 Jean Delvare + + Based on older i2c-philips-par.c driver + Copyright (C) 1995-2000 Simon G. Vogl +@@ -33,6 +33,8 @@ + #include + #include + #include ++#include ++#include + #include "i2c-parport.h" + + /* ----- Device list ------------------------------------------------------ */ +@@ -43,10 +45,11 @@ struct i2c_par { + struct i2c_algo_bit_data algo_data; + struct i2c_smbus_alert_setup alert_data; + struct i2c_client *ara; +- struct i2c_par *next; ++ struct list_head node; + }; + +-static struct i2c_par *adapter_list; ++static LIST_HEAD(adapter_list); ++static DEFINE_MUTEX(adapter_list_lock); + + /* ----- Low-level parallel port access ----------------------------------- */ + +@@ -228,8 +231,9 @@ static void i2c_parport_attach (struct p + } + + /* Add the new adapter to the list */ +- adapter->next = adapter_list; +- adapter_list = adapter; ++ mutex_lock(&adapter_list_lock); ++ list_add_tail(&adapter->node, &adapter_list); ++ mutex_unlock(&adapter_list_lock); + return; + + ERROR1: +@@ -241,11 +245,11 @@ ERROR0: + + static void i2c_parport_detach (struct parport *port) + { +- struct i2c_par *adapter, *prev; ++ struct i2c_par *adapter, *_n; + + /* Walk the list */ +- for (prev = NULL, adapter = adapter_list; adapter; +- prev = adapter, adapter = adapter->next) { ++ mutex_lock(&adapter_list_lock); ++ list_for_each_entry_safe(adapter, _n, &adapter_list, node) { + if (adapter->pdev->port == port) { + if (adapter->ara) { + parport_disable_irq(port); +@@ -259,14 +263,11 @@ static void i2c_parport_detach (struct p + + parport_release(adapter->pdev); + parport_unregister_device(adapter->pdev); +- if (prev) +- prev->next = adapter->next; +- else +- adapter_list = adapter->next; ++ list_del(&adapter->node); + kfree(adapter); +- return; + } + } ++ mutex_unlock(&adapter_list_lock); + } + + static struct parport_driver i2c_parport_driver = { diff --git a/queue-2.6.38/imon-add-conditional-locking-in-change_protocol.patch b/queue-2.6.38/imon-add-conditional-locking-in-change_protocol.patch new file mode 100644 index 00000000000..206343f7e00 --- /dev/null +++ b/queue-2.6.38/imon-add-conditional-locking-in-change_protocol.patch @@ -0,0 +1,194 @@ +From 23ef710e1a6c4d6b9ef1c2fa19410f7f1479401e Mon Sep 17 00:00:00 2001 +From: Jarod Wilson +Date: Wed, 27 Apr 2011 19:01:44 -0300 +Subject: [media] imon: add conditional locking in change_protocol + +From: Jarod Wilson + +commit 23ef710e1a6c4d6b9ef1c2fa19410f7f1479401e upstream. + +The imon_ir_change_protocol function gets called two different ways, one +way is from rc_register_device, for initial protocol selection/setup, +and the other is via a userspace-initiated protocol change request, +either by direct sysfs prodding or by something like ir-keytable. + +In the rc_register_device case, the imon context lock is already held, +but when initiated from userspace, it is not, so we must acquire it, +prior to calling send_packet, which requires that the lock is held. + +Without this change, there's an easily reproduceable deadlock when +another function calls send_packet (such as either of the display write +fops) after a userspace-initiated change_protocol. + +With a lock-debugging-enabled kernel, I was getting this: + +[ 15.014153] ===================================== +[ 15.015048] [ BUG: bad unlock balance detected! ] +[ 15.015048] ------------------------------------- +[ 15.015048] ir-keytable/773 is trying to release lock (&ictx->lock) at: +[ 15.015048] [] mutex_unlock+0xe/0x10 +[ 15.015048] but there are no more locks to release! +[ 15.015048] +[ 15.015048] other info that might help us debug this: +[ 15.015048] 2 locks held by ir-keytable/773: +[ 15.015048] #0: (&buffer->mutex){+.+.+.}, at: [] sysfs_write_file+0x3c/0x144 +[ 15.015048] #1: (s_active#87){.+.+.+}, at: [] sysfs_write_file+0xe7/0x144 +[ 15.015048] +[ 15.015048] stack backtrace: +[ 15.015048] Pid: 773, comm: ir-keytable Not tainted 2.6.38.4-20.fc15.x86_64.debug #1 +[ 15.015048] Call Trace: +[ 15.015048] [] ? print_unlock_inbalance_bug+0xca/0xd5 +[ 15.015048] [] ? lock_release_non_nested+0xc1/0x263 +[ 15.015048] [] ? mutex_unlock+0xe/0x10 +[ 15.015048] [] ? mutex_unlock+0xe/0x10 +[ 15.015048] [] ? lock_release+0x17d/0x1a4 +[ 15.015048] [] ? __mutex_unlock_slowpath+0xc5/0x125 +[ 15.015048] [] ? mutex_unlock+0xe/0x10 +[ 15.015048] [] ? send_packet+0x1c9/0x264 [imon] +[ 15.015048] [] ? lock_release_non_nested+0xdb/0x263 +[ 15.015048] [] ? imon_ir_change_protocol+0x126/0x15e [imon] +[ 15.015048] [] ? store_protocols+0x1c3/0x286 [rc_core] +[ 15.015048] [] ? dev_attr_store+0x20/0x22 +[ 15.015048] [] ? sysfs_write_file+0x108/0x144 +... + +The original report that led to the investigation was the following: + +[ 1679.457305] INFO: task LCDd:8460 blocked for more than 120 seconds. +[ 1679.457307] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 1679.457309] LCDd D ffff88010fcd89c8 0 8460 1 0x00000000 +[ 1679.457312] ffff8800d5a03b48 0000000000000082 0000000000000000 ffff8800d5a03fd8 +[ 1679.457314] 00000000012dcd30 fffffffffffffffd ffff8800d5a03fd8 ffff88010fcd86f0 +[ 1679.457316] ffff8800d5a03fd8 ffff8800d5a03fd8 ffff88010fcd89d0 ffff8800d5a03fd8 +[ 1679.457319] Call Trace: +[ 1679.457324] [] ? zone_statistics+0x75/0x90 +[ 1679.457327] [] ? get_page_from_freelist+0x3c7/0x820 +[ 1679.457330] [] __mutex_lock_slowpath+0x139/0x320 +[ 1679.457335] [] mutex_lock+0x11/0x30 +[ 1679.457338] [] display_open+0x66/0x130 [imon] +[ 1679.457345] [] usb_open+0x180/0x310 [usbcore] +[ 1679.457349] [] chrdev_open+0x1bb/0x2d0 +[ 1679.457350] [] __dentry_open+0x10d/0x370 +[ 1679.457352] [] ? chrdev_open+0x0/0x2d0 +... + +Bump the driver version here so its easier to tell if people have this +locking fix or not, and also make locking during probe easier to follow. + +Reported-by: Benjamin Hodgetts +Signed-off-by: Jarod Wilson +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/rc/imon.c | 31 +++++++++++++++++++++++++++---- + 1 file changed, 27 insertions(+), 4 deletions(-) + +--- a/drivers/media/rc/imon.c ++++ b/drivers/media/rc/imon.c +@@ -46,7 +46,7 @@ + #define MOD_AUTHOR "Jarod Wilson " + #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" + #define MOD_NAME "imon" +-#define MOD_VERSION "0.9.2" ++#define MOD_VERSION "0.9.3" + + #define DISPLAY_MINOR_BASE 144 + #define DEVICE_NAME "lcd%d" +@@ -451,8 +451,9 @@ static int display_close(struct inode *i + } + + /** +- * Sends a packet to the device -- this function must be called +- * with ictx->lock held. ++ * Sends a packet to the device -- this function must be called with ++ * ictx->lock held, or its unlock/lock sequence while waiting for tx ++ * to complete can/will lead to a deadlock. + */ + static int send_packet(struct imon_context *ictx) + { +@@ -982,12 +983,21 @@ static void imon_touch_display_timeout(u + * the iMON remotes, and those used by the Windows MCE remotes (which is + * really just RC-6), but only one or the other at a time, as the signals + * are decoded onboard the receiver. ++ * ++ * This function gets called two different ways, one way is from ++ * rc_register_device, for initial protocol selection/setup, and the other is ++ * via a userspace-initiated protocol change request, either by direct sysfs ++ * prodding or by something like ir-keytable. In the rc_register_device case, ++ * the imon context lock is already held, but when initiated from userspace, ++ * it is not, so we must acquire it prior to calling send_packet, which ++ * requires that the lock is held. + */ + static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) + { + int retval; + struct imon_context *ictx = rc->priv; + struct device *dev = ictx->dev; ++ bool unlock = false; + unsigned char ir_proto_packet[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; + +@@ -1020,6 +1030,11 @@ static int imon_ir_change_protocol(struc + + memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); + ++ if (!mutex_is_locked(&ictx->lock)) { ++ unlock = true; ++ mutex_lock(&ictx->lock); ++ } ++ + retval = send_packet(ictx); + if (retval) + goto out; +@@ -1028,6 +1043,9 @@ static int imon_ir_change_protocol(struc + ictx->pad_mouse = false; + + out: ++ if (unlock) ++ mutex_unlock(&ictx->lock); ++ + return retval; + } + +@@ -2125,6 +2143,7 @@ static struct imon_context *imon_init_in + goto rdev_setup_failed; + } + ++ mutex_unlock(&ictx->lock); + return ictx; + + rdev_setup_failed: +@@ -2196,6 +2215,7 @@ static struct imon_context *imon_init_in + goto urb_submit_failed; + } + ++ mutex_unlock(&ictx->lock); + return ictx; + + urb_submit_failed: +@@ -2290,6 +2310,8 @@ static int __devinit imon_probe(struct u + usb_set_intfdata(interface, ictx); + + if (ifnum == 0) { ++ mutex_lock(&ictx->lock); ++ + if (product == 0xffdc && ictx->rf_device) { + sysfs_err = sysfs_create_group(&interface->dev.kobj, + &imon_rf_attr_group); +@@ -2300,13 +2322,14 @@ static int __devinit imon_probe(struct u + + if (ictx->display_supported) + imon_init_display(ictx, interface); ++ ++ mutex_unlock(&ictx->lock); + } + + dev_info(dev, "iMON device (%04x:%04x, intf%d) on " + "usb<%d:%d> initialized\n", vendor, product, ifnum, + usbdev->bus->busnum, usbdev->devnum); + +- mutex_unlock(&ictx->lock); + mutex_unlock(&driver_lock); + + return 0; diff --git a/queue-2.6.38/iwlagn-fix-received-ba-when-not-expected.patch b/queue-2.6.38/iwlagn-fix-received-ba-when-not-expected.patch new file mode 100644 index 00000000000..e266343a79d --- /dev/null +++ b/queue-2.6.38/iwlagn-fix-received-ba-when-not-expected.patch @@ -0,0 +1,68 @@ +From bfd36103ec26599557c2bd3225a1f1c9267f8fcb Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Fri, 29 Apr 2011 17:51:06 +0200 +Subject: iwlagn: fix "Received BA when not expected" + +From: Stanislaw Gruszka + +commit bfd36103ec26599557c2bd3225a1f1c9267f8fcb upstream. + +Need to use broadcast sta_id for management frames, otherwise we broke +BA session in the firmware and get messages like that: + +"Received BA when not expected" + +or (on older kernels): + +"BA scd_flow 0 does not match txq_id 10" + +This fix regression introduced in 2.6.35 during station management +code rewrite by: + +commit 2a87c26bbe9587baeb9e56d3ce0b4971bd777643 +Author: Johannes Berg +Date: Fri Apr 30 11:30:45 2010 -0700 + + iwlwifi: use iwl_find_station less + +Patch partially resolve: +https://bugzilla.kernel.org/show_bug.cgi?id=16691 +However, there are still 11n performance problems on 4965 and 5xxx +devices that need to be investigated. + +Signed-off-by: Stanislaw Gruszka +Acked-by: Johannes Berg +Acked-by: Wey-Yi Guy +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +@@ -561,12 +561,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, + + hdr_len = ieee80211_hdrlen(fc); + +- /* Find index into station table for destination station */ +- sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta); +- if (sta_id == IWL_INVALID_STATION) { +- IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", +- hdr->addr1); +- goto drop_unlock; ++ /* For management frames use broadcast id to do not break aggregation */ ++ if (!ieee80211_is_data(fc)) ++ sta_id = ctx->bcast_sta_id; ++ else { ++ /* Find index into station table for destination station */ ++ sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta); ++ if (sta_id == IWL_INVALID_STATION) { ++ IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", ++ hdr->addr1); ++ goto drop_unlock; ++ } + } + + IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); diff --git a/queue-2.6.38/iwlwifi-fix-skb-usage-after-free.patch b/queue-2.6.38/iwlwifi-fix-skb-usage-after-free.patch new file mode 100644 index 00000000000..0cbf0e07ec5 --- /dev/null +++ b/queue-2.6.38/iwlwifi-fix-skb-usage-after-free.patch @@ -0,0 +1,55 @@ +From b25026981aecde3685dd0e45ad980fff9f528daa Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Wed, 20 Apr 2011 15:57:14 +0200 +Subject: iwlwifi: fix skb usage after free + +From: Stanislaw Gruszka + +commit b25026981aecde3685dd0e45ad980fff9f528daa upstream. + +Since + +commit a120e912eb51e347f36c71b60a1d13af74d30e83 +Author: Stanislaw Gruszka +Date: Fri Feb 19 15:47:33 2010 -0800 + + iwlwifi: sanity check before counting number of tfds can be free + +we use skb->data after calling ieee80211_tx_status_irqsafe(), which +could free skb instantly. + +On current kernels I do not observe practical problems related with +bug, but on 2.6.35.y it cause random system hangs when stressing +wireless link. + +Signed-off-by: Stanislaw Gruszka +Acked-by: Wey-Yi Guy +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +@@ -1207,12 +1207,16 @@ int iwlagn_tx_queue_reclaim(struct iwl_p + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { + + tx_info = &txq->txb[txq->q.read_ptr]; +- iwlagn_tx_status(priv, tx_info, +- txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); ++ ++ if (WARN_ON_ONCE(tx_info->skb == NULL)) ++ continue; + + hdr = (struct ieee80211_hdr *)tx_info->skb->data; +- if (hdr && ieee80211_is_data_qos(hdr->frame_control)) ++ if (ieee80211_is_data_qos(hdr->frame_control)) + nfreed++; ++ ++ iwlagn_tx_status(priv, tx_info, ++ txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); + tx_info->skb = NULL; + + if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) diff --git a/queue-2.6.38/mmc-fix-a-race-between-card-detect-rescan-and-clock-gate-work-instances.patch b/queue-2.6.38/mmc-fix-a-race-between-card-detect-rescan-and-clock-gate-work-instances.patch new file mode 100644 index 00000000000..546be02c4e7 --- /dev/null +++ b/queue-2.6.38/mmc-fix-a-race-between-card-detect-rescan-and-clock-gate-work-instances.patch @@ -0,0 +1,82 @@ +From 26fc8775b51484d8c0a671198639c6d5ae60533e Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski +Date: Fri, 15 Apr 2011 20:08:19 +0200 +Subject: mmc: fix a race between card-detect rescan and clock-gate work instances + +From: Guennadi Liakhovetski + +commit 26fc8775b51484d8c0a671198639c6d5ae60533e upstream. + +Currently there is a race in the MMC core between a card-detect +rescan work and the clock-gating work, scheduled from a command +completion. Fix it by removing the dedicated clock-gating mutex +and using the MMC standard locking mechanism instead. + +Signed-off-by: Guennadi Liakhovetski +Cc: Simon Horman +Cc: Magnus Damm +Acked-by: Linus Walleij +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/core/host.c | 9 ++++----- + include/linux/mmc/host.h | 1 - + 2 files changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/mmc/core/host.c ++++ b/drivers/mmc/core/host.c +@@ -94,7 +94,7 @@ static void mmc_host_clk_gate_delayed(st + spin_unlock_irqrestore(&host->clk_lock, flags); + return; + } +- mutex_lock(&host->clk_gate_mutex); ++ mmc_claim_host(host); + spin_lock_irqsave(&host->clk_lock, flags); + if (!host->clk_requests) { + spin_unlock_irqrestore(&host->clk_lock, flags); +@@ -104,7 +104,7 @@ static void mmc_host_clk_gate_delayed(st + pr_debug("%s: gated MCI clock\n", mmc_hostname(host)); + } + spin_unlock_irqrestore(&host->clk_lock, flags); +- mutex_unlock(&host->clk_gate_mutex); ++ mmc_release_host(host); + } + + /* +@@ -130,7 +130,7 @@ void mmc_host_clk_ungate(struct mmc_host + { + unsigned long flags; + +- mutex_lock(&host->clk_gate_mutex); ++ mmc_claim_host(host); + spin_lock_irqsave(&host->clk_lock, flags); + if (host->clk_gated) { + spin_unlock_irqrestore(&host->clk_lock, flags); +@@ -140,7 +140,7 @@ void mmc_host_clk_ungate(struct mmc_host + } + host->clk_requests++; + spin_unlock_irqrestore(&host->clk_lock, flags); +- mutex_unlock(&host->clk_gate_mutex); ++ mmc_release_host(host); + } + + /** +@@ -218,7 +218,6 @@ static inline void mmc_host_clk_init(str + host->clk_gated = false; + INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); + spin_lock_init(&host->clk_lock); +- mutex_init(&host->clk_gate_mutex); + } + + /** +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -183,7 +183,6 @@ struct mmc_host { + struct work_struct clk_gate_work; /* delayed clock gate */ + unsigned int clk_old; /* old clock value cache */ + spinlock_t clk_lock; /* lock for clk fields */ +- struct mutex clk_gate_mutex; /* mutex for clock gating */ + #endif + + /* host specific block data */ diff --git a/queue-2.6.38/mmc-sdhci-check-mrq-cmd-in-sdhci_tasklet_finish.patch b/queue-2.6.38/mmc-sdhci-check-mrq-cmd-in-sdhci_tasklet_finish.patch new file mode 100644 index 00000000000..3b6ea3962ab --- /dev/null +++ b/queue-2.6.38/mmc-sdhci-check-mrq-cmd-in-sdhci_tasklet_finish.patch @@ -0,0 +1,39 @@ +From b7b4d3426d2b5ecab21578eb20d8e456a1aace8f Mon Sep 17 00:00:00 2001 +From: Ben Dooks +Date: Wed, 27 Apr 2011 14:24:19 +0100 +Subject: mmc: sdhci: Check mrq->cmd in sdhci_tasklet_finish + +From: Ben Dooks + +commit b7b4d3426d2b5ecab21578eb20d8e456a1aace8f upstream. + +It seems that under certain circumstances that the sdhci_tasklet_finish() +call can be entered with mrq->cmd set to NULL, causing the system to crash +with a NULL pointer de-reference. + +Unable to handle kernel NULL pointer dereference at virtual address 00000000 +PC is at sdhci_tasklet_finish+0x34/0xe8 +LR is at sdhci_tasklet_finish+0x24/0xe8 + +Seen on S3C6410 system. + +Signed-off-by: Ben Dooks +Signed-off-by: Mark Brown +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/host/sdhci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -1345,7 +1345,7 @@ static void sdhci_tasklet_finish(unsigne + * upon error conditions. + */ + if (!(host->flags & SDHCI_DEVICE_DEAD) && +- (mrq->cmd->error || ++ ((mrq->cmd && mrq->cmd->error) || + (mrq->data && (mrq->data->error || + (mrq->data->stop && mrq->data->stop->error))) || + (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) { diff --git a/queue-2.6.38/mmc-sdhci-check-mrq-null-in-sdhci_tasklet_finish.patch b/queue-2.6.38/mmc-sdhci-check-mrq-null-in-sdhci_tasklet_finish.patch new file mode 100644 index 00000000000..e17852ea124 --- /dev/null +++ b/queue-2.6.38/mmc-sdhci-check-mrq-null-in-sdhci_tasklet_finish.patch @@ -0,0 +1,39 @@ +From 0c9c99a765321104cc5f9c97f949382a9ba4927e Mon Sep 17 00:00:00 2001 +From: Chris Ball +Date: Wed, 27 Apr 2011 17:35:31 -0400 +Subject: mmc: sdhci: Check mrq != NULL in sdhci_tasklet_finish + +From: Chris Ball + +commit 0c9c99a765321104cc5f9c97f949382a9ba4927e upstream. + +It seems that under certain circumstances the sdhci_tasklet_finish() +call can be entered with mrq set to NULL, causing the system to crash +with a NULL pointer de-reference. + +Seen on S3C6410 system. Based on a patch by Dimitris Papastamos. + +Reported-by: Dimitris Papastamos +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/host/sdhci.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -1334,6 +1334,13 @@ static void sdhci_tasklet_finish(unsigne + + host = (struct sdhci_host*)param; + ++ /* ++ * If this tasklet gets rescheduled while running, it will ++ * be run again afterwards but without any active request. ++ */ ++ if (!host->mrq) ++ return; ++ + spin_lock_irqsave(&host->lock, flags); + + del_timer(&host->timer); diff --git a/queue-2.6.38/mmc-sdhci-pci-fix-error-case-in-sdhci_pci_probe_slot.patch b/queue-2.6.38/mmc-sdhci-pci-fix-error-case-in-sdhci_pci_probe_slot.patch new file mode 100644 index 00000000000..faa7df552fb --- /dev/null +++ b/queue-2.6.38/mmc-sdhci-pci-fix-error-case-in-sdhci_pci_probe_slot.patch @@ -0,0 +1,35 @@ +From 9fdcdbb0d84922e7ccda2f717a04ea62629f7e18 Mon Sep 17 00:00:00 2001 +From: Chris Ball +Date: Tue, 29 Mar 2011 00:46:12 -0400 +Subject: mmc: sdhci-pci: Fix error case in sdhci_pci_probe_slot() + +From: Chris Ball + +commit 9fdcdbb0d84922e7ccda2f717a04ea62629f7e18 upstream. + +If pci_ioremap_bar() fails during probe, we "goto release;" and free the +host, but then we return 0 -- which tells sdhci_pci_probe() that the probe +succeeded. Since we think the probe succeeded, when we unload sdhci we'll +go to sdhci_pci_remove_slot() and it will try to dereference slot->host, +which is now NULL because we freed it in the error path earlier. + +The patch simply sets ret appropriately, so that sdhci_pci_probe() will +detect the failure immediately and bail out. + +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/host/sdhci-pci.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mmc/host/sdhci-pci.c ++++ b/drivers/mmc/host/sdhci-pci.c +@@ -961,6 +961,7 @@ static struct sdhci_pci_slot * __devinit + host->ioaddr = pci_ioremap_bar(pdev, bar); + if (!host->ioaddr) { + dev_err(&pdev->dev, "failed to remap registers\n"); ++ ret = -ENOMEM; + goto release; + } + diff --git a/queue-2.6.38/mpt2sas-prevent-heap-overflows-and-unchecked-reads.patch b/queue-2.6.38/mpt2sas-prevent-heap-overflows-and-unchecked-reads.patch new file mode 100644 index 00000000000..2aea0979d93 --- /dev/null +++ b/queue-2.6.38/mpt2sas-prevent-heap-overflows-and-unchecked-reads.patch @@ -0,0 +1,86 @@ +From a1f74ae82d133ebb2aabb19d181944b4e83e9960 Mon Sep 17 00:00:00 2001 +From: Dan Rosenberg +Date: Tue, 5 Apr 2011 12:45:59 -0400 +Subject: [SCSI] mpt2sas: prevent heap overflows and unchecked reads + +From: Dan Rosenberg + +commit a1f74ae82d133ebb2aabb19d181944b4e83e9960 upstream. + +At two points in handling device ioctls via /dev/mpt2ctl, user-supplied +length values are used to copy data from userspace into heap buffers +without bounds checking, allowing controllable heap corruption and +subsequently privilege escalation. + +Additionally, user-supplied values are used to determine the size of a +copy_to_user() as well as the offset into the buffer to be read, with no +bounds checking, allowing users to read arbitrary kernel memory. + +Signed-off-by: Dan Rosenberg +Acked-by: Eric Moore +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/mpt2sas/mpt2sas_ctl.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c ++++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c +@@ -688,6 +688,13 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPT + goto out; + } + ++ /* Check for overflow and wraparound */ ++ if (karg.data_sge_offset * 4 > ioc->request_sz || ++ karg.data_sge_offset > (UINT_MAX / 4)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + /* copy in request message frame from user */ + if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, +@@ -1963,7 +1970,7 @@ _ctl_diag_read_buffer(void __user *arg, + Mpi2DiagBufferPostReply_t *mpi_reply; + int rc, i; + u8 buffer_type; +- unsigned long timeleft; ++ unsigned long timeleft, request_size, copy_size; + u16 smid; + u16 ioc_status; + u8 issue_reset = 0; +@@ -1999,6 +2006,8 @@ _ctl_diag_read_buffer(void __user *arg, + return -ENOMEM; + } + ++ request_size = ioc->diag_buffer_sz[buffer_type]; ++ + if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { + printk(MPT2SAS_ERR_FMT "%s: either the starting_offset " + "or bytes_to_read are not 4 byte aligned\n", ioc->name, +@@ -2006,13 +2015,23 @@ _ctl_diag_read_buffer(void __user *arg, + return -EINVAL; + } + ++ if (karg.starting_offset > request_size) ++ return -EINVAL; ++ + diag_data = (void *)(request_data + karg.starting_offset); + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), " + "offset(%d), sz(%d)\n", ioc->name, __func__, + diag_data, karg.starting_offset, karg.bytes_to_read)); + ++ /* Truncate data on requests that are too large */ ++ if ((diag_data + karg.bytes_to_read < diag_data) || ++ (diag_data + karg.bytes_to_read > request_data + request_size)) ++ copy_size = request_size - karg.starting_offset; ++ else ++ copy_size = karg.bytes_to_read; ++ + if (copy_to_user((void __user *)uarg->diagnostic_data, +- diag_data, karg.bytes_to_read)) { ++ diag_data, copy_size)) { + printk(MPT2SAS_ERR_FMT "%s: Unable to write " + "mpt_diag_read_buffer_t data @ %p\n", ioc->name, + __func__, diag_data); diff --git a/queue-2.6.38/pmcraid-reject-negative-request-size.patch b/queue-2.6.38/pmcraid-reject-negative-request-size.patch new file mode 100644 index 00000000000..0149daefa18 --- /dev/null +++ b/queue-2.6.38/pmcraid-reject-negative-request-size.patch @@ -0,0 +1,53 @@ +From 5f6279da3760ce48f478f2856aacebe0c59a39f3 Mon Sep 17 00:00:00 2001 +From: Dan Rosenberg +Date: Tue, 5 Apr 2011 13:27:31 -0400 +Subject: [SCSI] pmcraid: reject negative request size + +From: Dan Rosenberg + +commit 5f6279da3760ce48f478f2856aacebe0c59a39f3 upstream. + +There's a code path in pmcraid that can be reached via device ioctl that +causes all sorts of ugliness, including heap corruption or triggering +the OOM killer due to consecutive allocation of large numbers of pages. +Not especially relevant from a security perspective, since users must +have CAP_SYS_ADMIN to open the character device. + +First, the user can call pmcraid_chr_ioctl() with a type +PMCRAID_PASSTHROUGH_IOCTL. A pmcraid_passthrough_ioctl_buffer +is copied in, and the request_size variable is set to +buffer->ioarcb.data_transfer_length, which is an arbitrary 32-bit signed +value provided by the user. + +If a negative value is provided here, bad things can happen. For +example, pmcraid_build_passthrough_ioadls() is called with this +request_size, which immediately calls pmcraid_alloc_sglist() with a +negative size. The resulting math on allocating a scatter list can +result in an overflow in the kzalloc() call (if num_elem is 0, the +sglist will be smaller than expected), or if num_elem is unexpectedly +large the subsequent loop will call alloc_pages() repeatedly, a high +number of pages will be allocated and the OOM killer might be invoked. + +Prevent this value from being negative in pmcraid_ioctl_passthrough(). + +Signed-off-by: Dan Rosenberg +Cc: Anil Ravindranath +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/pmcraid.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/scsi/pmcraid.c ++++ b/drivers/scsi/pmcraid.c +@@ -3814,6 +3814,9 @@ static long pmcraid_ioctl_passthrough( + rc = -EFAULT; + goto out_free_buffer; + } ++ } else if (request_size < 0) { ++ rc = -EINVAL; ++ goto out_free_buffer; + } + + /* check if we have any additional command parameters */ diff --git a/queue-2.6.38/put-stricter-guards-on-queue-dead-checks.patch b/queue-2.6.38/put-stricter-guards-on-queue-dead-checks.patch new file mode 100644 index 00000000000..d2471cd0200 --- /dev/null +++ b/queue-2.6.38/put-stricter-guards-on-queue-dead-checks.patch @@ -0,0 +1,61 @@ +From 86cbfb5607d4b81b1a993ff689bbd2addd5d3a9b Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Fri, 22 Apr 2011 10:39:59 -0500 +Subject: [SCSI] put stricter guards on queue dead checks + +From: James Bottomley + +commit 86cbfb5607d4b81b1a993ff689bbd2addd5d3a9b upstream. + +SCSI uses request_queue->queuedata == NULL as a signal that the queue +is dying. We set this state in the sdev release function. However, +this allows a small window where we release the last reference but +haven't quite got to this stage yet and so something will try to take +a reference in scsi_request_fn and oops. It's very rare, but we had a +report here, so we're pushing this as a bug fix + +The actual fix is to set request_queue->queuedata to NULL in +scsi_remove_device() before we drop the reference. This causes +correct automatic rejects from scsi_request_fn as people who hold +additional references try to submit work and prevents anything from +getting a new reference to the sdev that way. + +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/scsi_sysfs.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -322,14 +322,8 @@ static void scsi_device_dev_release_user + kfree(evt); + } + +- if (sdev->request_queue) { +- sdev->request_queue->queuedata = NULL; +- /* user context needed to free queue */ +- scsi_free_queue(sdev->request_queue); +- /* temporary expedient, try to catch use of queue lock +- * after free of sdev */ +- sdev->request_queue = NULL; +- } ++ /* NULL queue means the device can't be used */ ++ sdev->request_queue = NULL; + + scsi_target_reap(scsi_target(sdev)); + +@@ -937,6 +931,12 @@ void __scsi_remove_device(struct scsi_de + if (sdev->host->hostt->slave_destroy) + sdev->host->hostt->slave_destroy(sdev); + transport_destroy_device(dev); ++ ++ /* cause the request function to reject all I/O requests */ ++ sdev->request_queue->queuedata = NULL; ++ ++ /* Freeing the queue signals to block that we're done */ ++ scsi_free_queue(sdev->request_queue); + put_device(dev); + } + diff --git a/queue-2.6.38/revert-alsa-hda-fix-pin-config-of-gigabyte-mobo.patch b/queue-2.6.38/revert-alsa-hda-fix-pin-config-of-gigabyte-mobo.patch new file mode 100644 index 00000000000..d03a5fd544c --- /dev/null +++ b/queue-2.6.38/revert-alsa-hda-fix-pin-config-of-gigabyte-mobo.patch @@ -0,0 +1,104 @@ +From ebb47241ea0eac6a5a23404821a2d62f64c68496 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 2 May 2011 10:37:29 +0200 +Subject: Revert "ALSA: hda - Fix pin-config of Gigabyte mobo" + +From: Takashi Iwai + +commit ebb47241ea0eac6a5a23404821a2d62f64c68496 upstream. + +This reverts commit c6b358748e19ce7e230b0926ac42696bc485a562. + +It turned out that there are different pin configurations for this +PCI SSID, including multi-channel modes. And more proper fix for +allowing line-out mutes will come up in 2.6.40 tree, so we won't need +this fixup any more there. + +Reported-by: Andrew Clayton +Reported-by: Emmanuel Benisty +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 21 +++------------------ + 1 file changed, 3 insertions(+), 18 deletions(-) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -9932,6 +9932,7 @@ static struct snd_pci_quirk alc882_cfg_t + SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), + SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL), + SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), ++ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG), + + SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG), + SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG), +@@ -10768,7 +10769,6 @@ enum { + PINFIX_LENOVO_Y530, + PINFIX_PB_M5210, + PINFIX_ACER_ASPIRE_7736, +- PINFIX_GIGABYTE_880GM, + }; + + static const struct alc_fixup alc882_fixups[] = { +@@ -10800,13 +10800,6 @@ static const struct alc_fixup alc882_fix + .type = ALC_FIXUP_SKU, + .v.sku = ALC_FIXUP_SKU_IGNORE, + }, +- [PINFIX_GIGABYTE_880GM] = { +- .type = ALC_FIXUP_PINS, +- .v.pins = (const struct alc_pincfg[]) { +- { 0x14, 0x1114410 }, /* set as speaker */ +- { } +- } +- }, + }; + + static struct snd_pci_quirk alc882_fixup_tbl[] = { +@@ -10814,7 +10807,6 @@ static struct snd_pci_quirk alc882_fixup + SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530), + SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), + SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736), +- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", PINFIX_GIGABYTE_880GM), + {} + }; + +@@ -18882,6 +18874,8 @@ static struct snd_pci_quirk alc662_cfg_t + ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO), + SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), ++ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ++ ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13), + SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA), +@@ -19555,7 +19549,6 @@ enum { + ALC662_FIXUP_IDEAPAD, + ALC272_FIXUP_MARIO, + ALC662_FIXUP_CZC_P10T, +- ALC662_FIXUP_GIGABYTE, + ALC662_FIXUP_SKU_IGNORE, + }; + +@@ -19585,13 +19578,6 @@ static const struct alc_fixup alc662_fix + {} + } + }, +- [ALC662_FIXUP_GIGABYTE] = { +- .type = ALC_FIXUP_PINS, +- .v.pins = (const struct alc_pincfg[]) { +- { 0x14, 0x1114410 }, /* set as speaker */ +- { } +- } +- }, + [ALC662_FIXUP_SKU_IGNORE] = { + .type = ALC_FIXUP_SKU, + .v.sku = ALC_FIXUP_SKU_IGNORE, +@@ -19603,7 +19589,6 @@ static struct snd_pci_quirk alc662_fixup + SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), + SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), +- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", ALC662_FIXUP_GIGABYTE), + SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T), diff --git a/queue-2.6.38/scsi_dh-fix-reference-counting-in-scsi_dh_activate-error-path.patch b/queue-2.6.38/scsi_dh-fix-reference-counting-in-scsi_dh_activate-error-path.patch new file mode 100644 index 00000000000..bd12af1d837 --- /dev/null +++ b/queue-2.6.38/scsi_dh-fix-reference-counting-in-scsi_dh_activate-error-path.patch @@ -0,0 +1,57 @@ +From 0b8393578c70bc1f09790eeae7d918f38da2e010 Mon Sep 17 00:00:00 2001 +From: Mike Snitzer +Date: Fri, 8 Apr 2011 15:05:36 -0400 +Subject: [SCSI] scsi_dh: fix reference counting in scsi_dh_activate error path + +From: Mike Snitzer + +commit 0b8393578c70bc1f09790eeae7d918f38da2e010 upstream. + +Commit db422318cbca55168cf965f655471dbf8be82433 ([SCSI] scsi_dh: +propagate SCSI device deletion) introduced a regression where the device +reference is not dropped prior to scsi_dh_activate's early return from +the error path. + +Signed-off-by: Mike Snitzer +Reviewed-by: Mike Christie +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/device_handler/scsi_dh.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/device_handler/scsi_dh.c ++++ b/drivers/scsi/device_handler/scsi_dh.c +@@ -437,12 +437,14 @@ int scsi_dh_activate(struct request_queu + unsigned long flags; + struct scsi_device *sdev; + struct scsi_device_handler *scsi_dh = NULL; ++ struct device *dev = NULL; + + spin_lock_irqsave(q->queue_lock, flags); + sdev = q->queuedata; + if (sdev && sdev->scsi_dh_data) + scsi_dh = sdev->scsi_dh_data->scsi_dh; +- if (!scsi_dh || !get_device(&sdev->sdev_gendev) || ++ dev = get_device(&sdev->sdev_gendev); ++ if (!scsi_dh || !dev || + sdev->sdev_state == SDEV_CANCEL || + sdev->sdev_state == SDEV_DEL) + err = SCSI_DH_NOSYS; +@@ -453,12 +455,13 @@ int scsi_dh_activate(struct request_queu + if (err) { + if (fn) + fn(data, err); +- return err; ++ goto out; + } + + if (scsi_dh->activate) + err = scsi_dh->activate(sdev, fn, data); +- put_device(&sdev->sdev_gendev); ++out: ++ put_device(dev); + return err; + } + EXPORT_SYMBOL_GPL(scsi_dh_activate); diff --git a/queue-2.6.38/series b/queue-2.6.38/series new file mode 100644 index 00000000000..5fb2fb0c9d2 --- /dev/null +++ b/queue-2.6.38/series @@ -0,0 +1,27 @@ +pmcraid-reject-negative-request-size.patch +mpt2sas-prevent-heap-overflows-and-unchecked-reads.patch +scsi_dh-fix-reference-counting-in-scsi_dh_activate-error-path.patch +put-stricter-guards-on-queue-dead-checks.patch +alsa-hda-fix-automute-for-gateway-nv79.patch +revert-alsa-hda-fix-pin-config-of-gigabyte-mobo.patch +alsa-hda-fix-realtek-s-chained-fixup-checks.patch +i2c-parport-fix-adapter-list-handling.patch +workqueue-fix-deadlock-in-worker_maybe_bind_and_lock.patch +iwlwifi-fix-skb-usage-after-free.patch +iwlagn-fix-received-ba-when-not-expected.patch +atl1c-fix-work-event-interrupt-task-races.patch +ubifs-do-not-free-write-buffers-when-in-r-o-mode.patch +ubifs-seek-journal-heads-to-the-latest-bud-in-replay.patch +mmc-fix-a-race-between-card-detect-rescan-and-clock-gate-work-instances.patch +mmc-sdhci-pci-fix-error-case-in-sdhci_pci_probe_slot.patch +mmc-sdhci-check-mrq-cmd-in-sdhci_tasklet_finish.patch +mmc-sdhci-check-mrq-null-in-sdhci_tasklet_finish.patch +drm-radeon-fix-regression-on-atom-cards-with-hardcoded-edid-record.patch +usb-fix-regression-in-usbip-by-setting-has_tt-flag.patch +firewire-fix-for-broken-configrom-updates-in-quick-succession.patch +usbnet-add-support-for-some-huawei-modems-with-cdc-ether-ports.patch +v4l-make-sure-drivers-supply-a-zeroed-struct-v4l2_subdev.patch +imon-add-conditional-locking-in-change_protocol.patch +flex_array-flex_array_prealloc-takes-a-number-of-elements-not-an-end.patch +flex_arrays-allow-zero-length-flex-arrays.patch +x86-amd-fix-apic-timer-erratum-400-affecting-k8-rev.a-e-processors.patch diff --git a/queue-2.6.38/ubifs-do-not-free-write-buffers-when-in-r-o-mode.patch b/queue-2.6.38/ubifs-do-not-free-write-buffers-when-in-r-o-mode.patch new file mode 100644 index 00000000000..5cd7d352c72 --- /dev/null +++ b/queue-2.6.38/ubifs-do-not-free-write-buffers-when-in-r-o-mode.patch @@ -0,0 +1,123 @@ +From b50b9f408502a2ea90459ae36ba8cdc9cc005cfe Mon Sep 17 00:00:00 2001 +From: Artem Bityutskiy +Date: Mon, 25 Apr 2011 18:17:09 +0300 +Subject: UBIFS: do not free write-buffers when in R/O mode + +From: Artem Bityutskiy + +commit b50b9f408502a2ea90459ae36ba8cdc9cc005cfe upstream. + +Currently UBIFS has a small optimization - it frees write-buffers when it is +re-mounted from R/W mode to R/O mode. Of course, when it is mounted R/O, it +does not allocate write-buffers as well. + +This optimization is nice but it leads to subtle problems and complications +in recovery, which I can reproduce using the integck test. The symptoms are +that after a power cut the file-system cannot be mounted if we first mount +it R/O, and then re-mount R/W - 'ubifs_rcvry_gc_commit()' prints: + +UBIFS error (pid 34456): could not find an empty LEB + +Analysis of the problem. + +When mounting R/W, the reply process sets journal heads to buds [1], but +when mounting R/O - it does not do this, because the write-buffers are not +allocated. So 'ubifs_rcvry_gc_commit()' works completely differently for the +same file-system but for the following 2 cases: + +1. mounting R/W after a power cut and recover +2. mounting R/O after a power cut, re-mounting R/W and run deferred recovery + +In the former case, we have journal heads seeked to the a bud, in the latter +case, they are non-seeked (wbuf->lnum == -1). So in the latter case we do not +try to recover the GC LEB by garbage-collecting to the GC head, but we just +try to find an empty LEB, and there may be no empty LEBs, so we just fail. +On the other hand, in the former case (mount R/W), we are able to make a GC LEB +(@c->gc_lnum) by garbage-collecting. + +Thus, let's remove this small nice optimization and always allocate +write-buffers. This should not make too big difference - we have only 3 +of them, each of max. write unit size, which is usually 2KiB. So this is +about 6KiB of RAM for the typical case, and only when mounted R/O. + +[1]: Note, currently the replay process is setting (seeking) the journal heads +to _some_ buds, not necessarily to the buds which had been the journal heads +before the power cut happened. This will be fixed separately. + +Signed-off-by: Artem Bityutskiy +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/log.c | 20 -------------------- + fs/ubifs/super.c | 15 ++++----------- + 2 files changed, 4 insertions(+), 31 deletions(-) + +--- a/fs/ubifs/log.c ++++ b/fs/ubifs/log.c +@@ -175,26 +175,6 @@ void ubifs_add_bud(struct ubifs_info *c, + } + + /** +- * ubifs_create_buds_lists - create journal head buds lists for remount rw. +- * @c: UBIFS file-system description object +- */ +-void ubifs_create_buds_lists(struct ubifs_info *c) +-{ +- struct rb_node *p; +- +- spin_lock(&c->buds_lock); +- p = rb_first(&c->buds); +- while (p) { +- struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb); +- struct ubifs_jhead *jhead = &c->jheads[bud->jhead]; +- +- list_add_tail(&bud->list, &jhead->buds_list); +- p = rb_next(p); +- } +- spin_unlock(&c->buds_lock); +-} +- +-/** + * ubifs_add_bud_to_log - add a new bud to the log. + * @c: UBIFS file-system description object + * @jhead: journal head the bud belongs to +--- a/fs/ubifs/super.c ++++ b/fs/ubifs/super.c +@@ -1235,12 +1235,12 @@ static int mount_ubifs(struct ubifs_info + goto out_free; + } + ++ err = alloc_wbufs(c); ++ if (err) ++ goto out_cbuf; ++ + sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); + if (!c->ro_mount) { +- err = alloc_wbufs(c); +- if (err) +- goto out_cbuf; +- + /* Create background thread */ + c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name); + if (IS_ERR(c->bgt)) { +@@ -1603,12 +1603,6 @@ static int ubifs_remount_rw(struct ubifs + if (err) + goto out; + +- err = alloc_wbufs(c); +- if (err) +- goto out; +- +- ubifs_create_buds_lists(c); +- + /* Create background thread */ + c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name); + if (IS_ERR(c->bgt)) { +@@ -1717,7 +1711,6 @@ static void ubifs_remount_ro(struct ubif + if (err) + ubifs_ro_mode(c, err); + +- free_wbufs(c); + vfree(c->orph_buf); + c->orph_buf = NULL; + vfree(c->ileb_buf); diff --git a/queue-2.6.38/ubifs-seek-journal-heads-to-the-latest-bud-in-replay.patch b/queue-2.6.38/ubifs-seek-journal-heads-to-the-latest-bud-in-replay.patch new file mode 100644 index 00000000000..34848dbc50d --- /dev/null +++ b/queue-2.6.38/ubifs-seek-journal-heads-to-the-latest-bud-in-replay.patch @@ -0,0 +1,116 @@ +From 52c6e6f990669deac3f370f1603815adb55a1dbd Mon Sep 17 00:00:00 2001 +From: Artem Bityutskiy +Date: Mon, 25 Apr 2011 18:46:31 +0300 +Subject: UBIFS: seek journal heads to the latest bud in replay + +From: Artem Bityutskiy + +commit 52c6e6f990669deac3f370f1603815adb55a1dbd upstream. + +This is the second fix of the following symptom: + +UBIFS error (pid 34456): could not find an empty LEB + +which sometimes happens after power cuts when we mount the file-system - UBIFS +refuses it with the above error message which comes from the +'ubifs_rcvry_gc_commit()' function. I can reproduce this using the integck test +with the UBIFS power cut emulation enabled. + +Analysis of the problem. + +Currently UBIFS replay seeks the journal heads to the last _replayed_ bud. +But the buds are replayed out-of-order, so the replay basically seeks journal +heads to the "random" bud belonging to this head, and not to the _last_ one. + +The result of this is that the GC head may be seeked to a full LEB with no free +space, or very little free space. And 'ubifs_rcvry_gc_commit()' tries to find a +fully or mostly dirty LEB to match the current GC head (because we need to +garbage-collect that dirty LEB at one go, because we do not have @c->gc_lnum). +So 'ubifs_find_dirty_leb()' fails and we fall back to finding an empty LEB and +also fail. As a result - recovery fails and mounting fails. + +This patch teaches the replay to initialize the GC heads exactly to the latest +buds, i.e. the buds which have the largest sequence number in corresponding +log reference nodes. + +Signed-off-by: Artem Bityutskiy +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/replay.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/fs/ubifs/replay.c ++++ b/fs/ubifs/replay.c +@@ -59,6 +59,7 @@ enum { + * @new_size: truncation new size + * @free: amount of free space in a bud + * @dirty: amount of dirty space in a bud from padding and deletion nodes ++ * @jhead: journal head number of the bud + * + * UBIFS journal replay must compare node sequence numbers, which means it must + * build a tree of node information to insert into the TNC. +@@ -80,6 +81,7 @@ struct replay_entry { + struct { + int free; + int dirty; ++ int jhead; + }; + }; + }; +@@ -159,6 +161,11 @@ static int set_bud_lprops(struct ubifs_i + err = PTR_ERR(lp); + goto out; + } ++ ++ /* Make sure the journal head points to the latest bud */ ++ err = ubifs_wbuf_seek_nolock(&c->jheads[r->jhead].wbuf, r->lnum, ++ c->leb_size - r->free, UBI_SHORTTERM); ++ + out: + ubifs_release_lprops(c); + return err; +@@ -627,10 +634,6 @@ static int replay_bud(struct ubifs_info + ubifs_assert(sleb->endpt - offs >= used); + ubifs_assert(sleb->endpt % c->min_io_size == 0); + +- if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount) +- err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum, +- sleb->endpt, UBI_SHORTTERM); +- + *dirty = sleb->endpt - offs - used; + *free = c->leb_size - sleb->endpt; + +@@ -653,12 +656,14 @@ out_dump: + * @sqnum: sequence number + * @free: amount of free space in bud + * @dirty: amount of dirty space from padding and deletion nodes ++ * @jhead: journal head number for the bud + * + * This function inserts a reference node to the replay tree and returns zero + * in case of success or a negative error code in case of failure. + */ + static int insert_ref_node(struct ubifs_info *c, int lnum, int offs, +- unsigned long long sqnum, int free, int dirty) ++ unsigned long long sqnum, int free, int dirty, ++ int jhead) + { + struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL; + struct replay_entry *r; +@@ -688,6 +693,7 @@ static int insert_ref_node(struct ubifs_ + r->flags = REPLAY_REF; + r->free = free; + r->dirty = dirty; ++ r->jhead = jhead; + + rb_link_node(&r->rb, parent, p); + rb_insert_color(&r->rb, &c->replay_tree); +@@ -712,7 +718,7 @@ static int replay_buds(struct ubifs_info + if (err) + return err; + err = insert_ref_node(c, b->bud->lnum, b->bud->start, b->sqnum, +- free, dirty); ++ free, dirty, b->bud->jhead); + if (err) + return err; + } diff --git a/queue-2.6.38/usb-fix-regression-in-usbip-by-setting-has_tt-flag.patch b/queue-2.6.38/usb-fix-regression-in-usbip-by-setting-has_tt-flag.patch new file mode 100644 index 00000000000..026b38ccb30 --- /dev/null +++ b/queue-2.6.38/usb-fix-regression-in-usbip-by-setting-has_tt-flag.patch @@ -0,0 +1,34 @@ +From cee6a262550f53a13acfefbc1e3e5ff35c96182c Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Mon, 2 May 2011 14:21:44 -0400 +Subject: USB: fix regression in usbip by setting has_tt flag + +From: Alan Stern + +commit cee6a262550f53a13acfefbc1e3e5ff35c96182c upstream. + +This patch (as1460) fixes a regression in the usbip driver caused by +the new check for Transaction Translators in USB-2 hubs. The root hub +registered by vhci_hcd needs to have the has_tt flag set, because it +can connect to low- and full-speed devices as well as high-speed +devices. + +Signed-off-by: Alan Stern +Reported-and-tested-by: Nikola Ciprich +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/usbip/vhci_hcd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/usbip/vhci_hcd.c ++++ b/drivers/staging/usbip/vhci_hcd.c +@@ -1135,7 +1135,7 @@ static int vhci_hcd_probe(struct platfor + usbip_uerr("create hcd failed\n"); + return -ENOMEM; + } +- ++ hcd->has_tt = 1; + + /* this is private data for vhci_hcd */ + the_controller = hcd_to_vhci(hcd); diff --git a/queue-2.6.38/usbnet-add-support-for-some-huawei-modems-with-cdc-ether-ports.patch b/queue-2.6.38/usbnet-add-support-for-some-huawei-modems-with-cdc-ether-ports.patch new file mode 100644 index 00000000000..b6e190afa1c --- /dev/null +++ b/queue-2.6.38/usbnet-add-support-for-some-huawei-modems-with-cdc-ether-ports.patch @@ -0,0 +1,59 @@ +From b3c914aa84f4e4bbb3efc8f41c359d96e5e932d2 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Wed, 27 Apr 2011 09:54:28 +0000 +Subject: usbnet: add support for some Huawei modems with cdc-ether ports + +From: Dan Williams + +commit b3c914aa84f4e4bbb3efc8f41c359d96e5e932d2 upstream. + +Some newer Huawei devices (T-Mobile Rocket, others) have cdc-ether +compatible ports, so recognize and expose them. + +Signed-off-by: Dan Williams +Acked-by: Oliver Neukum +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/usb/cdc_ether.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/net/usb/cdc_ether.c ++++ b/drivers/net/usb/cdc_ether.c +@@ -458,7 +458,7 @@ static const struct driver_info cdc_info + .manage_power = cdc_manage_power, + }; + +-static const struct driver_info mbm_info = { ++static const struct driver_info wwan_info = { + .description = "Mobile Broadband Network Device", + .flags = FLAG_WWAN, + .bind = cdc_bind, +@@ -469,6 +469,7 @@ static const struct driver_info mbm_info + + /*-------------------------------------------------------------------------*/ + ++#define HUAWEI_VENDOR_ID 0x12D1 + + static const struct usb_device_id products [] = { + /* +@@ -578,8 +579,17 @@ static const struct usb_device_id produc + }, { + USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, + USB_CDC_PROTO_NONE), +- .driver_info = (unsigned long)&mbm_info, ++ .driver_info = (unsigned long)&wwan_info, + ++}, { ++ /* Various Huawei modems with a network port like the UMG1831 */ ++ .match_flags = USB_DEVICE_ID_MATCH_VENDOR ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = HUAWEI_VENDOR_ID, ++ .bInterfaceClass = USB_CLASS_COMM, ++ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, ++ .bInterfaceProtocol = 255, ++ .driver_info = (unsigned long)&wwan_info, + }, + { }, // END + }; diff --git a/queue-2.6.38/v4l-make-sure-drivers-supply-a-zeroed-struct-v4l2_subdev.patch b/queue-2.6.38/v4l-make-sure-drivers-supply-a-zeroed-struct-v4l2_subdev.patch new file mode 100644 index 00000000000..758296adba5 --- /dev/null +++ b/queue-2.6.38/v4l-make-sure-drivers-supply-a-zeroed-struct-v4l2_subdev.patch @@ -0,0 +1,124 @@ +From 80845a33165278f3236812009e9c568ba8c29938 Mon Sep 17 00:00:00 2001 +From: Herton Ronaldo Krzesinski +Date: Fri, 1 Apr 2011 14:12:02 -0300 +Subject: [media] v4l: make sure drivers supply a zeroed struct v4l2_subdev + +From: Herton Ronaldo Krzesinski + +commit 80845a33165278f3236812009e9c568ba8c29938 upstream. + +Some v4l drivers currently don't initialize their struct v4l2_subdev +with zeros, and this is a problem since some of the v4l2 code expects +this. One example is the addition of internal_ops in commit 45f6f84, +after that we are at risk of random oopses with these drivers when code +in v4l2_device_register_subdev tries to dereference sd->internal_ops->*, +as can be shown by the report at http://bugs.launchpad.net/bugs/745213 +and analysis of its crash at https://lkml.org/lkml/2011/4/1/168 + +Use kzalloc within problematic drivers to ensure we have a zeroed struct +v4l2_subdev. + +BugLink: http://bugs.launchpad.net/bugs/745213 +Signed-off-by: Herton Ronaldo Krzesinski +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/radio/saa7706h.c | 2 +- + drivers/media/radio/tef6862.c | 2 +- + drivers/media/video/m52790.c | 2 +- + drivers/media/video/tda9840.c | 2 +- + drivers/media/video/tea6415c.c | 2 +- + drivers/media/video/tea6420.c | 2 +- + drivers/media/video/upd64031a.c | 2 +- + drivers/media/video/upd64083.c | 2 +- + 8 files changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/media/radio/saa7706h.c ++++ b/drivers/media/radio/saa7706h.c +@@ -376,7 +376,7 @@ static int __devinit saa7706h_probe(stru + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + +- state = kmalloc(sizeof(struct saa7706h_state), GFP_KERNEL); ++ state = kzalloc(sizeof(struct saa7706h_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + sd = &state->sd; +--- a/drivers/media/radio/tef6862.c ++++ b/drivers/media/radio/tef6862.c +@@ -176,7 +176,7 @@ static int __devinit tef6862_probe(struc + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + +- state = kmalloc(sizeof(struct tef6862_state), GFP_KERNEL); ++ state = kzalloc(sizeof(struct tef6862_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + state->freq = TEF6862_LO_FREQ; +--- a/drivers/media/video/m52790.c ++++ b/drivers/media/video/m52790.c +@@ -174,7 +174,7 @@ static int m52790_probe(struct i2c_clien + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + +- state = kmalloc(sizeof(struct m52790_state), GFP_KERNEL); ++ state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + +--- a/drivers/media/video/tda9840.c ++++ b/drivers/media/video/tda9840.c +@@ -171,7 +171,7 @@ static int tda9840_probe(struct i2c_clie + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + +- sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); ++ sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &tda9840_ops); +--- a/drivers/media/video/tea6415c.c ++++ b/drivers/media/video/tea6415c.c +@@ -152,7 +152,7 @@ static int tea6415c_probe(struct i2c_cli + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); +- sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); ++ sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &tea6415c_ops); +--- a/drivers/media/video/tea6420.c ++++ b/drivers/media/video/tea6420.c +@@ -125,7 +125,7 @@ static int tea6420_probe(struct i2c_clie + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + +- sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); ++ sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &tea6420_ops); +--- a/drivers/media/video/upd64031a.c ++++ b/drivers/media/video/upd64031a.c +@@ -230,7 +230,7 @@ static int upd64031a_probe(struct i2c_cl + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + +- state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL); ++ state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + sd = &state->sd; +--- a/drivers/media/video/upd64083.c ++++ b/drivers/media/video/upd64083.c +@@ -202,7 +202,7 @@ static int upd64083_probe(struct i2c_cli + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + +- state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL); ++ state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + sd = &state->sd; diff --git a/queue-2.6.38/workqueue-fix-deadlock-in-worker_maybe_bind_and_lock.patch b/queue-2.6.38/workqueue-fix-deadlock-in-worker_maybe_bind_and_lock.patch new file mode 100644 index 00000000000..cbc9a263321 --- /dev/null +++ b/queue-2.6.38/workqueue-fix-deadlock-in-worker_maybe_bind_and_lock.patch @@ -0,0 +1,54 @@ +From 5035b20fa5cd146b66f5f89619c20a4177fb736d Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Fri, 29 Apr 2011 18:08:37 +0200 +Subject: workqueue: fix deadlock in worker_maybe_bind_and_lock() + +From: Tejun Heo + +commit 5035b20fa5cd146b66f5f89619c20a4177fb736d upstream. + +If a rescuer and stop_machine() bringing down a CPU race with each +other, they may deadlock on non-preemptive kernel. The CPU won't +accept a new task, so the rescuer can't migrate to the target CPU, +while stop_machine() can't proceed because the rescuer is holding one +of the CPU retrying migration. GCWQ_DISASSOCIATED is never cleared +and worker_maybe_bind_and_lock() retries indefinitely. + +This problem can be reproduced semi reliably while the system is +entering suspend. + + http://thread.gmane.org/gmane.linux.kernel/1122051 + +A lot of kudos to Thilo-Alexander for reporting this tricky issue and +painstaking testing. + +stable: This affects all kernels with cmwq, so all kernels since and + including v2.6.36 need this fix. + +Signed-off-by: Tejun Heo +Reported-by: Thilo-Alexander Ginkel +Tested-by: Thilo-Alexander Ginkel +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/workqueue.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -1283,8 +1283,14 @@ __acquires(&gcwq->lock) + return true; + spin_unlock_irq(&gcwq->lock); + +- /* CPU has come up inbetween, retry migration */ ++ /* ++ * We've raced with CPU hot[un]plug. Give it a breather ++ * and retry migration. cond_resched() is required here; ++ * otherwise, we might deadlock against cpu_stop trying to ++ * bring down the CPU on non-preemptive kernel. ++ */ + cpu_relax(); ++ cond_resched(); + } + } + diff --git a/queue-2.6.38/x86-amd-fix-apic-timer-erratum-400-affecting-k8-rev.a-e-processors.patch b/queue-2.6.38/x86-amd-fix-apic-timer-erratum-400-affecting-k8-rev.a-e-processors.patch new file mode 100644 index 00000000000..d318f09879f --- /dev/null +++ b/queue-2.6.38/x86-amd-fix-apic-timer-erratum-400-affecting-k8-rev.a-e-processors.patch @@ -0,0 +1,44 @@ +From e20a2d205c05cef6b5783df339a7d54adeb50962 Mon Sep 17 00:00:00 2001 +From: Boris Ostrovsky +Date: Fri, 29 Apr 2011 17:47:43 -0400 +Subject: x86, AMD: Fix APIC timer erratum 400 affecting K8 Rev.A-E processors + +From: Boris Ostrovsky + +commit e20a2d205c05cef6b5783df339a7d54adeb50962 upstream. + +Older AMD K8 processors (Revisions A-E) are affected by erratum +400 (APIC timer interrupts don't occur in C states greater than +C1). This, for example, means that X86_FEATURE_ARAT flag should +not be set for these parts. + +This addresses regression introduced by commit +b87cf80af3ba4b4c008b4face3c68d604e1715c6 ("x86, AMD: Set ARAT +feature on AMD processors") where the system may become +unresponsive until external interrupt (such as keyboard input) +occurs. This results, for example, in time not being reported +correctly, lack of progress on the system and other lockups. + +Reported-by: Joerg-Volker Peetz +Tested-by: Joerg-Volker Peetz +Acked-by: Borislav Petkov +Signed-off-by: Boris Ostrovsky +Link: http://lkml.kernel.org/r/1304113663-6586-1-git-send-email-ostr@amd64.org +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/cpu/amd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -681,7 +681,7 @@ cpu_dev_register(amd_cpu_dev); + */ + + const int amd_erratum_400[] = +- AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), ++ AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0x0f, 0x4, 0x2, 0xff, 0xf), + AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); + EXPORT_SYMBOL_GPL(amd_erratum_400); + -- 2.47.3