From 0ad8acaf434d360ad99813d981a68e605d6c8179 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 24 Mar 2009 21:21:08 -0400 Subject: cfg80211: fix NULL pointer deference in reg_device_remove() We won't ever get here as regulatory_hint_core() can only fail on -ENOMEM and in that case we don't initialize cfg80211 but this is technically correct code. This is actually good for stable, where we don't check for -ENOMEM failure on __regulatory_hint()'s failure. Cc: stable@kernel.org Reported-by: Quentin Armitage Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 6327e1617acb..6c1993d99902 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2095,11 +2095,12 @@ int set_regdom(const struct ieee80211_regdomain *rd) /* Caller must hold cfg80211_mutex */ void reg_device_remove(struct wiphy *wiphy) { - struct wiphy *request_wiphy; + struct wiphy *request_wiphy = NULL; assert_cfg80211_lock(); - request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); + if (last_request) + request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); kfree(wiphy->regd); if (!last_request || !request_wiphy) -- cgit v1.2.3 From b3631286aca3f54427ca0eb950981e9753866f6c Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 25 Mar 2009 18:10:18 +0530 Subject: mac80211: Fix bug in getting rx status for frames pending in reorder buffer Currently rx status for frames which are completed from reorder buffer is taken from it's cb area which is not always right, cb is not holding the rx status when driver uses mac80211's non-irq rx handler to pass it's received frames. This results in dropping almost all frames from reorder buffer when security is enabled by doing double decryption (first in hw, second in sw because of wrong rx status). This patch copies rx status into cb area before the frame is put into reorder buffer. After this patch, there is a significant improvement in throughput with ath9k + WPA2(AES). Signed-off-by: Vasanthakumar Thiagarajan Acked-by: Johannes Berg Cc: stable@kernel.org Signed-off-by: John W. Linville --- net/mac80211/rx.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 64ebe664effc..5fa7aedd90ed 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -29,6 +29,7 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, struct tid_ampdu_rx *tid_agg_rx, struct sk_buff *skb, + struct ieee80211_rx_status *status, u16 mpdu_seq_num, int bar_req); /* @@ -1688,7 +1689,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) /* manage reordering buffer according to requested */ /* sequence number */ rcu_read_lock(); - ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, + ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, NULL, start_seq_num, 1); rcu_read_unlock(); return RX_DROP_UNUSABLE; @@ -2293,6 +2294,7 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, struct tid_ampdu_rx *tid_agg_rx, struct sk_buff *skb, + struct ieee80211_rx_status *rxstatus, u16 mpdu_seq_num, int bar_req) { @@ -2374,6 +2376,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, /* put the frame in the reordering buffer */ tid_agg_rx->reorder_buf[index] = skb; + memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, + sizeof(*rxstatus)); tid_agg_rx->stored_mpdu_num++; /* release the buffer until next missing frame */ index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) @@ -2399,7 +2403,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, } static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, - struct sk_buff *skb) + struct sk_buff *skb, + struct ieee80211_rx_status *status) { struct ieee80211_hw *hw = &local->hw; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; @@ -2448,7 +2453,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, /* according to mpdu sequence number deal with reordering buffer */ mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; - ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, + ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, status, mpdu_seq_num, 0); end_reorder: return ret; @@ -2512,7 +2517,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, return; } - if (!ieee80211_rx_reorder_ampdu(local, skb)) + if (!ieee80211_rx_reorder_ampdu(local, skb, status)) __ieee80211_rx_handle_packet(hw, skb, status, rate); rcu_read_unlock(); -- cgit v1.2.3 From ec9a1d8c13e36440eda0f3c79b8149080e3ab5ba Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Mar 2009 22:51:58 +0100 Subject: b43: Poison RX buffers This patch adds poisoning and sanity checking to the RX DMA buffers. This is used for protection against buggy hardware/firmware that raises RX interrupts without doing an actual DMA transfer. This mechanism protects against rare "bad packets" (due to uninitialized skb data) and rare kernel crashes due to uninitialized RX headers. The poison is selected to not match on valid frames and to be cheap for checking. The poison check mechanism _might_ trigger incorrectly, if we are voluntarily receiving frames with bad PLCP headers. However, this is nonfatal, because the chance of such a match is basically zero and in case it happens it just results in dropping the packet. Bad-PLCP RX defaults to off, and you should leave it off unless you want to listen to the latest news broadcasted by your microwave oven. This patch also moves the initialization of the RX-header "length" field in front of the mapping of the DMA buffer. The CPU should not touch the buffer after we mapped it. Cc: stable@kernel.org Reported-by: Francesco Gringoli Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index e228c1de6e11..dfa6c72c3bd2 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -555,11 +555,32 @@ address_error: return 1; } +static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) +{ + unsigned char *f = skb->data + ring->frameoffset; + + return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7]) == 0xFF); +} + +static void b43_poison_rx_buffer(struct b43_dmaring *ring, struct sk_buff *skb) +{ + struct b43_rxhdr_fw4 *rxhdr; + unsigned char *frame; + + /* This poisons the RX buffer to detect DMA failures. */ + + rxhdr = (struct b43_rxhdr_fw4 *)(skb->data); + rxhdr->frame_len = 0; + + B43_WARN_ON(ring->rx_buffersize < ring->frameoffset + sizeof(struct b43_plcp_hdr6) + 2); + frame = skb->data + ring->frameoffset; + memset(frame, 0xFF, sizeof(struct b43_plcp_hdr6) + 2 /* padding */); +} + static int setup_rx_descbuffer(struct b43_dmaring *ring, struct b43_dmadesc_generic *desc, struct b43_dmadesc_meta *meta, gfp_t gfp_flags) { - struct b43_rxhdr_fw4 *rxhdr; dma_addr_t dmaaddr; struct sk_buff *skb; @@ -568,6 +589,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); if (unlikely(!skb)) return -ENOMEM; + b43_poison_rx_buffer(ring, skb); dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { /* ugh. try to realloc in zone_dma */ @@ -578,6 +600,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); if (unlikely(!skb)) return -ENOMEM; + b43_poison_rx_buffer(ring, skb); dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { @@ -592,9 +615,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, ring->ops->fill_descriptor(ring, desc, dmaaddr, ring->rx_buffersize, 0, 0, 0); - rxhdr = (struct b43_rxhdr_fw4 *)(skb->data); - rxhdr->frame_len = 0; - return 0; } @@ -1489,6 +1509,15 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) goto drop; } } + if (unlikely(b43_rx_buffer_is_poisoned(ring, skb))) { + /* Something went wrong with the DMA. + * The device did not touch the buffer and did not overwrite the poison. */ + b43dbg(ring->dev->wl, "DMA RX: Dropping poisoned buffer.\n"); + /* recycle the descriptor buffer. */ + sync_descbuffer_for_device(ring, meta->dmaaddr, + ring->rx_buffersize); + goto drop; + } if (unlikely(len > ring->rx_buffersize)) { /* The data did not fit into one descriptor buffer * and is split over multiple buffers. -- cgit v1.2.3 From cf68636a9773aa97915497fe54fa4a51e3f08f3a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 28 Mar 2009 00:41:25 +0100 Subject: b43: Refresh RX poison on buffer recycling The RX buffer poison needs to be refreshed, if we recycle an RX buffer, because it might be (partially) overwritten by some DMA operations. Cc: stable@kernel.org Cc: Francesco Gringoli Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index dfa6c72c3bd2..eae680b53052 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1503,20 +1503,16 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) len = le16_to_cpu(rxhdr->frame_len); } while (len == 0 && i++ < 5); if (unlikely(len == 0)) { - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - goto drop; + dmaaddr = meta->dmaaddr; + goto drop_recycle_buffer; } } if (unlikely(b43_rx_buffer_is_poisoned(ring, skb))) { /* Something went wrong with the DMA. * The device did not touch the buffer and did not overwrite the poison. */ b43dbg(ring->dev->wl, "DMA RX: Dropping poisoned buffer.\n"); - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - goto drop; + dmaaddr = meta->dmaaddr; + goto drop_recycle_buffer; } if (unlikely(len > ring->rx_buffersize)) { /* The data did not fit into one descriptor buffer @@ -1530,6 +1526,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) while (1) { desc = ops->idx2desc(ring, *slot, &meta); /* recycle the descriptor buffer. */ + b43_poison_rx_buffer(ring, meta->skb); sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize); *slot = next_slot(ring, *slot); @@ -1548,8 +1545,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); if (unlikely(err)) { b43dbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer() failed\n"); - sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); - goto drop; + goto drop_recycle_buffer; } unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); @@ -1559,6 +1555,11 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) b43_rx(ring->dev, skb, rxhdr); drop: return; + +drop_recycle_buffer: + /* Poison and recycle the RX buffer. */ + b43_poison_rx_buffer(ring, skb); + sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); } void b43_dma_rx(struct b43_dmaring *ring) -- cgit v1.2.3 From 540828196e48ec54b64067a2b9defd870bff3ece Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 25 Mar 2009 03:11:44 +0100 Subject: p54: replace MAC80211_LEDS with P54_LEDS in p54.h I'm very sorry, as this change belongs to the other patch: "[PATCH] p54: fix SoftLED compile dependencies". however I must have somehow lost "git add" for that file. Signed-off-by: Christian Lamparter Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 2dda5fe418b6..ecf8b6ed5a47 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -14,9 +14,9 @@ * published by the Free Software Foundation. */ -#ifdef CONFIG_MAC80211_LEDS +#ifdef CONFIG_P54_LEDS #include -#endif /* CONFIG_MAC80211_LEDS */ +#endif /* CONFIG_P54_LEDS */ enum p54_control_frame_types { P54_CONTROL_TYPE_SETUP = 0, @@ -116,7 +116,7 @@ enum fw_state { FW_STATE_RESETTING, }; -#ifdef CONFIG_MAC80211_LEDS +#ifdef CONFIG_P54_LEDS #define P54_LED_MAX_NAME_LEN 31 @@ -129,7 +129,7 @@ struct p54_led_dev { unsigned int registered; }; -#endif /* CONFIG_MAC80211_LEDS */ +#endif /* CONFIG_P54_LEDS */ struct p54_common { struct ieee80211_hw *hw; @@ -177,10 +177,10 @@ struct p54_common { u8 privacy_caps; u8 rx_keycache_size; /* LED management */ - #ifdef CONFIG_MAC80211_LEDS +#ifdef CONFIG_P54_LEDS struct p54_led_dev assoc_led; struct p54_led_dev tx_led; - #endif /* CONFIG_MAC80211_LEDS */ +#endif /* CONFIG_P54_LEDS */ u16 softled_state; /* bit field of glowing LEDs */ }; -- cgit v1.2.3 From 731c6531684250c46d732e369b25b003356f3947 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 30 Mar 2009 15:55:24 +0200 Subject: p54spi: fix locking warning in p54spi_op_tx This patch fixes the following waring: > ------------[ cut here ]------------ >WARNING: at kernel/softirq.c:138 local_bh_enable+0x54/0xbc() >Modules linked in: p54spi >[] (dump_stack+0x0/0x14) >[] (warn_on_slowpath+0x0/0x68) >[] (local_bh_enable+0x0/0xbc) >[] (p54spi_op_tx+0x0/0x4c [p54spi]) >[] (p54_sta_unlock+0x0/0x78) p54spi_op_tx needs to be called from different locking contexts. Therefore we have to protect the linked list with irqsave spinlocks. Reported-by: Max Filippov Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 2b222aaa6f0a..d1fe577de3d4 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -457,9 +457,10 @@ static int p54spi_wq_tx(struct p54s_priv *priv) struct ieee80211_tx_info *info; struct p54_tx_info *minfo; struct p54s_tx_info *dinfo; + unsigned long flags; int ret = 0; - spin_lock_bh(&priv->tx_lock); + spin_lock_irqsave(&priv->tx_lock, flags); while (!list_empty(&priv->tx_pending)) { entry = list_entry(priv->tx_pending.next, @@ -467,7 +468,7 @@ static int p54spi_wq_tx(struct p54s_priv *priv) list_del_init(&entry->tx_list); - spin_unlock_bh(&priv->tx_lock); + spin_unlock_irqrestore(&priv->tx_lock, flags); dinfo = container_of((void *) entry, struct p54s_tx_info, tx_list); @@ -479,16 +480,14 @@ static int p54spi_wq_tx(struct p54s_priv *priv) ret = p54spi_tx_frame(priv, skb); - spin_lock_bh(&priv->tx_lock); - if (ret < 0) { p54_free_skb(priv->hw, skb); - goto out; + return ret; } - } -out: - spin_unlock_bh(&priv->tx_lock); + spin_lock_irqsave(&priv->tx_lock, flags); + } + spin_unlock_irqrestore(&priv->tx_lock, flags); return ret; } @@ -498,12 +497,13 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct p54_tx_info *mi = (struct p54_tx_info *) info->rate_driver_data; struct p54s_tx_info *di = (struct p54s_tx_info *) mi->data; + unsigned long flags; BUILD_BUG_ON(sizeof(*di) > sizeof((mi->data))); - spin_lock_bh(&priv->tx_lock); + spin_lock_irqsave(&priv->tx_lock, flags); list_add_tail(&di->tx_list, &priv->tx_pending); - spin_unlock_bh(&priv->tx_lock); + spin_unlock_irqrestore(&priv->tx_lock, flags); queue_work(priv->hw->workqueue, &priv->work); } @@ -604,6 +604,7 @@ out: static void p54spi_op_stop(struct ieee80211_hw *dev) { struct p54s_priv *priv = dev->priv; + unsigned long flags; if (mutex_lock_interruptible(&priv->mutex)) { /* FIXME: how to handle this error? */ @@ -615,9 +616,9 @@ static void p54spi_op_stop(struct ieee80211_hw *dev) cancel_work_sync(&priv->work); p54spi_power_off(priv); - spin_lock_bh(&priv->tx_lock); + spin_lock_irqsave(&priv->tx_lock, flags); INIT_LIST_HEAD(&priv->tx_pending); - spin_unlock_bh(&priv->tx_lock); + spin_unlock_irqrestore(&priv->tx_lock, flags); priv->fw_state = FW_STATE_OFF; mutex_unlock(&priv->mutex); -- cgit v1.2.3 From c6dbe17f193c4adc8afc6884f26efb5fa27aa8af Mon Sep 17 00:00:00 2001 From: Masakazu Mokuno Date: Mon, 30 Mar 2009 11:04:36 -0700 Subject: net/ps3: Fix wireless AP connect error handling This patch fixes the bug that the driver tries to continue to connect(associate) to AP even if gelic_wl_do_{wpa,wep}_setup() fails, Signed-off-by: Masakazu Mokuno Signed-off-by: Geoff Levand Signed-off-by: John W. Linville --- drivers/net/ps3_gelic_wireless.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index a5ac2bd58b5b..4f3ada622f9b 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -2101,6 +2101,9 @@ static int gelic_wl_associate_bss(struct gelic_wl_info *wl, if (ret) { pr_debug("%s: WEP/WPA setup failed %d\n", __func__, ret); + ret = -EPERM; + gelic_wl_send_iwap_event(wl, NULL); + goto out; } /* start association */ -- cgit v1.2.3 From 853da11b94e674445e93660f47a5f0aeeea09623 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Fri, 3 Apr 2009 20:10:26 -0400 Subject: ath9k: fix access to a freed skb in ath_rx_tasklet() Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/recv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 71cb18d6757d..dd1f30156740 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -493,6 +493,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) int hdrlen, padsize, retval; bool decrypt_error = false; u8 keyix; + __le16 fc; spin_lock_bh(&sc->rx.rxbuflock); @@ -606,6 +607,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) /* see if any padding is done by the hw and remove it */ hdr = (struct ieee80211_hdr *)skb->data; hdrlen = ieee80211_get_hdrlen_from_skb(skb); + fc = hdr->frame_control; /* The MAC header is padded to have 32-bit boundary if the * packet payload is non-zero. The general calculation for @@ -690,7 +692,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) sc->rx.rxotherant = 0; } - if (ieee80211_is_beacon(hdr->frame_control) && + if (ieee80211_is_beacon(fc) && (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) { sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); -- cgit v1.2.3 From 47afbaf5af9454a7a1a64591e20cbfcc27ca67a8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 7 Apr 2009 15:22:28 +0200 Subject: mac80211: correct wext transmit power handler Wext makes no assumptions about the contents of data->txpower.fixed and data->txpower.value when data->txpower.disabled is set, so do not update the user-requested power level while disabling. Also, when wext configures a really _fixed_ power output [1], we should reject it instead of limiting it to the regulatory constraint. If the user wants to set a _limit_ [2] then we should honour that. [1] iwconfig wlan0 txpower 20dBm fixed [2] iwconfig wlan0 txpower 10dBm This fixes http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1942 Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 2 +- net/mac80211/wext.c | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a6f1d8a869bc..fbcbed6cad01 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -258,7 +258,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) (chan->max_power - local->power_constr_level) : chan->max_power; - if (local->user_power_level) + if (local->user_power_level >= 0) power = min(power, local->user_power_level); if (local->hw.conf.power_level != power) { diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index deb4ecec122a..ce9115c18152 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -417,6 +417,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_channel* chan = local->hw.conf.channel; + bool reconf = false; u32 reconf_flags = 0; int new_power_level; @@ -427,14 +428,38 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, if (!chan) return -EINVAL; - if (data->txpower.fixed) - new_power_level = min(data->txpower.value, chan->max_power); - else /* Automatic power level setting */ - new_power_level = chan->max_power; + /* only change when not disabling */ + if (!data->txpower.disabled) { + if (data->txpower.fixed) { + if (data->txpower.value < 0) + return -EINVAL; + new_power_level = data->txpower.value; + /* + * Debatable, but we cannot do a fixed power + * level above the regulatory constraint. + * Use "iwconfig wlan0 txpower 15dBm" instead. + */ + if (new_power_level > chan->max_power) + return -EINVAL; + } else { + /* + * Automatic power level setting, max being the value + * passed in from userland. + */ + if (data->txpower.value < 0) + new_power_level = -1; + else + new_power_level = data->txpower.value; + } + + reconf = true; - local->user_power_level = new_power_level; - if (local->hw.conf.power_level != new_power_level) - reconf_flags |= IEEE80211_CONF_CHANGE_POWER; + /* + * ieee80211_hw_config() will limit to the channel's + * max power and possibly power constraint from AP. + */ + local->user_power_level = new_power_level; + } if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { local->hw.conf.radio_enabled = !(data->txpower.disabled); @@ -442,7 +467,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, ieee80211_led_radio(local, local->hw.conf.radio_enabled); } - if (reconf_flags) + if (reconf || reconf_flags) ieee80211_hw_config(local, reconf_flags); return 0; -- cgit v1.2.3 From f54930f363113a9357c9ae008965b6484a61cd29 Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Tue, 7 Apr 2009 12:41:17 -0700 Subject: libertas: don't leak skb on receive error Don't lead memory when receive errors Signed-off-by: Philip Rakity Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/rx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 63d7e19ce9bd..8e669775cb5d 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -170,6 +170,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) lbs_deb_rx("rx err: frame received with bad length\n"); dev->stats.rx_length_errors++; ret = 0; + dev_kfree_skb(skb); goto done; } @@ -181,6 +182,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) lbs_pr_alert("rxpd not ok\n"); dev->stats.rx_errors++; ret = 0; + dev_kfree_skb(skb); goto done; } -- cgit v1.2.3 From 02a9a39294017f105aedebcca5f49d552b18dbaa Mon Sep 17 00:00:00 2001 From: Jamie Lentin Date: Tue, 7 Apr 2009 22:59:56 +0100 Subject: at76c50x-usb: Add device ID for OQO model 01+ Add USB device ID for OQO 01+'s internal wireless LAN An OQO employee mentions the chip's true identity here:- ftp://ftp.oqo.com/unsupported/linux/OQOLinux.html Signed-off-by: Jamie Lentin Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/at76c50x-usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 0c02f1c2bd94..744f4f4dd3d1 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -250,6 +250,8 @@ static struct usb_device_id dev_table[] = { { USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A) }, /* Siemens Gigaset USB WLAN Adapter 11 */ { USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A) }, + /* OQO Model 01+ Internal Wi-Fi */ + { USB_DEVICE(0x1557, 0x0002), USB_DEVICE_DATA(BOARD_505A) }, /* * at76c505amx-rfmd */ -- cgit v1.2.3 From 011f5c5bb20c08af93faa8bfd8d611c8cf85134f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 8 Apr 2009 10:15:17 -0400 Subject: airo: queue SIOCSIWAUTH-requested auth mode change for next commit Code was clearly wrong, plus callers expect the mode change to happen as soon as possible, not dropped on the floor until the next time some other config value changes and a commit happens. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index f21a6171c691..c36d3a3d655f 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -6713,11 +6713,11 @@ static int airo_set_auth(struct net_device *dev, local->config.authType = AUTH_ENCRYPT; } else return -EINVAL; - break; /* Commit the changes to flags if needed */ if (local->config.authType != currentAuthType) set_bit (FLAG_COMMIT, &local->flags); + break; } case IW_AUTH_WPA_ENABLED: -- cgit v1.2.3 From 4fc298b86635c60061bbd81cef8de2b031e5c4a7 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 24 Mar 2009 21:58:08 +0100 Subject: ar9170: add Cace Airpcap NX usb_id This patch adds a new device to ar9170usb. Reported-by: Mike Kershaw/Dragorn Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ar9170/usb.c b/drivers/net/wireless/ar9170/usb.c index ad296840893e..43e8d8de9a5c 100644 --- a/drivers/net/wireless/ar9170/usb.c +++ b/drivers/net/wireless/ar9170/usb.c @@ -59,6 +59,8 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x9170) }, /* Atheros TG121N */ { USB_DEVICE(0x0cf3, 0x1001) }, + /* Cace Airpcap NX */ + { USB_DEVICE(0xcace, 0x0300) }, /* D-Link DWA 160A */ { USB_DEVICE(0x07d1, 0x3c10) }, /* Netgear WNDA3100 */ -- cgit v1.2.3 From e3062403f5f71c48cf26e791e576f4feca4c9c0f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 29 Mar 2009 22:50:28 +0200 Subject: p54usb: add Telsey 802.11g USB2.0 Adapter Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index da6640afc835..6cc6cbc9234f 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -71,6 +71,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ + {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ -- cgit v1.2.3 From 6aabd4c4441133836ac969a9488458b37f83b677 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 28 Mar 2009 20:52:14 +0100 Subject: rt2x00: Add rt73usb USB IDs Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt73usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 420fff42c0dd..853b2b279b64 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2369,6 +2369,8 @@ static struct usb_device_id rt73usb_device_table[] = { /* Buffalo */ { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, /* CNet */ { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, -- cgit v1.2.3 From 591f3dc200abb2100c473248a121ce14bfeeabd6 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 31 Mar 2009 12:27:32 +0200 Subject: b43: Do radio lock assertion in software The assertion of the lock-bit in the hardware register is unreliable, because there are devices with quirks that will randomly set the bit. Do the assertion in software, only. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 5 +++++ drivers/net/wireless/b43/phy_common.c | 16 ++++++++++++---- drivers/net/wireless/b43/phy_common.h | 4 +++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 4896e0831114..79b685e300c7 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3974,6 +3974,11 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev, phy->next_txpwr_check_time = jiffies; /* PHY TX errors counter. */ atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); + +#if B43_DEBUG + phy->phy_locked = 0; + phy->radio_locked = 0; +#endif } static void setup_struct_wldev_for_init(struct b43_wldev *dev) diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 026b61c03fb9..e176b6e0d9cf 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -131,12 +131,16 @@ void b43_radio_lock(struct b43_wldev *dev) { u32 macctl; +#if B43_DEBUG + B43_WARN_ON(dev->phy.radio_locked); + dev->phy.radio_locked = 1; +#endif + macctl = b43_read32(dev, B43_MMIO_MACCTL); - B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK); macctl |= B43_MACCTL_RADIOLOCK; b43_write32(dev, B43_MMIO_MACCTL, macctl); - /* Commit the write and wait for the device - * to exit any radio register access. */ + /* Commit the write and wait for the firmware + * to finish any radio register access. */ b43_read32(dev, B43_MMIO_MACCTL); udelay(10); } @@ -145,11 +149,15 @@ void b43_radio_unlock(struct b43_wldev *dev) { u32 macctl; +#if B43_DEBUG + B43_WARN_ON(!dev->phy.radio_locked); + dev->phy.radio_locked = 0; +#endif + /* Commit any write */ b43_read16(dev, B43_MMIO_PHY_VER); /* unlock */ macctl = b43_read32(dev, B43_MMIO_MACCTL); - B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK)); macctl &= ~B43_MACCTL_RADIOLOCK; b43_write32(dev, B43_MMIO_MACCTL, macctl); } diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index c9f5430d1d7d..b2d99101947b 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -245,8 +245,10 @@ struct b43_phy { atomic_t txerr_cnt; #ifdef CONFIG_B43_DEBUG - /* PHY registers locked by b43_phy_lock()? */ + /* PHY registers locked (w.r.t. firmware) */ bool phy_locked; + /* Radio registers locked (w.r.t. firmware) */ + bool radio_locked; #endif /* B43_DEBUG */ }; -- cgit v1.2.3 From a860402d8f1756dae48cdcabe153c974116fc37e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 15 Apr 2009 14:41:22 -0400 Subject: mac80211: quiet beacon loss messages On Sunday 05 April 2009 11:29:38 Michael Buesch wrote: > On Sunday 05 April 2009 11:23:59 Jaswinder Singh Rajput wrote: > > With latest linus tree I am getting, .config file attached: > > > > [ 22.895051] r8169: eth0: link down > > [ 22.897564] ADDRCONF(NETDEV_UP): eth0: link is not ready > > [ 22.928047] ADDRCONF(NETDEV_UP): wlan0: link is not ready > > [ 22.982292] libvirtd used greatest stack depth: 4200 bytes left > > [ 63.709879] wlan0: authenticate with AP 00:11:95:9e:df:f6 > > [ 63.712096] wlan0: authenticated > > [ 63.712127] wlan0: associate with AP 00:11:95:9e:df:f6 > > [ 63.726831] wlan0: RX AssocResp from 00:11:95:9e:df:f6 (capab=0x471 status=0 aid=1) > > [ 63.726855] wlan0: associated > > [ 63.730093] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready > > [ 74.296087] wlan0: no IPv6 routers present > > [ 79.349044] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 119.358200] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 179.354292] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 259.366044] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 359.348292] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 361.953459] packagekitd used greatest stack depth: 4160 bytes left > > [ 478.824258] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 598.813343] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 718.817292] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 838.824567] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 958.815402] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 1078.848434] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 1198.822913] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 1318.824931] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 1438.814157] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 1558.827336] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 1678.823011] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 1798.830589] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 1918.828044] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 2038.827224] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 2116.517152] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 2158.840243] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > [ 2278.827427] wlan0: beacon loss from AP 00:11:95:9e:df:f6 - sending probe request > > > I think this message should only show if CONFIG_MAC80211_VERBOSE_DEBUG is set. > It's kind of expected that we lose a beacon once in a while, so we shouldn't print > verbose messages to the kernel log (even if they are KERN_DEBUG). > > And besides that, I think one can easily remotely trigger this message and flood the logs. > So it should probably _also_ be ratelimited. Something like this: Signed-off-by: Michael Buesch --- net/mac80211/mlme.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7ecda9d59d8a..1b14d0204dd2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -945,9 +945,13 @@ void ieee80211_beacon_loss_work(struct work_struct *work) u.mgd.beacon_loss_work); struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM " - "- sending probe request\n", sdata->dev->name, - sdata->u.mgd.bssid); +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM " + "- sending probe request\n", sdata->dev->name, + sdata->u.mgd.bssid); + } +#endif ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, @@ -1007,9 +1011,13 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) (local->hw.conf.flags & IEEE80211_CONF_PS)) && time_after(jiffies, ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) { - printk(KERN_DEBUG "%s: beacon loss from AP %pM " - "- sending probe request\n", - sdata->dev->name, ifmgd->bssid); +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: beacon loss from AP %pM " + "- sending probe request\n", + sdata->dev->name, ifmgd->bssid); + } +#endif ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, ifmgd->ssid_len, NULL, 0); -- cgit v1.2.3 From d60cc91acdc45f234d8830409203f504d03513c9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 9 Apr 2009 09:56:02 +0200 Subject: fix iwl3945 registration regression I forgot that iwl3945 registration is separate from iwlagn. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ce729281ff62..8d738d752487 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4913,6 +4913,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) hw->wiphy->custom_regulatory = true; + hw->wiphy->max_scan_ssids = 1; /* WILL FIX */ + /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; -- cgit v1.2.3 From f05faa31c387fb07f4c561350f00ba12cf673c9f Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Fri, 10 Apr 2009 18:05:14 -0300 Subject: rt2x00: prevent double kfree when failing to register hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In a scenario where there isn't any firmware available, we will have a double kfree of rt2x00dev->spec.channels_info when ieee80211_register_hw returns an error status inside rt2x00lib_probe_hw. The problem is that if ieee80211_register_hw fails, we call rt2x00lib_remove_hw twice: * first inside rt2x00lib_probe_hw upon failure of ieee80211_register_hw * error status is returned to rt2x00lib_probe_dev, which then sees it and calls in this case rt2x00lib_remove_dev that will again run rt2x00lib_remove_hw Prevent this avoiding calling rt2x00lib_remove_hw inside rt2x00lib_probe_hw Problem was detected with CONFIG_DEBUG_PAGEALLOC=y, CONFIG_SLUB_DEBUG=y, CONFIG_SLUB_DEBUG_ON=y, that dumps this with no firmware available: rt61pci 0000:00:07.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19 wmaster0 (rt61pci): not using net_device_ops yet phy0: Selected rate control algorithm 'pid' phy0: Failed to initialize wep: -2 phy0 -> rt2x00lib_probe_dev: Error - Failed to initialize hw. ============================================================================= BUG kmalloc-128: Object already free ----------------------------------------------------------------------------- INFO: Allocated in rt61pci_probe_hw+0x3e5/0x6e0 [rt61pci] age=340 cpu=0 pid=21 INFO: Freed in rt2x00lib_remove_hw+0x59/0x70 [rt2x00lib] age=0 cpu=0 pid=21 INFO: Slab 0xc13ac3e0 objects=23 used=10 fp=0xdd59f6e0 flags=0x400000c3 INFO: Object 0xdd59f6e0 @offset=1760 fp=0xdd59f790 Bytes b4 0xdd59f6d0: 15 00 00 00 b2 8a fb ff 5a 5a 5a 5a 5a 5a 5a 5a ....².ûÿZZZZZZZZ Object 0xdd59f6e0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object 0xdd59f6f0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object 0xdd59f700: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object 0xdd59f710: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object 0xdd59f720: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object 0xdd59f730: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object 0xdd59f740: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object 0xdd59f750: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5 kkkkkkkkkkkkkkk¥ Redzone 0xdd59f760: bb bb bb bb »»»» Padding 0xdd59f788: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ Pid: 21, comm: stage1 Not tainted 2.6.29.1-desktop-1.1mnb #1 Call Trace: [] print_trailer+0xd3/0x120 [] object_err+0x37/0x50 [] __slab_free+0xe7/0x2f0 [] kfree+0x7e/0xd0 [] ? rt2x00lib_remove_hw+0x59/0x70 [rt2x00lib] [] ? rt2x00lib_remove_hw+0x59/0x70 [rt2x00lib] [] rt2x00lib_remove_hw+0x59/0x70 [rt2x00lib] [] rt2x00lib_remove_dev+0x37/0x50 [rt2x00lib] [] rt2x00lib_probe_dev+0x1a7/0x3b0 [rt2x00lib] [] rt2x00pci_probe+0xdf/0x1ee [rt2x00pci] [] local_pci_probe+0xe/0x10 [] pci_device_probe+0x60/0x80 [] driver_probe_device+0x9a/0x2e0 [] __driver_attach+0x89/0x90 [] bus_for_each_dev+0x4b/0x70 [] ? pci_device_remove+0x0/0x40 [] driver_attach+0x19/0x20 [] ? __driver_attach+0x0/0x90 [] bus_add_driver+0x1cf/0x2a0 [] ? pci_device_remove+0x0/0x40 [] driver_register+0x69/0x140 [] __pci_register_driver+0x40/0x80 [] ? rt61pci_init+0x0/0x19 [rt61pci] [] rt61pci_init+0x17/0x19 [rt61pci] [] do_one_initcall+0x26/0x1c0 [] ? slab_pad_check+0x3c/0x120 [] ? slab_pad_check+0x3c/0x120 [] ? check_object+0xda/0x210 [] ? percpu_free+0x46/0x50 [] ? __slab_free+0x22e/0x2f0 [] ? percpu_free+0x46/0x50 [] ? percpu_free+0x46/0x50 [] ? percpu_free+0x46/0x50 [] ? stop_machine_destroy+0x3c/0x40 [] ? load_module+0xa5/0x1c50 [] ? rt61pci_eepromregister_read+0x0/0x40 [rt61pci] [] ? rt2x00pci_write_tx_data+0x0/0x90 [rt2x00pci] [] ? mutex_lock+0xb/0x20 [] ? mutex_lock+0xb/0x20 [] ? tracepoint_update_probe_range+0x76/0xa0 [] ? tracepoint_module_notify+0x2f/0x40 [] ? notifier_call_chain+0x2d/0x70 [] ? __blocking_notifier_call_chain+0x4d/0x60 [] ? blocking_notifier_call_chain+0x1a/0x20 [] sys_init_module+0x96/0x1d0 [] ? sys_munmap+0x46/0x60 [] syscall_call+0x7/0xb FIX kmalloc-128: Object at 0xdd59f6e0 not freed rt61pci 0000:00:07.0: PCI INT A disabled rt61pci: probe of 0000:00:07.0 failed with error -2 Signed-off-by: Herton Ronaldo Krzesinski Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 05f94e21b423..5752aaae906b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -646,10 +646,8 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) * Register HW. */ status = ieee80211_register_hw(rt2x00dev->hw); - if (status) { - rt2x00lib_remove_hw(rt2x00dev); + if (status) return status; - } set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags); -- cgit v1.2.3 From 23a99840d571a237845fd0906bce78e7c76be650 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 14 Apr 2009 06:32:56 +0200 Subject: mac80211: Fragmentation threshold (typo) mac80211: Fragmentation threshold (typo) ieee80211_ioctl_siwfrag() sets the fragmentation_threshold to 2352 when frame fragmentation is to be disabled, yet the corresponding 'get' function tests for 2353 bytes instead. This causes user-space tools to display a fragmentation threshold of 2352 bytes even if fragmentation has been disabled. Signed-off-by: Gerrit Renker Signed-off-by: John W. Linville --- net/mac80211/wext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index ce9115c18152..959aa8379ccf 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -555,7 +555,7 @@ static int ieee80211_ioctl_giwfrag(struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); frag->value = local->fragmentation_threshold; - frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD); + frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD); frag->fixed = 1; return 0; -- cgit v1.2.3 From 91fe9ca74e8220f17e2fa71a92cda330857daac4 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 9 Apr 2009 21:41:05 -0400 Subject: orinoco: correct timeout logic in __orinoco_hw_set_tkip_key() If the value read from HERMES_RID_TXQUEUEEMPTY becomes 0 after exactly 100 readings, we wrongly consider it a timeout. Rewrite the clever while loop as a for loop that does the right thing and looks simpler. Reported by Juha Leppanen Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/hw.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 081428d9409e..632fac86a308 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -372,15 +372,13 @@ int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx, } /* Wait upto 100ms for tx queue to empty */ - k = 100; - do { - k--; + for (k = 100; k > 0; k--) { udelay(1000); ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY, &xmitting); - if (ret) + if (ret || !xmitting) break; - } while ((k > 0) && xmitting); + } if (k == 0) ret = -ETIMEDOUT; -- cgit v1.2.3 From 1269fa737f21b3f643e4b12d3ac9938b142a7f00 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 10 Apr 2009 10:02:45 +0200 Subject: ar9170: fix struct layout on arm arm will pad even between u8's, so mark the structs/unions packed. Fixes a build bug on arm due to BUILD_BUG_ON tests in the code. Signed-off-by: Johannes Berg Reported-by: Al Viro Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/hw.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ar9170/hw.h b/drivers/net/wireless/ar9170/hw.h index 13091bd9d815..53e250a4278f 100644 --- a/drivers/net/wireless/ar9170/hw.h +++ b/drivers/net/wireless/ar9170/hw.h @@ -310,7 +310,7 @@ struct ar9170_tx_control { struct ar9170_rx_head { u8 plcp[12]; -}; +} __packed; struct ar9170_rx_tail { union { @@ -318,16 +318,16 @@ struct ar9170_rx_tail { u8 rssi_ant0, rssi_ant1, rssi_ant2, rssi_ant0x, rssi_ant1x, rssi_ant2x, rssi_combined; - }; + } __packed; u8 rssi[7]; - }; + } __packed; u8 evm_stream0[6], evm_stream1[6]; u8 phy_err; u8 SAidx, DAidx; u8 error; u8 status; -}; +} __packed; #define AR9170_ENC_ALG_NONE 0x0 #define AR9170_ENC_ALG_WEP64 0x1 -- cgit v1.2.3 From 788873ac70a5f2a5569ad41ef9753763ab270ddf Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2009 09:38:45 +0000 Subject: MAINTAINERS - Add section NETWORKING DRIVERS Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index abedca58d8bd..1ed1fa12b4e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3962,6 +3962,13 @@ F: net/wireless/ F: include/net/ieee80211* F: include/net/wireless.h +NETWORKING DRIVERS +L: netdev@vger.kernel.org +W: http://www.linuxfoundation.org/en/Net +T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git +S: Odd Fixes +F: drivers/net/ + NETXEN (1/10) GbE SUPPORT P: Dhananjay Phadke M: dhananjay@netxen.com -- cgit v1.2.3 From b1e8fd54af73116331376a7b3074932a21e7477a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2009 09:38:46 +0000 Subject: MAINTAINERS - Update NETWORKING W: url and standardize T: git url Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1ed1fa12b4e4..36ea627dabc1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3920,8 +3920,8 @@ NETWORKING [GENERAL] P: David S. Miller M: davem@davemloft.net L: netdev@vger.kernel.org -W: http://linux-net.osdl.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git +W: http://www.linuxfoundation.org/en/Net +T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git S: Maintained F: net/ F: include/net/ -- cgit v1.2.3 From a86043c2ad92aa6312807039198d6ab6171164ef Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 16 Apr 2009 16:59:28 +0000 Subject: e1000e: fix bug in restart queue logic If the e1000e transmit cleanup inner loop exited early, then cleaned might not be true. This could cause tx hangs or other badness. Use count to track the total number of descriptors cleaned instead of basing a tx queue restart off of a temporary working state variable. This code now makes the flow the same for e1000/e1000e/igb/ixgbe Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 1693ed116b16..ca82f19a7ed1 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -621,7 +621,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) struct e1000_buffer *buffer_info; unsigned int i, eop; unsigned int count = 0; - bool cleaned = false; unsigned int total_tx_bytes = 0, total_tx_packets = 0; i = tx_ring->next_to_clean; @@ -630,7 +629,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && (count < tx_ring->count)) { - for (cleaned = 0; !cleaned; count++) { + bool cleaned = false; + for (; !cleaned; count++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); @@ -661,8 +661,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) tx_ring->next_to_clean = i; #define TX_WAKE_THRESHOLD 32 - if (cleaned && netif_carrier_ok(netdev) && - e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) { + if (count && netif_carrier_ok(netdev) && + e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean. */ -- cgit v1.2.3 From 843f42678f6c47a2c8d1648e584cb57ebff3750f Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 16 Apr 2009 16:59:47 +0000 Subject: e1000: fix transmit routine exit bug If the e1000 transmit cleanup inner loop exited early, then cleaned might not be true. This could cause tx hangs or other badness. Use count to track the total number of descriptors cleaned instead of basing a tx queue restart off of a temporary working state variable. This code now makes the flow the same for e1000/e1000e/igb/ixgbe Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ef12931d302a..6a46ceed9436 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3834,7 +3834,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info; unsigned int i, eop; unsigned int count = 0; - bool cleaned = false; unsigned int total_tx_bytes=0, total_tx_packets=0; i = tx_ring->next_to_clean; @@ -3843,7 +3842,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && (count < tx_ring->count)) { - for (cleaned = false; !cleaned; count++) { + bool cleaned = false; + for ( ; !cleaned; count++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); @@ -3871,7 +3871,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, tx_ring->next_to_clean = i; #define TX_WAKE_THRESHOLD 32 - if (unlikely(cleaned && netif_carrier_ok(netdev) && + if (unlikely(count && netif_carrier_ok(netdev) && E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean. -- cgit v1.2.3 From f92ef202988ffb07bb86cf94d0b09f2a61192da7 Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 16 Apr 2009 15:00:20 +0000 Subject: ixgbe: Fix DCB traffic class mapping for 82599 The traffic classes in hardware are not symmetrical for Rx and Tx. Rx is every 16 descriptor queues, Tx is not. It runs 32-32-16-16-8-8-8 when running with 8 traffic classes, and runs 64-32-16 when running with 4 traffic classes. This patch fixes the mapping. Signed-off-by: Peter P Waskiewicz Jr Cc: stable@kernel.org Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 52 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 49a903784566..01884256f4c9 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2841,11 +2841,55 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) } ret = true; } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - for (i = 0; i < dcb_i; i++) { - adapter->rx_ring[i].reg_idx = i << 4; - adapter->tx_ring[i].reg_idx = i << 4; + if (dcb_i == 8) { + /* + * Tx TC0 starts at: descriptor queue 0 + * Tx TC1 starts at: descriptor queue 32 + * Tx TC2 starts at: descriptor queue 64 + * Tx TC3 starts at: descriptor queue 80 + * Tx TC4 starts at: descriptor queue 96 + * Tx TC5 starts at: descriptor queue 104 + * Tx TC6 starts at: descriptor queue 112 + * Tx TC7 starts at: descriptor queue 120 + * + * Rx TC0-TC7 are offset by 16 queues each + */ + for (i = 0; i < 3; i++) { + adapter->tx_ring[i].reg_idx = i << 5; + adapter->rx_ring[i].reg_idx = i << 4; + } + for ( ; i < 5; i++) { + adapter->tx_ring[i].reg_idx = + ((i + 2) << 4); + adapter->rx_ring[i].reg_idx = i << 4; + } + for ( ; i < dcb_i; i++) { + adapter->tx_ring[i].reg_idx = + ((i + 8) << 3); + adapter->rx_ring[i].reg_idx = i << 4; + } + + ret = true; + } else if (dcb_i == 4) { + /* + * Tx TC0 starts at: descriptor queue 0 + * Tx TC1 starts at: descriptor queue 64 + * Tx TC2 starts at: descriptor queue 96 + * Tx TC3 starts at: descriptor queue 112 + * + * Rx TC0-TC3 are offset by 32 queues each + */ + adapter->tx_ring[0].reg_idx = 0; + adapter->tx_ring[1].reg_idx = 64; + adapter->tx_ring[2].reg_idx = 96; + adapter->tx_ring[3].reg_idx = 112; + for (i = 0 ; i < dcb_i; i++) + adapter->rx_ring[i].reg_idx = i << 5; + + ret = true; + } else { + ret = false; } - ret = true; } else { ret = false; } -- cgit v1.2.3 From 2f3889f42ec7c2b0c3049ecdd8e4687b6930779a Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 16 Apr 2009 15:00:41 +0000 Subject: ixgbe: Fix the DCB PFC thresholds for 82599 The thresholds for the DCB priority flow control are incorrect for 82599. This fixes the thresholds to be correct. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_dcb_82599.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index 470b676c1dae..f4417fc3b0fd 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -290,7 +290,7 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw, s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { - u32 i, reg; + u32 i, reg, rx_pba_size; /* If PFC is disabled globally then fall back to LFC. */ if (!dcb_config->pfc_mode_enable) { @@ -301,17 +301,23 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { - /* Config and remember Tx */ + if (dcb_config->rx_pba_cfg == pba_equal) + rx_pba_size = IXGBE_RXPBSIZE_64KB; + else + rx_pba_size = (i < 4) ? IXGBE_RXPBSIZE_80KB + : IXGBE_RXPBSIZE_48KB; + + reg = ((rx_pba_size >> 5) & 0xFFE0); if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full || - dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) { - reg = hw->fc.high_water | IXGBE_FCRTH_FCEN; - IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); - reg = hw->fc.low_water | IXGBE_FCRTL_XONE; - IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); - } else { - IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), 0); - IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); - } + dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) + reg |= IXGBE_FCRTL_XONE; + IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); + + reg = ((rx_pba_size >> 2) & 0xFFE0); + if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full || + dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) + reg |= IXGBE_FCRTH_FCEN; + IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); } /* Configure pause time (2 TCs per register) */ -- cgit v1.2.3 From ee33c58541bae92669fe64a39f695ab533d0de14 Mon Sep 17 00:00:00 2001 From: Erik Waling Date: Wed, 15 Apr 2009 23:32:10 +0000 Subject: macb: Handle Retry Limit Exceeded errors When transfering large amounts of data we sometimes experienced that the Retry Limit Exceeded (RLE) bit got set in TSR during transmission attempts. When this happened the driver would stall in a state that prevented any more data from being sent. Signed-off-by: Erik Waling Signed-off-by: Haavard Skinnemoen Signed-off-by: David S. Miller --- drivers/net/macb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 46073de290cf..9fcc717f4d1a 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -316,10 +316,11 @@ static void macb_tx(struct macb *bp) dev_dbg(&bp->pdev->dev, "macb_tx status = %02lx\n", (unsigned long)status); - if (status & MACB_BIT(UND)) { + if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) { int i; - printk(KERN_ERR "%s: TX underrun, resetting buffers\n", - bp->dev->name); + printk(KERN_ERR "%s: TX %s, resetting buffers\n", + bp->dev->name, status & MACB_BIT(UND) ? + "underrun" : "retry limit exceeded"); /* Transfer ongoing, disable transmitter, to avoid confusion */ if (status & MACB_BIT(TGO)) @@ -590,7 +591,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) } } - if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND))) + if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND) | + MACB_BIT(ISR_RLE))) macb_tx(bp); /* -- cgit v1.2.3 From f72f550c5885419ee1b32f47213087e6640e766b Mon Sep 17 00:00:00 2001 From: Erik Waling Date: Wed, 15 Apr 2009 23:32:11 +0000 Subject: macb: process the RX ring regardless of interrupt status Suppose that we receive lots of frames, start processing them, but exhaust our budget so that we return before we had a chance to look at all of them. Then, when the network layer calls us again, we will only continue processing the buffers if the REC bit was set in the mean time, which it might not be if there was a brief pause in the flow of packets. If this happens, we'll simply display a warning and call netif_rx_complete() with potentially lots of unprocessed packets in the RX ring... Fix this by scanning the ring no matter what flags are set in the interrupt status register. Signed-off-by: Erik Waling Signed-off-by: Haavard Skinnemoen Signed-off-by: David S. Miller --- drivers/net/macb.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 9fcc717f4d1a..e82aee41d77e 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -521,27 +521,10 @@ static int macb_poll(struct napi_struct *napi, int budget) macb_writel(bp, RSR, status); work_done = 0; - if (!status) { - /* - * This may happen if an interrupt was pending before - * this function was called last time, and no packets - * have been received since. - */ - napi_complete(napi); - goto out; - } dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n", (unsigned long)status, budget); - if (!(status & MACB_BIT(REC))) { - dev_warn(&bp->pdev->dev, - "No RX buffers complete, status = %02lx\n", - (unsigned long)status); - napi_complete(napi); - goto out; - } - work_done = macb_rx(bp, budget); if (work_done < budget) napi_complete(napi); @@ -550,7 +533,6 @@ static int macb_poll(struct napi_struct *napi, int budget) * We've done what we can to clean the buffers. Make sure we * get notified when new packets arrive. */ -out: macb_writel(bp, IER, MACB_RX_INT_FLAGS); /* TODO: Handle errors */ -- cgit v1.2.3 From 62bcaa13039538c7f794b0cfcbc26e0313e7fcd5 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Fri, 17 Apr 2009 01:38:46 -0700 Subject: can: Network Drop Monitor: Make use of consume_skb() in af_can.c Since commit ead2ceb0ec9f85cff19c43b5cdb2f8a054484431 ("Network Drop Monitor: Adding kfree_skb_clean for non-drops and modifying end-of-line points for skbs") so called end-of-line points for skb's should use consume_skb() to free the socket buffer. In opposite to consume_skb() the function kfree_skb() is intended to be used for unexpected skb drops e.g. in error conditions that now can trigger the network drop monitor if enabled. This patch moves the skb end-of-line point in af_can.c to use consume_skb(). Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller --- net/can/af_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 547bafc79e28..10f0528c3bf5 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -674,8 +674,8 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, rcu_read_unlock(); - /* free the skbuff allocated by the netdevice driver */ - kfree_skb(skb); + /* consume the skbuff allocated by the netdevice driver */ + consume_skb(skb); if (matches > 0) { can_stats.matches++; -- cgit v1.2.3 From 9dd014eb9804f19d6230c3cbc10fa25f5416bda7 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 17 Apr 2009 01:40:19 -0700 Subject: pegasus: Handle disconnect error code correctly. EPERM means that disconnect() is runnung. It should be treated like ENODEV Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/pegasus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index a8228d87c8cf..2138535f2339 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -899,6 +899,7 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) /* cleanup should already have been scheduled */ break; case -ENODEV: /* disconnect() upcoming */ + case -EPERM: netif_device_detach(pegasus->net); break; default: -- cgit v1.2.3 From a0a69a0106dab8d20596f97f6674bed3b394d1ee Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 17 Apr 2009 02:34:38 -0700 Subject: gro: Fix use after free in tcp_gro_receive After calling skb_gro_receive skb->len can no longer be relied on since if the skb was merged using frags, then its pages will have been removed and the length reduced. This caused tcp_gro_receive to prematurely end merging which resulted in suboptimal performance with ixgbe. The fix is to store skb->len on the stack. Reported-by: Mark Wagner Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fafbec8b073e..1d7f49c6f0ca 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2511,6 +2511,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) struct sk_buff *p; struct tcphdr *th; struct tcphdr *th2; + unsigned int len; unsigned int thlen; unsigned int flags; unsigned int mss = 1; @@ -2531,6 +2532,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) skb_gro_pull(skb, thlen); + len = skb_gro_len(skb); flags = tcp_flag_word(th); for (; (p = *head); head = &p->next) { @@ -2561,7 +2563,7 @@ found: mss = skb_shinfo(p)->gso_size; - flush |= (skb_gro_len(skb) > mss) | !skb_gro_len(skb); + flush |= (len > mss) | !len; flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); if (flush || skb_gro_receive(head, skb)) { @@ -2574,7 +2576,7 @@ found: tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); out_check_final: - flush = skb_gro_len(skb) < mss; + flush = len < mss; flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | TCP_FLAG_SYN | TCP_FLAG_FIN); -- cgit v1.2.3 From 150ace0db360373d2016a2497d252138a59c5ba8 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 17 Apr 2009 17:47:31 +0200 Subject: netfilter: ctnetlink: report error if event message allocation fails This patch fixes an inconsistency that results in no error reports to user-space listeners if we fail to allocate the event message. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index c6439c77953c..0ea36e0c8a0e 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -512,7 +512,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, skb = ctnetlink_alloc_skb(tuple(ct, IP_CT_DIR_ORIGINAL), GFP_ATOMIC); if (!skb) - return NOTIFY_DONE; + goto errout; b = skb->tail; @@ -591,8 +591,9 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, nla_put_failure: rcu_read_unlock(); nlmsg_failure: - nfnetlink_set_err(0, group, -ENOBUFS); kfree_skb(skb); +errout: + nfnetlink_set_err(0, group, -ENOBUFS); return NOTIFY_DONE; } #endif /* CONFIG_NF_CONNTRACK_EVENTS */ @@ -1564,7 +1565,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb) - return NOTIFY_DONE; + goto errout; b = skb->tail; @@ -1589,8 +1590,9 @@ static int ctnetlink_expect_event(struct notifier_block *this, nla_put_failure: rcu_read_unlock(); nlmsg_failure: - nfnetlink_set_err(0, 0, -ENOBUFS); kfree_skb(skb); +errout: + nfnetlink_set_err(0, 0, -ENOBUFS); return NOTIFY_DONE; } #endif -- cgit v1.2.3 From a0142733a7ef2f3476e63938b330026a08c53f37 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 17 Apr 2009 17:48:44 +0200 Subject: netfilter: nfnetlink: return ENOMEM if we fail to create netlink socket With this patch, nfnetlink returns -ENOMEM instead of -EPERM if we fail to create the nfnetlink netlink socket during the module loading. This is exactly what rtnetlink does in this case. Ideally, it would be better if we propagate the error that has happened in netlink_kernel_create(), however, this function still does not implement this yet. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/netfilter/nfnetlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 2785d66a7e38..b8ab37ad7ed5 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -203,7 +203,7 @@ static int __init nfnetlink_init(void) nfnetlink_rcv, NULL, THIS_MODULE); if (!nfnl) { printk(KERN_ERR "cannot initialize nfnetlink!\n"); - return -1; + return -ENOMEM; } return 0; -- cgit v1.2.3 From 7181d4673710888b6d7084b37b9d77ed4f4e41b2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 Apr 2009 21:33:15 +0200 Subject: mac80211: avoid crashing when no scan sdata Using the scan_sdata variable here is terribly wrong, if there has never been a scan then we fail. However, we need a bandaid... Signed-off-by: Johannes Berg Cc: stable@kernel.org [2.6.29] Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1b14d0204dd2..dc60804d6dd0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2113,12 +2113,13 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) struct ieee80211_local *local = container_of(work, struct ieee80211_local, dynamic_ps_enable_work); + /* XXX: using scan_sdata is completely broken! */ struct ieee80211_sub_if_data *sdata = local->scan_sdata; if (local->hw.conf.flags & IEEE80211_CONF_PS) return; - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK && sdata) ieee80211_send_nullfunc(local, sdata, 1); local->hw.conf.flags |= IEEE80211_CONF_PS; -- cgit v1.2.3 From 160002fe845218f5789a26954048592c3920ac7b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 Apr 2009 12:15:38 +0200 Subject: cfg80211: copy hold when replacing BSS When we receive a probe response frame we can replace the BSS struct in our list -- but if that struct is held then we need to hold the new one as well. We really should fix this completely and not replace the struct, but this is a bandaid for now. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/scan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 2a00e362f5fe..4c77669275eb 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -364,6 +364,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, list_replace(&found->list, &res->list); rb_replace_node(&found->rbn, &res->rbn, &dev->bss_tree); + /* XXX: workaround */ + res->hold = found->hold; kref_put(&found->ref, bss_release); found = res; } else if (found) { -- cgit v1.2.3 From cd1658f592a60d028dd2e48d86724b737a82cab0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 Apr 2009 15:00:58 +0200 Subject: cfg80211: do not replace BSS structs Instead, allocate extra IE memory if necessary. Normally, this isn't even necessary since there's enough space. This is a better way of correcting the "held BSS can disappear" issue, but also a lot more code. It is also necessary for proper auth/assoc BSS handling in the future. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.h | 2 +- net/wireless/scan.c | 42 +++++++++++++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/net/wireless/core.h b/net/wireless/core.h index d43daa236ef9..0a592e4295f0 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -90,7 +90,7 @@ struct cfg80211_internal_bss { struct rb_node rbn; unsigned long ts; struct kref ref; - bool hold; + bool hold, ies_allocated; /* must be last because of priv member */ struct cfg80211_bss pub; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 4c77669275eb..2ae65b39b529 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -58,6 +58,10 @@ static void bss_release(struct kref *ref) bss = container_of(ref, struct cfg80211_internal_bss, ref); if (bss->pub.free_priv) bss->pub.free_priv(&bss->pub); + + if (bss->ies_allocated) + kfree(bss->pub.information_elements); + kfree(bss); } @@ -360,21 +364,41 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, found = rb_find_bss(dev, res); - if (found && overwrite) { - list_replace(&found->list, &res->list); - rb_replace_node(&found->rbn, &res->rbn, - &dev->bss_tree); - /* XXX: workaround */ - res->hold = found->hold; - kref_put(&found->ref, bss_release); - found = res; - } else if (found) { + if (found) { kref_get(&found->ref); found->pub.beacon_interval = res->pub.beacon_interval; found->pub.tsf = res->pub.tsf; found->pub.signal = res->pub.signal; found->pub.capability = res->pub.capability; found->ts = res->ts; + + /* overwrite IEs */ + if (overwrite) { + size_t used = dev->wiphy.bss_priv_size + sizeof(*res); + size_t ielen = res->pub.len_information_elements; + + if (ksize(found) >= used + ielen) { + memcpy(found->pub.information_elements, + res->pub.information_elements, ielen); + found->pub.len_information_elements = ielen; + } else { + u8 *ies = found->pub.information_elements; + + if (found->ies_allocated) { + if (ksize(ies) < ielen) + ies = krealloc(ies, ielen, + GFP_ATOMIC); + } else + ies = kmalloc(ielen, GFP_ATOMIC); + + if (ies) { + memcpy(ies, res->pub.information_elements, ielen); + found->ies_allocated = true; + found->pub.information_elements = ies; + } + } + } + kref_put(&res->ref, bss_release); } else { /* this "consumes" the reference */ -- cgit v1.2.3 From 60375541f7c8a577b977d344565259776c3acfc1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 17 Apr 2009 00:54:23 +0200 Subject: mac80211: validate TIM IE length The TIM IE must not be shorter than 4 bytes, so verify that when parsing it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index dc60804d6dd0..1619e0cd26e2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -441,6 +441,9 @@ static bool ieee80211_check_tim(struct ieee802_11_elems *elems, u16 aid) u8 index, indexn1, indexn2; struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim; + if (unlikely(!tim || elems->tim_len < 4)) + return false; + aid &= 0x3fff; index = aid / 8; mask = 1 << (aid & 7); -- cgit v1.2.3 From 957b0516f7881284b48f2f2e4a909a1c5de0ddf8 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 17 Apr 2009 14:52:23 +0200 Subject: ar9170usb: add ZyXEL NWD271N Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ar9170/usb.c b/drivers/net/wireless/ar9170/usb.c index 43e8d8de9a5c..c9e422ead925 100644 --- a/drivers/net/wireless/ar9170/usb.c +++ b/drivers/net/wireless/ar9170/usb.c @@ -69,6 +69,8 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x0846, 0x9001) }, /* Zydas ZD1221 */ { USB_DEVICE(0x0ace, 0x1221) }, + /* ZyXEL NWD271N */ + { USB_DEVICE(0x0586, 0x3417) }, /* Z-Com UB81 BG */ { USB_DEVICE(0x0cde, 0x0023) }, /* Z-Com UB82 ABG */ -- cgit v1.2.3 From 7816a0a862d851d0b05710e7d94bfe390f3180e2 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 17 Apr 2009 15:59:23 -0700 Subject: vlan/macvlan: fix NULL pointer dereferences in ethtool handlers Check whether the underlying device provides a set of ethtool ops before checking for individual handlers to avoid NULL pointer dereferences. Reported-by: Art van Breemen Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 9 ++++++--- net/8021q/vlan_dev.c | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 70d3ef4a2c5f..214a8cf2b708 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -376,7 +376,8 @@ static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev) const struct macvlan_dev *vlan = netdev_priv(dev); struct net_device *lowerdev = vlan->lowerdev; - if (lowerdev->ethtool_ops->get_rx_csum == NULL) + if (lowerdev->ethtool_ops == NULL || + lowerdev->ethtool_ops->get_rx_csum == NULL) return 0; return lowerdev->ethtool_ops->get_rx_csum(lowerdev); } @@ -387,7 +388,8 @@ static int macvlan_ethtool_get_settings(struct net_device *dev, const struct macvlan_dev *vlan = netdev_priv(dev); struct net_device *lowerdev = vlan->lowerdev; - if (!lowerdev->ethtool_ops->get_settings) + if (!lowerdev->ethtool_ops || + !lowerdev->ethtool_ops->get_settings) return -EOPNOTSUPP; return lowerdev->ethtool_ops->get_settings(lowerdev, cmd); @@ -398,7 +400,8 @@ static u32 macvlan_ethtool_get_flags(struct net_device *dev) const struct macvlan_dev *vlan = netdev_priv(dev); struct net_device *lowerdev = vlan->lowerdev; - if (!lowerdev->ethtool_ops->get_flags) + if (!lowerdev->ethtool_ops || + !lowerdev->ethtool_ops->get_flags) return 0; return lowerdev->ethtool_ops->get_flags(lowerdev); } diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 1b34135cf990..6b0921364014 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -668,7 +668,8 @@ static int vlan_ethtool_get_settings(struct net_device *dev, const struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev = vlan->real_dev; - if (!real_dev->ethtool_ops->get_settings) + if (!real_dev->ethtool_ops || + !real_dev->ethtool_ops->get_settings) return -EOPNOTSUPP; return real_dev->ethtool_ops->get_settings(real_dev, cmd); -- cgit v1.2.3 From e2139b32726e5dd184974c785ea3f62026590801 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 26 Mar 2009 16:41:56 +0200 Subject: Bluetooth: Fix removing of RFCOMM DLC timer with DEFER_SETUP There is a missing call to rfcomm_dlc_clear_timer in the case that DEFER_SETUP is used and so the connection gets disconnected after the timeout even if it was successfully accepted previously. This patch adds a call to rfcomm_dlc_clear_timer to rfcomm_dlc_accept which will get called when the user accepts the connection by calling read() on the socket. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/rfcomm/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 1d0fb0f23c63..374536e050aa 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1194,6 +1194,8 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d) rfcomm_send_ua(d->session, d->dlci); + rfcomm_dlc_clear_timer(d); + rfcomm_dlc_lock(d); d->state = BT_CONNECTED; d->state_change(d, 0); -- cgit v1.2.3 From 732547f96ea2442965a24e0ed529d285321a0fff Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 19 Apr 2009 19:14:14 +0200 Subject: Bluetooth: Fallback from eSCO to SCO on unspecified error Some Bluetooth chips (like the ones from Texas Instruments) don't do proper eSCO negotiations inside the Link Manager. They just return an error code and in case of the Kyocera ED-8800 headset it is just a random error. < HCI Command: Setup Synchronous Connection 0x01|0x0028) plen 17 handle 1 voice setting 0x0060 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x1f handle 257 bdaddr 00:14:0A:xx:xx:xx type eSCO Error: Unspecified Error In these cases it is up to the host stack to fallback to a SCO setup and so retry with SCO parameters. Based on a report by Nick Pelly Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 55534244c3a0..963f9662eaa8 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1646,20 +1646,28 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu conn->type = SCO_LINK; } - if (conn->out && ev->status == 0x1c && conn->attempt < 2) { - conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | - (hdev->esco_type & EDR_ESCO_MASK); - hci_setup_sync(conn, conn->link->handle); - goto unlock; - } - - if (!ev->status) { + switch (ev->status) { + case 0x00: conn->handle = __le16_to_cpu(ev->handle); conn->state = BT_CONNECTED; hci_conn_add_sysfs(conn); - } else + break; + + case 0x1c: /* SCO interval rejected */ + case 0x1f: /* Unspecified error */ + if (conn->out && conn->attempt < 2) { + conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | + (hdev->esco_type & EDR_ESCO_MASK); + hci_setup_sync(conn, conn->link->handle); + goto unlock; + } + /* fall through */ + + default: conn->state = BT_CLOSED; + break; + } hci_proto_connect_cfm(conn, ev->status); if (ev->status) -- cgit v1.2.3 From 9499237a1c42a27fbcc7ed1d59e34df2b574cdfb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 19 Apr 2009 19:30:03 +0200 Subject: Bluetooth: Add workaround for wrong HCI event in eSCO setup The Broadcom chips with 2.1 firmware handle the fallback case to a SCO link wrongly when setting up eSCO connections. < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 11 voice setting 0x0060 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 > HCI Event: Connect Complete (0x03) plen 11 status 0x00 handle 1 bdaddr 00:1E:3A:xx:xx:xx type SCO encrypt 0x01 The Link Manager negotiates the fallback to SCO, but then sends out a Connect Complete event. This is wrong and the Link Manager should actually send a Synchronous Connection Complete event if the Setup Synchronous Connection has been used. Only the remote side is allowed to use Connect Complete to indicate the missing support for eSCO in the host stack. This patch adds a workaround for this which clearly should not be needed, but reality is that broken Broadcom devices are deployed. Based on a report by Ville Tervo Signed-off-by: Marcel Holtman --- net/bluetooth/hci_event.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 963f9662eaa8..15f40ea8d544 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -866,8 +866,16 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); - if (!conn) - goto unlock; + if (!conn) { + if (ev->link_type != SCO_LINK) + goto unlock; + + conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); + if (!conn) + goto unlock; + + conn->type = SCO_LINK; + } if (!ev->status) { conn->handle = __le16_to_cpu(ev->handle); -- cgit v1.2.3 From 3851c66cf0d130ae49f99fe1dea42950d9835037 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Fri, 17 Apr 2009 12:21:11 +0000 Subject: cxgb3: fix link fault handling Use the existing periodic task to handle link faults. The link fault interrupt handler is also called in work queue context, which is wrong and might cause potential deadlocks. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 22 ++-------------------- drivers/net/cxgb3/t3_hw.c | 11 +---------- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index ab0e5febef83..9fdfe0bfaecb 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2493,6 +2493,7 @@ static void check_link_status(struct adapter *adapter) spin_lock_irq(&adapter->work_lock); if (p->link_fault) { + t3_link_fault(adapter, i); spin_unlock_irq(&adapter->work_lock); continue; } @@ -2554,9 +2555,7 @@ static void t3_adap_check_task(struct work_struct *work) adapter->check_task_cnt++; - /* Check link status for PHYs without interrupts */ - if (p->linkpoll_period) - check_link_status(adapter); + check_link_status(adapter); /* Accumulate MAC stats if needed */ if (!p->linkpoll_period || @@ -2680,21 +2679,6 @@ void t3_os_ext_intr_handler(struct adapter *adapter) spin_unlock(&adapter->work_lock); } -static void link_fault_task(struct work_struct *work) -{ - struct adapter *adapter = container_of(work, struct adapter, - link_fault_handler_task); - int i; - - for_each_port(adapter, i) { - struct net_device *netdev = adapter->port[i]; - struct port_info *pi = netdev_priv(netdev); - - if (pi->link_fault) - t3_link_fault(adapter, i); - } -} - void t3_os_link_fault_handler(struct adapter *adapter, int port_id) { struct net_device *netdev = adapter->port[port_id]; @@ -2702,7 +2686,6 @@ void t3_os_link_fault_handler(struct adapter *adapter, int port_id) spin_lock(&adapter->work_lock); pi->link_fault = 1; - queue_work(cxgb3_wq, &adapter->link_fault_handler_task); spin_unlock(&adapter->work_lock); } @@ -3082,7 +3065,6 @@ static int __devinit init_one(struct pci_dev *pdev, INIT_LIST_HEAD(&adapter->adapter_list); INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task); - INIT_WORK(&adapter->link_fault_handler_task, link_fault_task); INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task); INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task); diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 31ed31a3428b..e1bd690ff831 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -1202,7 +1202,6 @@ void t3_link_changed(struct adapter *adapter, int port_id) struct cphy *phy = &pi->phy; struct cmac *mac = &pi->mac; struct link_config *lc = &pi->link_config; - int force_link_down = 0; phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); @@ -1218,14 +1217,9 @@ void t3_link_changed(struct adapter *adapter, int port_id) status = t3_read_reg(adapter, A_XGM_INT_STATUS + mac->offset); if (status & F_LINKFAULTCHANGE) { mac->stats.link_faults++; - force_link_down = 1; + pi->link_fault = 1; } t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low); - - if (force_link_down) { - t3_os_link_fault_handler(adapter, port_id); - return; - } } if (lc->requested_fc & PAUSE_AUTONEG) @@ -1292,9 +1286,6 @@ void t3_link_fault(struct adapter *adapter, int port_id) /* Account link faults only when the phy reports a link up */ if (link_ok) mac->stats.link_faults++; - - msleep(1000); - t3_os_link_fault_handler(adapter, port_id); } else { if (link_ok) t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, -- cgit v1.2.3 From c80b0c28caed5cd9165caab6295ed86b4e9fc327 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Fri, 17 Apr 2009 12:21:17 +0000 Subject: cxgb3: fix workqueue flush issues The fatal error task can be scheduled while processing an offload packet in NAPI context when the connection handle is bogus. this can race with the ports being brought down and the cxgb3 workqueue being flushed. Stop napi processing before flushing the work queue. The ULP drivers (iSCSI, iWARP) might also schedule a task on keventd_wk while releasing a connection handle (cxgb3_offload.c::cxgb3_queue_tid_release()). The driver however does not flush any work on keventd_wq while being unloaded. This patch also fixes this. Also call cancel_delayed_work_sync in place of the the deprecated cancel_rearming_delayed_workqueue. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 9fdfe0bfaecb..99b5032afda6 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1117,8 +1117,8 @@ static void cxgb_down(struct adapter *adapter) spin_unlock_irq(&adapter->work_lock); free_irq_resources(adapter); - flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ quiesce_rx(adapter); + flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ } static void schedule_chk_task(struct adapter *adap) @@ -1187,6 +1187,9 @@ static int offload_close(struct t3cdev *tdev) sysfs_remove_group(&tdev->lldev->dev.kobj, &offload_attr_group); + /* Flush work scheduled while releasing TIDs */ + flush_scheduled_work(); + tdev->lldev = NULL; cxgb3_set_dummy_ops(tdev); t3_tp_set_offload_mode(adapter, 0); @@ -1247,8 +1250,7 @@ static int cxgb_close(struct net_device *dev) spin_unlock_irq(&adapter->work_lock); if (!(adapter->open_device_map & PORT_MASK)) - cancel_rearming_delayed_workqueue(cxgb3_wq, - &adapter->adap_check_task); + cancel_delayed_work_sync(&adapter->adap_check_task); if (!adapter->open_device_map) cxgb_down(adapter); -- cgit v1.2.3 From 2c2f409f32d55d901b28b4e9a06c40e9d899ad25 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Fri, 17 Apr 2009 12:21:22 +0000 Subject: cxgb3: Fix potential msi-x vector leak Release vectors when a MSI-X allocation fails. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 99b5032afda6..cbd59fe618a9 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2917,8 +2917,13 @@ static int __devinit cxgb_enable_msix(struct adapter *adap) while ((err = pci_enable_msix(adap->pdev, entries, vectors)) > 0) vectors = err; - if (!err && vectors < (adap->params.nports + 1)) + if (err < 0) + pci_disable_msix(adap->pdev); + + if (!err && vectors < (adap->params.nports + 1)) { + pci_disable_msix(adap->pdev); err = -1; + } if (!err) { for (i = 0; i < vectors; ++i) -- cgit v1.2.3 From e8d19370734f11e5880bb9ae2125f586e9e5d15c Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Fri, 17 Apr 2009 12:21:27 +0000 Subject: cxgb3: Fix EEH final recovery attempt EEH attempts to recover up 6 times. The last attempt leaves all the ports and adapter down.hen The driver is then unloaded, bringing the adapter down again unconditionally. The unload will hang. Check if the adapter is already down before trying to bring it down again. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index cbd59fe618a9..7ea48414c6cb 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1235,6 +1235,10 @@ static int cxgb_close(struct net_device *dev) struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; + + if (!adapter->open_device_map) + return 0; + /* Stop link fault interrupts */ t3_xgm_intr_disable(adapter, pi->port_id); t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset); @@ -2823,6 +2827,9 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev, struct adapter *adapter = pci_get_drvdata(pdev); int ret; + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + ret = t3_adapter_error(adapter, 0); /* Request a slot reset. */ -- cgit v1.2.3 From c7c1a0f60b90955855ba8cd9cfc480167bf6c3da Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 17 Apr 2009 04:19:36 +0000 Subject: ax25: proc uid file misses header This has been broken for a while. I happened to catch it testing because one app "knew" that the top line of the calls data was the policy line and got confused. Put the header back. Signed-off-by: Alan Cox Signed-off-by: David S. Miller --- net/ax25/ax25_uid.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 57aeba729bae..832bcf092a01 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -148,9 +148,13 @@ static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos) { struct ax25_uid_assoc *pt; struct hlist_node *node; - int i = 0; + int i = 1; read_lock(&ax25_uid_lock); + + if (*pos == 0) + return SEQ_START_TOKEN; + ax25_uid_for_each(pt, node, &ax25_uid_list) { if (i == *pos) return pt; @@ -162,8 +166,10 @@ static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos) static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; - - return hlist_entry(((ax25_uid_assoc *)v)->uid_node.next, + if (v == SEQ_START_TOKEN) + return ax25_uid_list.first; + else + return hlist_entry(((ax25_uid_assoc *)v)->uid_node.next, ax25_uid_assoc, uid_node); } -- cgit v1.2.3 From 8caf153974f2274301e583fda732cc8e5b80331f Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Fri, 17 Apr 2009 10:08:49 +0000 Subject: net: sch_netem: Fix an inconsistency in ingress netem timestamps. Alex Sidorenko reported: "while experimenting with 'netem' we have found some strange behaviour. It seemed that ingress delay as measured by 'ping' command shows up on some hosts but not on others. After some investigation I have found that the problem is that skbuff->tstamp field value depends on whether there are any packet sniffers enabled. That is: - if any ptype_all handler is registered, the tstamp field is as expected - if there are no ptype_all handlers, the tstamp field does not show the delay" This patch prevents unnecessary update of tstamp in dev_queue_xmit_nit() on ingress path (with act_mirred) adding a check, so minimal overhead on the fast path, but only when sniffers etc. are active. Since netem at ingress seems to logically emulate a network before a host, tstamp is zeroed to trigger the update and pretend delays are from the outside. Reported-by: Alex Sidorenko Tested-by: Alex Sidorenko Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/core/dev.c | 5 +++++ net/sched/sch_netem.c | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 343883f65ea7..dcc357e4f91e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1336,7 +1336,12 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) { struct packet_type *ptype; +#ifdef CONFIG_NET_CLS_ACT + if (!(skb->tstamp.tv64 && (G_TC_FROM(skb->tc_verd) & AT_INGRESS))) + net_timestamp(skb); +#else net_timestamp(skb); +#endif rcu_read_lock(); list_for_each_entry_rcu(ptype, &ptype_all, list) { diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index d876b8734848..2b88295cb7b7 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -280,6 +280,14 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) if (unlikely(!skb)) return NULL; +#ifdef CONFIG_NET_CLS_ACT + /* + * If it's at ingress let's pretend the delay is + * from the network (tstamp will be updated). + */ + if (G_TC_FROM(skb->tc_verd) & AT_INGRESS) + skb->tstamp.tv64 = 0; +#endif pr_debug("netem_dequeue: return skb=%p\n", skb); sch->q.qlen--; return skb; -- cgit v1.2.3 From 52cf3cc8acea52ecb93ef1dddb4ef2ae4e35c319 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Sat, 18 Apr 2009 05:48:48 +0000 Subject: tcp: fix mid-wq adjustment helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just noticed while doing some new work that the recent mid-wq adjustment logic will misbehave when FACK is not in use (happens either due sysctl'ed off or auto-detected reordering) because I forgot the relevant TCPCB tagbit. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 53300fa2359f..59aec609cec6 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -778,7 +778,7 @@ static void tcp_adjust_pcount(struct sock *sk, struct sk_buff *skb, int decr) if (tp->lost_skb_hint && before(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(tp->lost_skb_hint)->seq) && - (tcp_is_fack(tp) || TCP_SKB_CB(skb)->sacked)) + (tcp_is_fack(tp) || (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))) tp->lost_cnt_hint -= decr; tcp_verify_left_out(tp); -- cgit v1.2.3 From eb39c57ff7782bc015da517af1d9c3b2592e721e Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 19 Apr 2009 07:24:24 +0000 Subject: net: fix "compatibility" typos Signed-off-by: Marcin Slusarz Signed-off-by: David S. Miller --- drivers/net/Kconfig | 4 ++-- net/core/dev.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9e921544ba20..214a92d1ef75 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -28,9 +28,9 @@ if NETDEVICES config COMPAT_NET_DEV_OPS default y - bool "Enable older network device API compatiablity" + bool "Enable older network device API compatibility" ---help--- - This option enables kernel compatiability with older network devices + This option enables kernel compatibility with older network devices that do not use net_device_ops interface. If unsure, say Y. diff --git a/net/core/dev.c b/net/core/dev.c index dcc357e4f91e..001a4c551d44 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4405,7 +4405,7 @@ int register_netdevice(struct net_device *dev) dev->iflink = -1; #ifdef CONFIG_COMPAT_NET_DEV_OPS - /* Netdevice_ops API compatiability support. + /* Netdevice_ops API compatibility support. * This is temporary until all network devices are converted. */ if (dev->netdev_ops) { @@ -4416,7 +4416,7 @@ int register_netdevice(struct net_device *dev) dev->name, netdev_drivername(dev, drivername, 64)); /* This works only because net_device_ops and the - compatiablity structure are the same. */ + compatibility structure are the same. */ dev->netdev_ops = (void *) &(dev->init); } #endif -- cgit v1.2.3 From 5db8765a86a4cbaf45adaf8c231cf9a6ca2dcfaf Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 16 Apr 2009 08:04:20 +0000 Subject: net: Fix GRO for multiple page fragments This loop over fragments in napi_fraginfo_skb() was "interesting". Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 001a4c551d44..308a7d0c277f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2545,9 +2545,9 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, } BUG_ON(info->nr_frags > MAX_SKB_FRAGS); - frag = &info->frags[info->nr_frags - 1]; + frag = info->frags; - for (i = skb_shinfo(skb)->nr_frags; i < info->nr_frags; i++) { + for (i = 0; i < info->nr_frags; i++) { skb_fill_page_desc(skb, i, frag->page, frag->page_offset, frag->size); frag++; -- cgit v1.2.3 From 9c3fea6ab04a7bd9298e635bf29b4a5379f6c476 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 18 Apr 2009 14:15:52 +0000 Subject: tun: Only free a netdev when all tun descriptors are closed The commit c70f182940f988448f3c12a209d18b1edc276e33 ("tun: Fix races between tun_net_close and free_netdev") fixed a race where an asynchronous deletion of a tun device can hose a poll(2) on a tun fd attached to that device. However, this came at the cost of moving the tun wait queue into the tun file data structure. The problem with this is that it imposes restrictions on when and where the tun device can access the wait queue since the tun file may change at any time due to detaching and reattaching. In particular, now that we need to use the wait queue on the receive path it becomes difficult to properly synchronise this with the detachment of the tun device. This patch solves the original race in a different way. Since the race is only because the underlying memory gets freed, we can prevent it simply by ensuring that we don't do that until all tun descriptors ever attached to the device (even if they have since be detached because they may still be sitting in poll) have been closed. This is done by using reference counting the attached tun file descriptors. The refcount in tun->sk has been reappropriated for this purpose since it was already being used for that, albeit from the opposite angle. Note that we no longer zero tfile->tun since tun_get will return NULL anyway after the refcount on tfile hits zero. Instead it represents whether this device has ever been attached to a device. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/tun.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 16716aef184c..95ae40ab8718 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -156,6 +156,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file) tfile->tun = tun; tun->tfile = tfile; dev_hold(tun->dev); + sock_hold(tun->sk); atomic_inc(&tfile->count); out: @@ -165,11 +166,8 @@ out: static void __tun_detach(struct tun_struct *tun) { - struct tun_file *tfile = tun->tfile; - /* Detach from net device */ netif_tx_lock_bh(tun->dev); - tfile->tun = NULL; tun->tfile = NULL; netif_tx_unlock_bh(tun->dev); @@ -339,6 +337,13 @@ static void tun_net_uninit(struct net_device *dev) } } +static void tun_free_netdev(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + sock_put(tun->sk); +} + /* Net device open. */ static int tun_net_open(struct net_device *dev) { @@ -811,7 +816,7 @@ static void tun_setup(struct net_device *dev) tun->group = -1; dev->ethtool_ops = &tun_ethtool_ops; - dev->destructor = free_netdev; + dev->destructor = tun_free_netdev; } /* Trivial set of netlink ops to allow deleting tun or tap @@ -848,7 +853,7 @@ static void tun_sock_write_space(struct sock *sk) static void tun_sock_destruct(struct sock *sk) { - dev_put(container_of(sk, struct tun_sock, sk)->tun->dev); + free_netdev(container_of(sk, struct tun_sock, sk)->tun->dev); } static struct proto tun_proto = { @@ -920,11 +925,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) if (!sk) goto err_free_dev; - /* This ref count is for tun->sk. */ - dev_hold(dev); sock_init_data(&tun->socket, sk); sk->sk_write_space = tun_sock_write_space; - sk->sk_destruct = tun_sock_destruct; sk->sk_sndbuf = INT_MAX; sk->sk_sleep = &tfile->read_wait; @@ -942,11 +944,13 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) err = -EINVAL; err = register_netdevice(tun->dev); if (err < 0) - goto err_free_dev; + goto err_free_sk; + + sk->sk_destruct = tun_sock_destruct; err = tun_attach(tun, file); if (err < 0) - goto err_free_dev; + goto failed; } DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); @@ -1284,14 +1288,16 @@ static int tun_chr_close(struct inode *inode, struct file *file) __tun_detach(tun); /* If desireable, unregister the netdevice. */ - if (!(tun->flags & TUN_PERSIST)) { - sock_put(tun->sk); + if (!(tun->flags & TUN_PERSIST)) unregister_netdevice(tun->dev); - } rtnl_unlock(); } + tun = tfile->tun; + if (tun) + sock_put(tun->sk); + put_net(tfile->net); kfree(tfile); -- cgit v1.2.3 From c40af84a6726f63e35740d26f841992e8f31f92c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 19 Apr 2009 22:35:50 +0000 Subject: tun: Fix sk_sleep races when attaching/detaching As the sk_sleep wait queue actually lives in tfile, which may be detached from the tun device, bad things will happen when we use sk_sleep after detaching. Since the tun device is the persistent data structure here (when requested by the user), it makes much more sense to have the wait queue live there. There is no reason to have it in tfile at all since the only time we can wait is if we have a tun attached. In fact we already have a wait queue in tun_struct, so we might as well use it. Reported-by: Eric W. Biederman Tested-by: Christian Borntraeger Tested-by: Patrick McHardy Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/tun.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 95ae40ab8718..735bf41c654a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -93,7 +93,6 @@ struct tun_file { atomic_t count; struct tun_struct *tun; struct net *net; - wait_queue_head_t read_wait; }; struct tun_sock; @@ -331,7 +330,7 @@ static void tun_net_uninit(struct net_device *dev) /* Inform the methods they need to stop using the dev. */ if (tfile) { - wake_up_all(&tfile->read_wait); + wake_up_all(&tun->socket.wait); if (atomic_dec_and_test(&tfile->count)) __tun_detach(tun); } @@ -398,7 +397,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev) /* Notify and wake up reader process */ if (tun->flags & TUN_FASYNC) kill_fasync(&tun->fasync, SIGIO, POLL_IN); - wake_up_interruptible(&tun->tfile->read_wait); + wake_up_interruptible(&tun->socket.wait); return 0; drop: @@ -495,7 +494,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); - poll_wait(file, &tfile->read_wait, wait); + poll_wait(file, &tun->socket.wait, wait); if (!skb_queue_empty(&tun->readq)) mask |= POLLIN | POLLRDNORM; @@ -768,7 +767,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, goto out; } - add_wait_queue(&tfile->read_wait, &wait); + add_wait_queue(&tun->socket.wait, &wait); while (len) { current->state = TASK_INTERRUPTIBLE; @@ -799,7 +798,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, } current->state = TASK_RUNNING; - remove_wait_queue(&tfile->read_wait, &wait); + remove_wait_queue(&tun->socket.wait, &wait); out: tun_put(tun); @@ -867,7 +866,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) struct sock *sk; struct tun_struct *tun; struct net_device *dev; - struct tun_file *tfile = file->private_data; int err; dev = __dev_get_by_name(net, ifr->ifr_name); @@ -925,10 +923,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) if (!sk) goto err_free_dev; + init_waitqueue_head(&tun->socket.wait); sock_init_data(&tun->socket, sk); sk->sk_write_space = tun_sock_write_space; sk->sk_sndbuf = INT_MAX; - sk->sk_sleep = &tfile->read_wait; tun->sk = sk; container_of(sk, struct tun_sock, sk)->tun = tun; @@ -1270,7 +1268,6 @@ static int tun_chr_open(struct inode *inode, struct file * file) atomic_set(&tfile->count, 0); tfile->tun = NULL; tfile->net = get_net(current->nsproxy->net_ns); - init_waitqueue_head(&tfile->read_wait); file->private_data = tfile; return 0; } -- cgit v1.2.3 From 499a214ca2765522d6a59ff73825d40e7bb31510 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 28 Mar 2009 20:51:58 +0100 Subject: rt2x00: Don't free register information on suspend After suspend & resume the rt2x00 devices won't wakeup anymore due to a broken register information setup. The most important problem is the release of the EEPROM buffer which is completely cleared and never read again after the suspend. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00pci.c | 18 +----------------- drivers/net/wireless/rt2x00/rt2x00usb.c | 18 +----------------- 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 43fa0f849003..9730b4f8fd26 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -369,8 +369,6 @@ int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state) if (retval) return retval; - rt2x00pci_free_reg(rt2x00dev); - pci_save_state(pci_dev); pci_disable_device(pci_dev); return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); @@ -381,7 +379,6 @@ int rt2x00pci_resume(struct pci_dev *pci_dev) { struct ieee80211_hw *hw = pci_get_drvdata(pci_dev); struct rt2x00_dev *rt2x00dev = hw->priv; - int retval; if (pci_set_power_state(pci_dev, PCI_D0) || pci_enable_device(pci_dev) || @@ -390,20 +387,7 @@ int rt2x00pci_resume(struct pci_dev *pci_dev) return -EIO; } - retval = rt2x00pci_alloc_reg(rt2x00dev); - if (retval) - return retval; - - retval = rt2x00lib_resume(rt2x00dev); - if (retval) - goto exit_free_reg; - - return 0; - -exit_free_reg: - rt2x00pci_free_reg(rt2x00dev); - - return retval; + return rt2x00lib_resume(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00pci_resume); #endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 7d50ca82375e..501544882c2c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -702,8 +702,6 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state) if (retval) return retval; - rt2x00usb_free_reg(rt2x00dev); - /* * Decrease usbdev refcount. */ @@ -717,24 +715,10 @@ int rt2x00usb_resume(struct usb_interface *usb_intf) { struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); struct rt2x00_dev *rt2x00dev = hw->priv; - int retval; usb_get_dev(interface_to_usbdev(usb_intf)); - retval = rt2x00usb_alloc_reg(rt2x00dev); - if (retval) - return retval; - - retval = rt2x00lib_resume(rt2x00dev); - if (retval) - goto exit_free_reg; - - return 0; - -exit_free_reg: - rt2x00usb_free_reg(rt2x00dev); - - return retval; + return rt2x00lib_resume(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00usb_resume); #endif /* CONFIG_PM */ -- cgit v1.2.3 From 125143966f02bd7366eb9040aa74392d19955da8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2009 16:23:26 -0700 Subject: iwl3945-base.c: Add missing space to debug print "not" is not printed without a space after %pM Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8d738d752487..da61ecd62882 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4075,7 +4075,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!static_key) { sta_id = iwl3945_hw_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pMnot in station map.\n", + IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", addr); return -EINVAL; } -- cgit v1.2.3 From c3b93c878d7912a01467890bc0785071c2dc4bc1 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 17 Apr 2009 15:14:22 +0200 Subject: p54: deactivate broken powersave function This patch deactivates powersave in station mode. It does not work correctly yet, so the code does more harm than good. Reported-by: Johannes Berg Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 0c1b0577d4ee..c8f0232ee5e0 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2543,8 +2543,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) priv->basic_rate_mask = 0x15f; skb_queue_head_init(&priv->tx_queue); dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; -- cgit v1.2.3 From 230f7af0d8f6f2019e64920378b3b66e7d3e99a5 Mon Sep 17 00:00:00 2001 From: Joerg Albert Date: Sat, 18 Apr 2009 02:10:45 +0200 Subject: mwl8k: fix module re-insertion bug swap mwl8k_remove and mwl8k_shutdown functions to allow "rmmod mwl8k; modprobe mwl8k" Signed-off-by: Joerg Albert Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 57a0268d1bae..b5dbf6d9e517 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3720,12 +3720,12 @@ err_free_reg: return rc; } -static void __devexit mwl8k_remove(struct pci_dev *pdev) +static void __devexit mwl8k_shutdown(struct pci_dev *pdev) { printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__); } -static void __devexit mwl8k_shutdown(struct pci_dev *pdev) +static void __devexit mwl8k_remove(struct pci_dev *pdev) { struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct mwl8k_priv *priv; -- cgit v1.2.3 From 18aaab15f9a9cd4f20dc596aa38408c5e5d208ed Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Sat, 18 Apr 2009 09:33:55 -0400 Subject: MAC80211: Remove unused MAC80211_VERBOSE_SPECT_MGMT_DEBUG. Remove this unused Kconfig variable, which Intel apparently once promised to make use of but never did. Signed-off-by: Robert P. J. Day Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Kconfig | 7 ------- 1 file changed, 7 deletions(-) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index f3d9ae350fb6..ecc3faf9f11a 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -202,10 +202,3 @@ config MAC80211_DEBUG_COUNTERS and show them in debugfs. If unsure, say N. - -config MAC80211_VERBOSE_SPECT_MGMT_DEBUG - bool "Verbose Spectrum Management (IEEE 802.11h)debugging" - depends on MAC80211_DEBUG_MENU - ---help--- - Say Y here to print out verbose Spectrum Management (IEEE 802.11h) - debug messages. -- cgit v1.2.3 From e10a9dfc35ae6bd62bbb83df08297ea06b54d9ce Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 18 Apr 2009 17:12:18 +0200 Subject: ar9170usb: fix hang on resume This patch fixes a hang on resume when the filesystem is not available and request_firmware blocks. However, the device does not accept the firmware on resume. and it will exit with: > firmware part 1 upload failed (-71). > device is in a bad state. please reconnect it! Reported-by: Johannes Berg Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/usb.c | 110 +++++++++++++++++++++++++++++++------- 1 file changed, 90 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ar9170/usb.c b/drivers/net/wireless/ar9170/usb.c index c9e422ead925..fddda477095c 100644 --- a/drivers/net/wireless/ar9170/usb.c +++ b/drivers/net/wireless/ar9170/usb.c @@ -623,6 +623,39 @@ static int ar9170_usb_open(struct ar9170 *ar) return 0; } +static int ar9170_usb_init_device(struct ar9170_usb *aru) +{ + int err; + + err = ar9170_usb_alloc_rx_irq_urb(aru); + if (err) + goto err_out; + + err = ar9170_usb_alloc_rx_bulk_urbs(aru); + if (err) + goto err_unrx; + + err = ar9170_usb_upload_firmware(aru); + if (err) { + err = ar9170_echo_test(&aru->common, 0x60d43110); + if (err) { + /* force user invention, by disabling the device */ + err = usb_driver_set_configuration(aru->udev, -1); + dev_err(&aru->udev->dev, "device is in a bad state. " + "please reconnect it!\n"); + goto err_unrx; + } + } + + return 0; + +err_unrx: + ar9170_usb_cancel_urbs(aru); + +err_out: + return err; +} + static int ar9170_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -658,32 +691,16 @@ static int ar9170_usb_probe(struct usb_interface *intf, err = ar9170_usb_reset(aru); if (err) - goto err_unlock; + goto err_freehw; err = ar9170_usb_request_firmware(aru); if (err) - goto err_unlock; + goto err_freehw; - err = ar9170_usb_alloc_rx_irq_urb(aru); + err = ar9170_usb_init_device(aru); if (err) goto err_freefw; - err = ar9170_usb_alloc_rx_bulk_urbs(aru); - if (err) - goto err_unrx; - - err = ar9170_usb_upload_firmware(aru); - if (err) { - err = ar9170_echo_test(&aru->common, 0x60d43110); - if (err) { - /* force user invention, by disabling the device */ - err = usb_driver_set_configuration(aru->udev, -1); - dev_err(&aru->udev->dev, "device is in a bad state. " - "please reconnect it!\n"); - goto err_unrx; - } - } - err = ar9170_usb_open(ar); if (err) goto err_unrx; @@ -703,7 +720,7 @@ err_freefw: release_firmware(aru->init_values); release_firmware(aru->firmware); -err_unlock: +err_freehw: usb_set_intfdata(intf, NULL); usb_put_dev(udev); ieee80211_free_hw(ar->hw); @@ -730,12 +747,65 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) ieee80211_free_hw(aru->common.hw); } +#ifdef CONFIG_PM +static int ar9170_suspend(struct usb_interface *intf, + pm_message_t message) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + + if (!aru) + return -ENODEV; + + aru->common.state = AR9170_IDLE; + ar9170_usb_cancel_urbs(aru); + + return 0; +} + +static int ar9170_resume(struct usb_interface *intf) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + int err; + + if (!aru) + return -ENODEV; + + usb_unpoison_anchored_urbs(&aru->rx_submitted); + usb_unpoison_anchored_urbs(&aru->tx_submitted); + + /* + * FIXME: firmware upload will fail on resume. + * but this is better than a hang! + */ + + err = ar9170_usb_init_device(aru); + if (err) + goto err_unrx; + + err = ar9170_usb_open(&aru->common); + if (err) + goto err_unrx; + + return 0; + +err_unrx: + aru->common.state = AR9170_IDLE; + ar9170_usb_cancel_urbs(aru); + + return err; +} +#endif /* CONFIG_PM */ + static struct usb_driver ar9170_driver = { .name = "ar9170usb", .probe = ar9170_usb_probe, .disconnect = ar9170_usb_disconnect, .id_table = ar9170_usb_ids, .soft_unbind = 1, +#ifdef CONFIG_PM + .suspend = ar9170_suspend, + .resume = ar9170_resume, +#endif /* CONFIG_PM */ }; static int __init ar9170_init(void) -- cgit v1.2.3 From d91c01c757bd9659ac10549504586fae610265a4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 18 Apr 2009 21:53:15 +0300 Subject: nl80211: Make nl80211_send_mlme_event() atomic One of the code paths sending deauth/disassoc events ends up calling this function with rcu_read_lock held, so we must use GFP_ATOMIC in allocation routines. Reported-by: Johannes Berg Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 353e1a4ece83..2456e4ee445e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3334,7 +3334,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, struct sk_buff *msg; void *hdr; - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (!msg) return; @@ -3353,7 +3353,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, return; } - genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL); + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC); return; nla_put_failure: -- cgit v1.2.3 From ad935687dbe7307f5abd9e3f610a965a287324a9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 19 Apr 2009 08:47:19 +0300 Subject: mac80211: fix beacon loss detection after scan Currently beacon loss detection triggers after a scan. A probe request is sent and a message like this is printed to the log: wlan0: beacon loss from AP 00:12:17:e7:98:de - sending probe request But in fact there is no beacon loss, the beacons are just not received because of the ongoing scan. Fix it by updating last_beacon after the scan has finished. Reported-by: Jaswinder Singh Rajput Signed-off-by: Kalle Valo Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1619e0cd26e2..ccfc21aa0b61 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1913,9 +1913,17 @@ static void ieee80211_sta_work(struct work_struct *work) static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) { - if (sdata->vif.type == NL80211_IFTYPE_STATION) + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + /* + * Need to update last_beacon to avoid beacon loss + * test to trigger. + */ + sdata->u.mgd.last_beacon = jiffies; + + queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work); + } } /* interface setup */ -- cgit v1.2.3 From 7e0986c17f695952ce5d61ed793ce048ba90a661 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 19 Apr 2009 13:22:11 +0200 Subject: mac80211: fix basic rate bitmap calculation "mac80211: fix basic rates setting from association response" introduced a copy/paste error. Unfortunately, this not just leads to wrong data being passed to the driver but is remotely exploitable for some hardware or driver combinations. Signed-off-by: Johannes Berg Cc: stable@kernel.org [2.6.29] Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ccfc21aa0b61..132938b073dc 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1366,7 +1366,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, for (i = 0; i < elems.ext_supp_rates_len; i++) { int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; - bool is_basic = !!(elems.supp_rates[i] & 0x80); + bool is_basic = !!(elems.ext_supp_rates[i] & 0x80); if (rate > 110) have_higher_than_11mbit = true; -- cgit v1.2.3 From 62cedd11f63c99efd2962fb69763a09e2778f6e6 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 20 Apr 2009 14:52:29 -0700 Subject: tg3: Fix SEEPROM accesses The recent NVRAM patches sanitized how the driver deals with NVRAM data, but they failed to bring the SEEPROM interfaces inline with the new strategy. This patch brings the SEEPROM interfaces up to date. This patch also reverts commit 0d489ffb76de0fe804cf06a9d4d11fa7342d74b9 ("tg3: fix big endian MAC address collection failure"). Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Tested-by: Robin Holt Tested-by: James Bottomley Signed-off-by: David S. Miller --- drivers/net/tg3.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7a837c465960..201be425643a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2190,7 +2190,14 @@ static int tg3_nvram_read_using_eeprom(struct tg3 *tp, if (!(tmp & EEPROM_ADDR_COMPLETE)) return -EBUSY; - *val = tr32(GRC_EEPROM_DATA); + tmp = tr32(GRC_EEPROM_DATA); + + /* + * The data will always be opposite the native endian + * format. Perform a blind byteswap to compensate. + */ + *val = swab32(tmp); + return 0; } @@ -10663,7 +10670,13 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, memcpy(&data, buf + i, 4); - tw32(GRC_EEPROM_DATA, be32_to_cpu(data)); + /* + * The SEEPROM interface expects the data to always be opposite + * the native endian format. We accomplish this by reversing + * all the operations that would have been performed on the + * data from a call to tg3_nvram_read_be32(). + */ + tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data))); val = tr32(GRC_EEPROM_ADDR); tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); @@ -12443,13 +12456,8 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) /* Next, try NVRAM. */ if (!tg3_nvram_read_be32(tp, mac_offset + 0, &hi) && !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) { - dev->dev_addr[0] = ((hi >> 16) & 0xff); - dev->dev_addr[1] = ((hi >> 24) & 0xff); - dev->dev_addr[2] = ((lo >> 0) & 0xff); - dev->dev_addr[3] = ((lo >> 8) & 0xff); - dev->dev_addr[4] = ((lo >> 16) & 0xff); - dev->dev_addr[5] = ((lo >> 24) & 0xff); - + memcpy(&dev->dev_addr[0], ((char *)&hi) + 2, 2); + memcpy(&dev->dev_addr[2], (char *)&lo, sizeof(lo)); } /* Finally just fetch it out of the MAC control regs. */ else { -- cgit v1.2.3