From: Greg Kroah-Hartman Date: Tue, 24 Aug 2010 17:40:51 +0000 (-0700) Subject: .35 patches X-Git-Tag: v2.6.32.21~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=97672ef66c6b12a61793ef0b3b461bb82de1d2e1;p=thirdparty%2Fkernel%2Fstable-queue.git .35 patches --- diff --git a/queue-2.6.35/alsa-intel8x0-mute-external-amplifier-by-default-for-thinkpad-x31.patch b/queue-2.6.35/alsa-intel8x0-mute-external-amplifier-by-default-for-thinkpad-x31.patch new file mode 100644 index 00000000000..c3547a153d4 --- /dev/null +++ b/queue-2.6.35/alsa-intel8x0-mute-external-amplifier-by-default-for-thinkpad-x31.patch @@ -0,0 +1,38 @@ +From 9c77b846ec8b4e0c7107dd7f820172462dc84a61 Mon Sep 17 00:00:00 2001 +From: Daniel T Chen +Date: Wed, 18 Aug 2010 19:33:43 -0400 +Subject: ALSA: intel8x0: Mute External Amplifier by default for ThinkPad X31 + +From: Daniel T Chen + +commit 9c77b846ec8b4e0c7107dd7f820172462dc84a61 upstream. + +BugLink: https://bugs.launchpad.net/bugs/619439 + +This ThinkPad model needs External Amplifier muted for audible playback, +so set the inv_eapd quirk for it. + +Reported-and-tested-by: Dennis Bell +Signed-off-by: Daniel T Chen +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/intel8x0.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/sound/pci/intel8x0.c ++++ b/sound/pci/intel8x0.c +@@ -1776,6 +1776,12 @@ static struct ac97_quirk ac97_quirks[] _ + }, + { + .subvendor = 0x1014, ++ .subdevice = 0x0534, ++ .name = "ThinkPad X31", ++ .type = AC97_TUNE_INV_EAPD ++ }, ++ { ++ .subvendor = 0x1014, + .subdevice = 0x1f00, + .name = "MS-9128", + .type = AC97_TUNE_ALC_JACK diff --git a/queue-2.6.35/dm-separate-device-deletion-from-dm_put.patch b/queue-2.6.35/dm-separate-device-deletion-from-dm_put.patch new file mode 100644 index 00000000000..fba0437fa75 --- /dev/null +++ b/queue-2.6.35/dm-separate-device-deletion-from-dm_put.patch @@ -0,0 +1,222 @@ +From 3f77316de0ec0fd208467fbee8d9edc70e2c73b2 Mon Sep 17 00:00:00 2001 +From: Kiyoshi Ueda +Date: Thu, 12 Aug 2010 04:13:56 +0100 +Subject: dm: separate device deletion from dm_put + +From: Kiyoshi Ueda + +commit 3f77316de0ec0fd208467fbee8d9edc70e2c73b2 upstream. + +This patch separates the device deletion code from dm_put() +to make sure the deletion happens in the process context. + +By this patch, device deletion always occurs in an ioctl (process) +context and dm_put() can be called in interrupt context. +As a result, the request-based dm's bad dm_put() usage pointed out +by Mikulas below disappears. + http://marc.info/?l=dm-devel&m=126699981019735&w=2 + +Without this patch, I confirmed there is a case to crash the system: + dm_put() => dm_table_destroy() => vfree() => BUG_ON(in_interrupt()) + +Some more backgrounds and details: +In request-based dm, a device opener can remove a mapped_device +while the last request is still completing, because bios in the last +request complete first and then the device opener can close and remove +the mapped_device before the last request completes: + CPU0 CPU1 + ================================================================= + <> + blk_end_request_all(clone_rq) + blk_update_request(clone_rq) + bio_endio(clone_bio) == end_clone_bio + blk_update_request(orig_rq) + bio_endio(orig_bio) + <> + dm_blk_close() + dev_remove() + dm_put(md) + <> + blk_finish_request(clone_rq) + .... + dm_end_request(clone_rq) + free_rq_clone(clone_rq) + blk_end_request_all(orig_rq) + rq_completed(md) + +So request-based dm used dm_get()/dm_put() to hold md for each I/O +until its request completion handling is fully done. +However, the final dm_put() can call the device deletion code which +must not be run in interrupt context and may cause kernel panic. + +To solve the problem, this patch moves the device deletion code, +dm_destroy(), to predetermined places that is actually deleting +the mapped_device in ioctl (process) context, and changes dm_put() +just to decrement the reference count of the mapped_device. +By this change, dm_put() can be used in any context and the symmetric +model below is introduced: + dm_create(): create a mapped_device + dm_destroy(): destroy a mapped_device + dm_get(): increment the reference count of a mapped_device + dm_put(): decrement the reference count of a mapped_device + +dm_destroy() waits for all references of the mapped_device to disappear, +then deletes the mapped_device. + +dm_destroy() uses active waiting with msleep(1), since deleting +the mapped_device isn't performance-critical task. +And since at this point, nobody opens the mapped_device and no new +reference will be taken, the pending counts are just for racing +completing activity and will eventually decrease to zero. + +For the unlikely case of the forced module unload, dm_destroy_immediate(), +which doesn't wait and forcibly deletes the mapped_device, is also +introduced and used in dm_hash_remove_all(). Otherwise, "rmmod -f" +may be stuck and never return. +And now, because the mapped_device is deleted at this point, subsequent +accesses to the mapped_device may cause NULL pointer references. + +Signed-off-by: Kiyoshi Ueda +Signed-off-by: Jun'ichi Nomura +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-ioctl.c | 6 ++++ + drivers/md/dm.c | 62 +++++++++++++++++++++++++++++++++++++------------- + drivers/md/dm.h | 5 ++++ + 3 files changed, 57 insertions(+), 16 deletions(-) + +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -274,6 +274,10 @@ retry: + up_write(&_hash_lock); + + dm_put(md); ++ if (likely(keep_open_devices)) ++ dm_destroy(md); ++ else ++ dm_destroy_immediate(md); + + /* + * Some mapped devices may be using other mapped +@@ -646,6 +650,7 @@ static int dev_create(struct dm_ioctl *p + r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); + if (r) { + dm_put(md); ++ dm_destroy(md); + return r; + } + +@@ -748,6 +753,7 @@ static int dev_remove(struct dm_ioctl *p + param->flags |= DM_UEVENT_GENERATED_FLAG; + + dm_put(md); ++ dm_destroy(md); + return 0; + } + +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include + +@@ -2176,6 +2177,7 @@ void dm_set_mdptr(struct mapped_device * + void dm_get(struct mapped_device *md) + { + atomic_inc(&md->holders); ++ BUG_ON(test_bit(DMF_FREEING, &md->flags)); + } + + const char *dm_device_name(struct mapped_device *md) +@@ -2184,27 +2186,55 @@ const char *dm_device_name(struct mapped + } + EXPORT_SYMBOL_GPL(dm_device_name); + +-void dm_put(struct mapped_device *md) ++static void __dm_destroy(struct mapped_device *md, bool wait) + { + struct dm_table *map; + +- BUG_ON(test_bit(DMF_FREEING, &md->flags)); ++ might_sleep(); + +- if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { +- map = dm_get_live_table(md); +- idr_replace(&_minor_idr, MINOR_ALLOCED, +- MINOR(disk_devt(dm_disk(md)))); +- set_bit(DMF_FREEING, &md->flags); +- spin_unlock(&_minor_lock); +- if (!dm_suspended_md(md)) { +- dm_table_presuspend_targets(map); +- dm_table_postsuspend_targets(map); +- } +- dm_sysfs_exit(md); +- dm_table_put(map); +- dm_table_destroy(__unbind(md)); +- free_dev(md); ++ spin_lock(&_minor_lock); ++ map = dm_get_live_table(md); ++ idr_replace(&_minor_idr, MINOR_ALLOCED, MINOR(disk_devt(dm_disk(md)))); ++ set_bit(DMF_FREEING, &md->flags); ++ spin_unlock(&_minor_lock); ++ ++ if (!dm_suspended_md(md)) { ++ dm_table_presuspend_targets(map); ++ dm_table_postsuspend_targets(map); + } ++ ++ /* ++ * Rare, but there may be I/O requests still going to complete, ++ * for example. Wait for all references to disappear. ++ * No one should increment the reference count of the mapped_device, ++ * after the mapped_device state becomes DMF_FREEING. ++ */ ++ if (wait) ++ while (atomic_read(&md->holders)) ++ msleep(1); ++ else if (atomic_read(&md->holders)) ++ DMWARN("%s: Forcibly removing mapped_device still in use! (%d users)", ++ dm_device_name(md), atomic_read(&md->holders)); ++ ++ dm_sysfs_exit(md); ++ dm_table_put(map); ++ dm_table_destroy(__unbind(md)); ++ free_dev(md); ++} ++ ++void dm_destroy(struct mapped_device *md) ++{ ++ __dm_destroy(md, true); ++} ++ ++void dm_destroy_immediate(struct mapped_device *md) ++{ ++ __dm_destroy(md, false); ++} ++ ++void dm_put(struct mapped_device *md) ++{ ++ atomic_dec(&md->holders); + } + EXPORT_SYMBOL_GPL(dm_put); + +--- a/drivers/md/dm.h ++++ b/drivers/md/dm.h +@@ -122,6 +122,11 @@ void dm_linear_exit(void); + int dm_stripe_init(void); + void dm_stripe_exit(void); + ++/* ++ * mapped_device operations ++ */ ++void dm_destroy(struct mapped_device *md); ++void dm_destroy_immediate(struct mapped_device *md); + int dm_open_count(struct mapped_device *md); + int dm_lock_for_deletion(struct mapped_device *md); + diff --git a/queue-2.6.35/e1000e-disable-aspm-l1-on-82573.patch b/queue-2.6.35/e1000e-disable-aspm-l1-on-82573.patch new file mode 100644 index 00000000000..e76cb8cd4bd --- /dev/null +++ b/queue-2.6.35/e1000e-disable-aspm-l1-on-82573.patch @@ -0,0 +1,35 @@ +From 19833b5dffe2f2e92a1b377f9aae9d5f32239512 Mon Sep 17 00:00:00 2001 +From: Bruce Allan +Date: Thu, 19 Aug 2010 15:48:30 -0700 +Subject: e1000e: disable ASPM L1 on 82573 + +From: Bruce Allan + +commit 19833b5dffe2f2e92a1b377f9aae9d5f32239512 upstream. + +On the e1000-devel mailing list, Nils Faerber reported latency issues with +the 82573 LOM on a ThinkPad X60. It was found to be caused by ASPM L1; +disabling it resolves the latency. The issue is present in kernels back +to 2.6.34 and possibly 2.6.33. + + +Reported-by: Nils Faerber +Signed-off-by: Bruce Allan +Signed-off-by: Jeff Kirsher +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/e1000e/82571.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/e1000e/82571.c ++++ b/drivers/net/e1000e/82571.c +@@ -1833,6 +1833,7 @@ struct e1000_info e1000_82573_info = { + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_HAS_AMT + | FLAG_HAS_SWSM_ON_LOAD, ++ .flags2 = FLAG2_DISABLE_ASPM_L1, + .pba = 20, + .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, + .get_variants = e1000_get_variants_82571, diff --git a/queue-2.6.35/e1000e-don-t-check-for-alternate-mac-addr-on-parts-that-don-t-support-it.patch b/queue-2.6.35/e1000e-don-t-check-for-alternate-mac-addr-on-parts-that-don-t-support-it.patch new file mode 100644 index 00000000000..fb30aa42f57 --- /dev/null +++ b/queue-2.6.35/e1000e-don-t-check-for-alternate-mac-addr-on-parts-that-don-t-support-it.patch @@ -0,0 +1,118 @@ +From 1aef70ef125165e0114a8e475636eff242a52030 Mon Sep 17 00:00:00 2001 +From: Bruce Allan +Date: Thu, 19 Aug 2010 15:48:52 -0700 +Subject: e1000e: don't check for alternate MAC addr on parts that don't support it + +From: Bruce Allan + +commit 1aef70ef125165e0114a8e475636eff242a52030 upstream. + +From: Bruce Allan + +The alternate MAC address feature is only supported by 80003ES2LAN and +82571 LOMs as well as a couple 82571 mezzanine cards. Checking for an +alternate MAC address on other parts can fail leading to the driver not +able to load. This patch limits the check for an alternate MAC address +to be done only for parts that support the feature. + +This issue has been around since support for the feature was introduced +to the e1000e driver in 2.6.34. + +Signed-off-by: Bruce Allan +Reported-by: Fabio Varesano +Signed-off-by: Jeff Kirsher +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/e1000e/82571.c | 30 +++++++++++++++++------------- + drivers/net/e1000e/defines.h | 4 ++++ + drivers/net/e1000e/lib.c | 10 ++++++++++ + 3 files changed, 31 insertions(+), 13 deletions(-) + +--- a/drivers/net/e1000e/82571.c ++++ b/drivers/net/e1000e/82571.c +@@ -936,12 +936,14 @@ static s32 e1000_reset_hw_82571(struct e + ew32(IMC, 0xffffffff); + icr = er32(ICR); + +- /* Install any alternate MAC address into RAR0 */ +- ret_val = e1000_check_alt_mac_addr_generic(hw); +- if (ret_val) +- return ret_val; ++ if (hw->mac.type == e1000_82571) { ++ /* Install any alternate MAC address into RAR0 */ ++ ret_val = e1000_check_alt_mac_addr_generic(hw); ++ if (ret_val) ++ return ret_val; + +- e1000e_set_laa_state_82571(hw, true); ++ e1000e_set_laa_state_82571(hw, true); ++ } + + /* Reinitialize the 82571 serdes link state machine */ + if (hw->phy.media_type == e1000_media_type_internal_serdes) +@@ -1618,14 +1620,16 @@ static s32 e1000_read_mac_addr_82571(str + { + s32 ret_val = 0; + +- /* +- * If there's an alternate MAC address place it in RAR0 +- * so that it will override the Si installed default perm +- * address. +- */ +- ret_val = e1000_check_alt_mac_addr_generic(hw); +- if (ret_val) +- goto out; ++ if (hw->mac.type == e1000_82571) { ++ /* ++ * If there's an alternate MAC address place it in RAR0 ++ * so that it will override the Si installed default perm ++ * address. ++ */ ++ ret_val = e1000_check_alt_mac_addr_generic(hw); ++ if (ret_val) ++ goto out; ++ } + + ret_val = e1000_read_mac_addr_generic(hw); + +--- a/drivers/net/e1000e/defines.h ++++ b/drivers/net/e1000e/defines.h +@@ -620,6 +620,7 @@ + #define E1000_FLASH_UPDATES 2000 + + /* NVM Word Offsets */ ++#define NVM_COMPAT 0x0003 + #define NVM_ID_LED_SETTINGS 0x0004 + #define NVM_INIT_CONTROL2_REG 0x000F + #define NVM_INIT_CONTROL3_PORT_B 0x0014 +@@ -642,6 +643,9 @@ + /* Mask bits for fields in Word 0x1a of the NVM */ + #define NVM_WORD1A_ASPM_MASK 0x000C + ++/* Mask bits for fields in Word 0x03 of the EEPROM */ ++#define NVM_COMPAT_LOM 0x0800 ++ + /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ + #define NVM_SUM 0xBABA + +--- a/drivers/net/e1000e/lib.c ++++ b/drivers/net/e1000e/lib.c +@@ -183,6 +183,16 @@ s32 e1000_check_alt_mac_addr_generic(str + u16 offset, nvm_alt_mac_addr_offset, nvm_data; + u8 alt_mac_addr[ETH_ALEN]; + ++ ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data); ++ if (ret_val) ++ goto out; ++ ++ /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */ ++ if (!((nvm_data & NVM_COMPAT_LOM) || ++ (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) || ++ (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD))) ++ goto out; ++ + ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, + &nvm_alt_mac_addr_offset); + if (ret_val) { diff --git a/queue-2.6.35/fixes-for-using-make-3.82.patch b/queue-2.6.35/fixes-for-using-make-3.82.patch new file mode 100644 index 00000000000..9197677094f --- /dev/null +++ b/queue-2.6.35/fixes-for-using-make-3.82.patch @@ -0,0 +1,48 @@ +From 3c955b407a084810f57260d61548cc92c14bc627 Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Mon, 16 Aug 2010 11:58:58 +0100 +Subject: fixes for using make 3.82 + +From: Jan Beulich + +commit 3c955b407a084810f57260d61548cc92c14bc627 upstream. + +It doesn't like pattern and explicit rules to be on the same line, +and it seems to be more picky when matching file (or really directory) +names with different numbers of trailing slashes. + +Signed-off-by: Jan Beulich +Acked-by: Sam Ravnborg +Andrew Benton +Signed-off-by: Michal Marek +Signed-off-by: Greg Kroah-Hartman + +--- + firmware/Makefile | 2 +- + scripts/mkmakefile | 4 +++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -142,7 +142,7 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin + fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-) + + # Directories which we _might_ need to create, so we have a rule for them. +-firmware-dirs := $(sort $(patsubst %,$(objtree)/$(obj)/%/,$(dir $(fw-external-y) $(fw-shipped-all)))) ++firmware-dirs := $(sort $(addprefix $(objtree)/$(obj)/,$(dir $(fw-external-y) $(fw-shipped-all)))) + + quiet_cmd_mkdir = MKDIR $(patsubst $(objtree)/%,%,$@) + cmd_mkdir = mkdir -p $@ +--- a/scripts/mkmakefile ++++ b/scripts/mkmakefile +@@ -44,7 +44,9 @@ all: + + Makefile:; + +-\$(all) %/: all ++\$(all): all + @: + ++%/: all ++ @: + EOF diff --git a/queue-2.6.35/iwlagn-fix-rts-cts-protection.patch b/queue-2.6.35/iwlagn-fix-rts-cts-protection.patch new file mode 100644 index 00000000000..9982c28b654 --- /dev/null +++ b/queue-2.6.35/iwlagn-fix-rts-cts-protection.patch @@ -0,0 +1,332 @@ +From 94597ab23ea10b3bdcba534be00a9f7b35791c07 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 9 Aug 2010 10:57:02 -0700 +Subject: iwlagn: fix rts cts protection + +From: Johannes Berg + +This is a backport of mainline commit +94597ab23ea10b3bdcba534be00a9f7b35791c07. +I removed the variable renamings from it +and made it apply on 2.6.35. It now also +incorporates some changes from commit +cfecc6b492162fb49209a83dc207f182b87ea27a +since those were required as well. +commit 94597ab23ea10b3bdcba534be00a9f7b35791c07 upstream. + +Currently the driver will try to protect all frames, +which leads to a lot of odd things like sending an +RTS with a zeroed RA before multicast frames, which +is clearly bogus. + +In order to fix all of this, we need to take a step +back and see what we need to achieve: + * we need RTS/CTS protection if requested by + the AP for the BSS, mac80211 tells us this + * in that case, CTS-to-self should only be + enabled when mac80211 tells us + * additionally, as a hardware workaround, on + some devices we have to protect aggregated + frames with RTS + +To achieve the first two items, set up the RXON +accordingly and set the protection required flag +in the transmit command when mac80211 requests +protection for the frame. + +To achieve the last item, set the rate-control +RTS-requested flag for all stations that we have +aggregation sessions with, and set the protection +required flag when sending aggregated frames (on +those devices where this is required). + +Since otherwise bugs can occur, do not allow the +user to override the RTS-for-aggregation setting +from sysfs any more. + +Finally, also clean up the way all these flags get +set in the driver and move everything into the +device-specific functions. + +Signed-off-by: Johannes Berg +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/net/wireless/iwlwifi/iwl-3945.c | 16 ----------- + drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 17 ++++++++++-- + drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 17 +++--------- + drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 20 -------------- + drivers/net/wireless/iwlwifi/iwl-agn.c | 38 +++++++++++++++++++++------- + drivers/net/wireless/iwlwifi/iwl-core.c | 25 ++++++++++++++++-- + drivers/net/wireless/iwlwifi/iwl-core.h | 10 ++++--- + drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 --- + 8 files changed, 79 insertions(+), 69 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-3945.c ++++ b/drivers/net/wireless/iwlwifi/iwl-3945.c +@@ -915,22 +915,6 @@ void iwl3945_hw_build_tx_cmd_rate(struct + rts_retry_limit = data_retry_limit; + tx_cmd->rts_retry_limit = rts_retry_limit; + +- if (ieee80211_is_mgmt(fc)) { +- switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { +- case cpu_to_le16(IEEE80211_STYPE_AUTH): +- case cpu_to_le16(IEEE80211_STYPE_DEAUTH): +- case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): +- case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): +- if (tx_flags & TX_CMD_FLG_RTS_MSK) { +- tx_flags &= ~TX_CMD_FLG_RTS_MSK; +- tx_flags |= TX_CMD_FLG_CTS_MSK; +- } +- break; +- default: +- break; +- } +- } +- + tx_cmd->rate = rate; + tx_cmd->tx_flags = tx_flags; + +--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +@@ -209,10 +209,21 @@ static void iwlagn_chain_noise_reset(str + } + } + +-static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, +- __le32 *tx_flags) ++static void iwlagn_rts_tx_cmd_flag(struct iwl_priv *priv, ++ struct ieee80211_tx_info *info, ++ __le16 fc, __le32 *tx_flags) + { +- *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; ++ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || ++ info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { ++ *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; ++ return; ++ } ++ ++ if (priv->cfg->use_rts_for_ht && ++ info->flags & IEEE80211_TX_CTL_AMPDU) { ++ *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; ++ return; ++ } + } + + /* Calc max signal level (dBm) among 3 possible receivers */ +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +@@ -325,18 +325,11 @@ static void rs_tl_turn_on_agg(struct iwl + struct iwl_lq_sta *lq_data, + struct ieee80211_sta *sta) + { +- if ((tid < TID_MAX_LOAD_COUNT) && +- !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) { +- if (priv->cfg->use_rts_for_ht) { +- /* +- * switch to RTS/CTS if it is the prefer protection +- * method for HT traffic +- */ +- IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); +- priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; +- iwlcore_commit_rxon(priv); +- } +- } ++ if (tid < TID_MAX_LOAD_COUNT) ++ rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); ++ else ++ IWL_ERR(priv, "tid exceeds max load count: %d/%d\n", ++ tid, TID_MAX_LOAD_COUNT); + } + + static inline int get_num_of_ant_from_rate(u32 rate_n_flags) +--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +@@ -376,10 +376,7 @@ static void iwlagn_tx_cmd_build_basic(st + tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + } + +- priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); +- +- if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) +- tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; ++ priv->cfg->ops->utils->rts_tx_cmd_flag(priv, info, fc, &tx_flags); + + tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); + if (ieee80211_is_mgmt(fc)) { +@@ -453,21 +450,6 @@ static void iwlagn_tx_cmd_build_rate(str + if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) + rate_flags |= RATE_MCS_CCK_MSK; + +- /* Set up RTS and CTS flags for certain packets */ +- switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { +- case cpu_to_le16(IEEE80211_STYPE_AUTH): +- case cpu_to_le16(IEEE80211_STYPE_DEAUTH): +- case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): +- case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): +- if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { +- tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; +- tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; +- } +- break; +- default: +- break; +- } +- + /* Set up antennas */ + priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); + rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -200,13 +200,6 @@ int iwl_commit_rxon(struct iwl_priv *pri + + priv->start_calib = 0; + if (new_assoc) { +- /* +- * allow CTS-to-self if possible for new association. +- * this is relevant only for 5000 series and up, +- * but will not damage 4965 +- */ +- priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; +- + /* Apply the new configuration + * RXON assoc doesn't clear the station table in uCode, + */ +@@ -3336,13 +3329,40 @@ static int iwl_mac_ampdu_action(struct i + IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", + priv->_agn.agg_tids_count); + } ++ if (priv->cfg->use_rts_for_ht) { ++ struct iwl_station_priv *sta_priv = ++ (void *) sta->drv_priv; ++ /* ++ * switch off RTS/CTS if it was previously enabled ++ */ ++ ++ sta_priv->lq_sta.lq.general_params.flags &= ++ ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; ++ iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, ++ CMD_ASYNC, false); ++ } ++ break; + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return 0; + else + return ret; + case IEEE80211_AMPDU_TX_OPERATIONAL: +- /* do nothing */ +- return -EOPNOTSUPP; ++ if (priv->cfg->use_rts_for_ht) { ++ struct iwl_station_priv *sta_priv = ++ (void *) sta->drv_priv; ++ ++ /* ++ * switch to RTS/CTS if it is the prefer protection ++ * method for HT traffic ++ */ ++ ++ sta_priv->lq_sta.lq.general_params.flags |= ++ LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; ++ iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, ++ CMD_ASYNC, false); ++ } ++ ret = 0; ++ break; + default: + IWL_DEBUG_HT(priv, "unknown\n"); + return -EINVAL; +--- a/drivers/net/wireless/iwlwifi/iwl-core.c ++++ b/drivers/net/wireless/iwlwifi/iwl-core.c +@@ -403,19 +403,36 @@ EXPORT_SYMBOL(iwlcore_free_geos); + * iwlcore_rts_tx_cmd_flag: Set rts/cts. 3945 and 4965 only share this + * function. + */ +-void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, +- __le32 *tx_flags) ++void iwlcore_rts_tx_cmd_flag(struct iwl_priv *priv, ++ struct ieee80211_tx_info *info, ++ __le16 fc, __le32 *tx_flags) + { + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { + *tx_flags |= TX_CMD_FLG_RTS_MSK; + *tx_flags &= ~TX_CMD_FLG_CTS_MSK; ++ *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; ++ ++ if (!ieee80211_is_mgmt(fc)) ++ return; ++ ++ switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { ++ case cpu_to_le16(IEEE80211_STYPE_AUTH): ++ case cpu_to_le16(IEEE80211_STYPE_DEAUTH): ++ case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): ++ case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): ++ *tx_flags &= ~TX_CMD_FLG_RTS_MSK; ++ *tx_flags |= TX_CMD_FLG_CTS_MSK; ++ break; ++ } + } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + *tx_flags &= ~TX_CMD_FLG_RTS_MSK; + *tx_flags |= TX_CMD_FLG_CTS_MSK; ++ *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; + } + } + EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag); + ++ + static bool is_single_rx_stream(struct iwl_priv *priv) + { + return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC || +@@ -1936,6 +1953,10 @@ void iwl_bss_info_changed(struct ieee802 + priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; ++ if (bss_conf->use_cts_prot) ++ priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; ++ else ++ priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; + } + + if (changes & BSS_CHANGED_BASIC_RATES) { +--- a/drivers/net/wireless/iwlwifi/iwl-core.h ++++ b/drivers/net/wireless/iwlwifi/iwl-core.h +@@ -102,8 +102,9 @@ struct iwl_hcmd_utils_ops { + u32 min_average_noise, + u8 default_chain); + void (*chain_noise_reset)(struct iwl_priv *priv); +- void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, +- __le32 *tx_flags); ++ void (*rts_tx_cmd_flag)(struct iwl_priv *priv, ++ struct ieee80211_tx_info *info, ++ __le16 fc, __le32 *tx_flags); + int (*calc_rssi)(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp); + void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); +@@ -375,8 +376,9 @@ void iwl_config_ap(struct iwl_priv *priv + void iwl_mac_reset_tsf(struct ieee80211_hw *hw); + int iwl_alloc_txq_mem(struct iwl_priv *priv); + void iwl_free_txq_mem(struct iwl_priv *priv); +-void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, +- __le32 *tx_flags); ++void iwlcore_rts_tx_cmd_flag(struct iwl_priv *priv, ++ struct ieee80211_tx_info *info, ++ __le16 fc, __le32 *tx_flags); + #ifdef CONFIG_IWLWIFI_DEBUGFS + int iwl_alloc_traffic_mem(struct iwl_priv *priv); + void iwl_free_traffic_mem(struct iwl_priv *priv); +--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c ++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c +@@ -434,10 +434,7 @@ static void iwl3945_build_tx_cmd_basic(s + tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + } + +- priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); +- +- if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) +- tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; ++ priv->cfg->ops->utils->rts_tx_cmd_flag(priv, info, fc, &tx_flags); + + tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); + if (ieee80211_is_mgmt(fc)) { diff --git a/queue-2.6.35/iwlwifi-fix-3945-filter-flags.patch b/queue-2.6.35/iwlwifi-fix-3945-filter-flags.patch new file mode 100644 index 00000000000..4466ae42912 --- /dev/null +++ b/queue-2.6.35/iwlwifi-fix-3945-filter-flags.patch @@ -0,0 +1,231 @@ +From 8b8ab9d5e352aae0dcae53c657b25ab61bb73f0f Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 17 Aug 2010 11:24:01 +0200 +Subject: iwlwifi: fix 3945 filter flags + +From: Johannes Berg + +commit 8b8ab9d5e352aae0dcae53c657b25ab61bb73f0f upstream. + +Applying the filter flags directly as done since + +commit 3474ad635db371b0d8d0ee40086f15d223d5b6a4 +Author: Johannes Berg +Date: Thu Apr 29 04:43:05 2010 -0700 + + iwlwifi: apply filter flags directly + +broke 3945 under some unknown circumstances, as +reported by Alex. + +Since I want to keep the direct application of +filter flags on iwlagn, duplicate the code into +both 3945 and agn and remove committing the +RXON that broke things from the 3945 version. + +Reported-by: Alex Romosan +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/iwl-agn.c | 45 ++++++++++++++++++++++++ + drivers/net/wireless/iwlwifi/iwl-core.c | 45 ------------------------ + drivers/net/wireless/iwlwifi/iwl-core.h | 3 - + drivers/net/wireless/iwlwifi/iwl3945-base.c | 51 +++++++++++++++++++++++++++- + 4 files changed, 94 insertions(+), 50 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -3443,6 +3443,49 @@ static int iwlagn_mac_sta_add(struct iee + return 0; + } + ++static void iwlagn_configure_filter(struct ieee80211_hw *hw, ++ unsigned int changed_flags, ++ unsigned int *total_flags, ++ u64 multicast) ++{ ++ struct iwl_priv *priv = hw->priv; ++ __le32 filter_or = 0, filter_nand = 0; ++ ++#define CHK(test, flag) do { \ ++ if (*total_flags & (test)) \ ++ filter_or |= (flag); \ ++ else \ ++ filter_nand |= (flag); \ ++ } while (0) ++ ++ IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", ++ changed_flags, *total_flags); ++ ++ CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); ++ CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); ++ CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); ++ ++#undef CHK ++ ++ mutex_lock(&priv->mutex); ++ ++ priv->staging_rxon.filter_flags &= ~filter_nand; ++ priv->staging_rxon.filter_flags |= filter_or; ++ ++ iwlcore_commit_rxon(priv); ++ ++ mutex_unlock(&priv->mutex); ++ ++ /* ++ * Receiving all multicast frames is always enabled by the ++ * default flags setup in iwl_connection_init_rx_config() ++ * since we currently do not support programming multicast ++ * filters into the device. ++ */ ++ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | ++ FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; ++} ++ + /***************************************************************************** + * + * driver setup and teardown +@@ -3603,7 +3646,7 @@ static struct ieee80211_ops iwl_hw_ops = + .add_interface = iwl_mac_add_interface, + .remove_interface = iwl_mac_remove_interface, + .config = iwl_mac_config, +- .configure_filter = iwl_configure_filter, ++ .configure_filter = iwlagn_configure_filter, + .set_key = iwl_mac_set_key, + .update_tkip_key = iwl_mac_update_tkip_key, + .conf_tx = iwl_mac_conf_tx, +--- a/drivers/net/wireless/iwlwifi/iwl-core.c ++++ b/drivers/net/wireless/iwlwifi/iwl-core.c +@@ -1311,51 +1311,6 @@ out: + EXPORT_SYMBOL(iwl_apm_init); + + +- +-void iwl_configure_filter(struct ieee80211_hw *hw, +- unsigned int changed_flags, +- unsigned int *total_flags, +- u64 multicast) +-{ +- struct iwl_priv *priv = hw->priv; +- __le32 filter_or = 0, filter_nand = 0; +- +-#define CHK(test, flag) do { \ +- if (*total_flags & (test)) \ +- filter_or |= (flag); \ +- else \ +- filter_nand |= (flag); \ +- } while (0) +- +- IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", +- changed_flags, *total_flags); +- +- CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); +- CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); +- CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); +- +-#undef CHK +- +- mutex_lock(&priv->mutex); +- +- priv->staging_rxon.filter_flags &= ~filter_nand; +- priv->staging_rxon.filter_flags |= filter_or; +- +- iwlcore_commit_rxon(priv); +- +- mutex_unlock(&priv->mutex); +- +- /* +- * Receiving all multicast frames is always enabled by the +- * default flags setup in iwl_connection_init_rx_config() +- * since we currently do not support programming multicast +- * filters into the device. +- */ +- *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | +- FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; +-} +-EXPORT_SYMBOL(iwl_configure_filter); +- + int iwl_set_hw_params(struct iwl_priv *priv) + { + priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; +--- a/drivers/net/wireless/iwlwifi/iwl-core.h ++++ b/drivers/net/wireless/iwlwifi/iwl-core.h +@@ -356,9 +356,6 @@ int iwl_set_decrypted_flag(struct iwl_pr + u32 decrypt_res, + struct ieee80211_rx_status *stats); + void iwl_irq_handle_error(struct iwl_priv *priv); +-void iwl_configure_filter(struct ieee80211_hw *hw, +- unsigned int changed_flags, +- unsigned int *total_flags, u64 multicast); + int iwl_set_hw_params(struct iwl_priv *priv); + void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); + void iwl_bss_info_changed(struct ieee80211_hw *hw, +--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c ++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c +@@ -3462,6 +3462,55 @@ static int iwl3945_mac_sta_add(struct ie + + return 0; + } ++ ++static void iwl3945_configure_filter(struct ieee80211_hw *hw, ++ unsigned int changed_flags, ++ unsigned int *total_flags, ++ u64 multicast) ++{ ++ struct iwl_priv *priv = hw->priv; ++ __le32 filter_or = 0, filter_nand = 0; ++ ++#define CHK(test, flag) do { \ ++ if (*total_flags & (test)) \ ++ filter_or |= (flag); \ ++ else \ ++ filter_nand |= (flag); \ ++ } while (0) ++ ++ IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", ++ changed_flags, *total_flags); ++ ++ CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); ++ CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); ++ CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); ++ ++#undef CHK ++ ++ mutex_lock(&priv->mutex); ++ ++ priv->staging_rxon.filter_flags &= ~filter_nand; ++ priv->staging_rxon.filter_flags |= filter_or; ++ ++ /* ++ * Committing directly here breaks for some reason, ++ * but we'll eventually commit the filter flags ++ * change anyway. ++ */ ++ ++ mutex_unlock(&priv->mutex); ++ ++ /* ++ * Receiving all multicast frames is always enabled by the ++ * default flags setup in iwl_connection_init_rx_config() ++ * since we currently do not support programming multicast ++ * filters into the device. ++ */ ++ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | ++ FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; ++} ++ ++ + /***************************************************************************** + * + * sysfs attributes +@@ -3867,7 +3916,7 @@ static struct ieee80211_ops iwl3945_hw_o + .add_interface = iwl_mac_add_interface, + .remove_interface = iwl_mac_remove_interface, + .config = iwl_mac_config, +- .configure_filter = iwl_configure_filter, ++ .configure_filter = iwl3945_configure_filter, + .set_key = iwl3945_mac_set_key, + .conf_tx = iwl_mac_conf_tx, + .reset_tsf = iwl_mac_reset_tsf, diff --git a/queue-2.6.35/netlink-fix-compat-recvmsg.patch b/queue-2.6.35/netlink-fix-compat-recvmsg.patch new file mode 100644 index 00000000000..bc339cae245 --- /dev/null +++ b/queue-2.6.35/netlink-fix-compat-recvmsg.patch @@ -0,0 +1,130 @@ +From 68d6ac6d2740b6a55f3ae92a4e0be6d881904b32 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Sun, 15 Aug 2010 21:20:44 +0000 +Subject: netlink: fix compat recvmsg + +From: Johannes Berg + +commit 68d6ac6d2740b6a55f3ae92a4e0be6d881904b32 upstream. + +Since +commit 1dacc76d0014a034b8aca14237c127d7c19d7726 +Author: Johannes Berg +Date: Wed Jul 1 11:26:02 2009 +0000 + + net/compat/wext: send different messages to compat tasks + +we had a race condition when setting and then +restoring frag_list. Eric attempted to fix it, +but the fix created even worse problems. + +However, the original motivation I had when I +added the code that turned out to be racy is +no longer clear to me, since we only copy up +to skb->len to userspace, which doesn't include +the frag_list length. As a result, not doing +any frag_list clearing and restoring avoids +the race condition, while not introducing any +other problems. + +Additionally, while preparing this patch I found +that since none of the remaining netlink code is +really aware of the frag_list, we need to use the +original skb's information for packet information +and credentials. This fixes, for example, the +group information received by compat tasks. + +Cc: Eric Dumazet +Signed-off-by: Johannes Berg +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/netlink/af_netlink.c | 46 ++++++++++++++++------------------------------ + 1 file changed, 16 insertions(+), 30 deletions(-) + +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1400,7 +1400,7 @@ static int netlink_recvmsg(struct kiocb + struct netlink_sock *nlk = nlk_sk(sk); + int noblock = flags&MSG_DONTWAIT; + size_t copied; +- struct sk_buff *skb, *frag __maybe_unused = NULL; ++ struct sk_buff *skb, *data_skb; + int err; + + if (flags&MSG_OOB) +@@ -1412,45 +1412,35 @@ static int netlink_recvmsg(struct kiocb + if (skb == NULL) + goto out; + ++ data_skb = skb; ++ + #ifdef CONFIG_COMPAT_NETLINK_MESSAGES + if (unlikely(skb_shinfo(skb)->frag_list)) { +- bool need_compat = !!(flags & MSG_CMSG_COMPAT); +- + /* +- * If this skb has a frag_list, then here that means that +- * we will have to use the frag_list skb for compat tasks +- * and the regular skb for non-compat tasks. ++ * If this skb has a frag_list, then here that means that we ++ * will have to use the frag_list skb's data for compat tasks ++ * and the regular skb's data for normal (non-compat) tasks. + * +- * The skb might (and likely will) be cloned, so we can't +- * just reset frag_list and go on with things -- we need to +- * keep that. For the compat case that's easy -- simply get +- * a reference to the compat skb and free the regular one +- * including the frag. For the non-compat case, we need to +- * avoid sending the frag to the user -- so assign NULL but +- * restore it below before freeing the skb. ++ * If we need to send the compat skb, assign it to the ++ * 'data_skb' variable so that it will be used below for data ++ * copying. We keep 'skb' for everything else, including ++ * freeing both later. + */ +- if (need_compat) { +- struct sk_buff *compskb = skb_shinfo(skb)->frag_list; +- skb_get(compskb); +- kfree_skb(skb); +- skb = compskb; +- } else { +- frag = skb_shinfo(skb)->frag_list; +- skb_shinfo(skb)->frag_list = NULL; +- } ++ if (flags & MSG_CMSG_COMPAT) ++ data_skb = skb_shinfo(skb)->frag_list; + } + #endif + + msg->msg_namelen = 0; + +- copied = skb->len; ++ copied = data_skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; + copied = len; + } + +- skb_reset_transport_header(skb); +- err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); ++ skb_reset_transport_header(data_skb); ++ err = skb_copy_datagram_iovec(data_skb, 0, msg->msg_iov, copied); + + if (msg->msg_name) { + struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name; +@@ -1470,11 +1460,7 @@ static int netlink_recvmsg(struct kiocb + } + siocb->scm->creds = *NETLINK_CREDS(skb); + if (flags & MSG_TRUNC) +- copied = skb->len; +- +-#ifdef CONFIG_COMPAT_NETLINK_MESSAGES +- skb_shinfo(skb)->frag_list = frag; +-#endif ++ copied = data_skb->len; + + skb_free_datagram(sk, skb); + diff --git a/queue-2.6.35/series b/queue-2.6.35/series index efb9893f295..97310cd346f 100644 --- a/queue-2.6.35/series +++ b/queue-2.6.35/series @@ -80,3 +80,11 @@ drm-agp-i915-trim-stolen-space-to-32m.patch timekeeping-fix-overflow-in-rawtime-tv_nsec-on-32-bit-archs.patch time-workaround-gcc-loop-optimization-that-causes-64bit-div-errors.patch can-raw-fix-skb_orphan_try-handling.patch +iwlagn-fix-rts-cts-protection.patch +dm-separate-device-deletion-from-dm_put.patch +e1000e-disable-aspm-l1-on-82573.patch +e1000e-don-t-check-for-alternate-mac-addr-on-parts-that-don-t-support-it.patch +iwlwifi-fix-3945-filter-flags.patch +fixes-for-using-make-3.82.patch +alsa-intel8x0-mute-external-amplifier-by-default-for-thinkpad-x31.patch +netlink-fix-compat-recvmsg.patch