From 85b442e378ac3413e269a70a0031727ef121bd2a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 22 Apr 2008 14:03:32 -0400 Subject: [PATCH 01/20] prism54: fix regression with missing carrier in AP-mode This fixes a regression introduced by commit 7b463ced6 (prism54: set carrier flags correctly) which causes the device to come up without a carrier in AP-mode. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/islpci_dev.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 04c2638d75ad..9196825ed1b5 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -388,8 +388,15 @@ islpci_open(struct net_device *ndev) netif_start_queue(ndev); - /* Turn off carrier unless we know we have associated */ - netif_carrier_off(ndev); + /* Turn off carrier if in STA or Ad-hoc mode. It will be turned on + * once the firmware receives a trap of being associated + * (GEN_OID_LINKSTATE). In other modes (AP or WDS or monitor) we + * should just leave the carrier on as its expected the firmware + * won't send us a trigger. */ + if (priv->iw_mode == IW_MODE_INFRA || priv->iw_mode == IW_MODE_ADHOC) + netif_carrier_off(ndev); + else + netif_carrier_on(ndev); return 0; } From bb55bdd512905f35f9d7dfe65d1f16014e1f9b2f Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 1 May 2008 15:58:17 -0700 Subject: [PATCH 02/20] fix irq flags in mac80211 code A file in the net/mac80211 directory uses "int" for flags. This can cause hard to find bugs on some architectures. This patch converts the flags to use "long" instead. This bug was discovered by doing an allyesconfig make on the -rt kernel where checks are done to ensure all flags are of size sizeof(long). Signed-off-by: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- net/mac80211/rc80211_pid_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index ae75d4178739..ff5c380f3c13 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c @@ -85,7 +85,7 @@ static int rate_control_pid_events_open(struct inode *inode, struct file *file) struct rc_pid_sta_info *sinfo = inode->i_private; struct rc_pid_event_buffer *events = &sinfo->events; struct rc_pid_events_file_info *file_info; - unsigned int status; + unsigned long status; /* Allocate a state struct */ file_info = kmalloc(sizeof(*file_info), GFP_KERNEL); @@ -135,7 +135,7 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, char pb[RC_PID_PRINT_BUF_SIZE]; int ret; int p; - unsigned int status; + unsigned long status; /* Check if there is something to read. */ if (events->next_entry == file_info->next_entry) { From d5251aea1539ec89dd567e75169c568b5243b6fa Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 2 May 2008 09:56:34 -0400 Subject: [PATCH 03/20] wavelan: avoid index past end of array if DEBUG_SHOW_UNUSED is defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by Daniel Marjamäki here: http://bugzilla.kernel.org/show_bug.cgi?id=10588 Signed-off-by: John W. Linville --- drivers/net/wireless/wavelan.c | 4 ++-- drivers/net/wireless/wavelan_cs.c | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index 03384a43186b..49ae97003952 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -908,9 +908,9 @@ static void wv_psa_show(psa_t * p) p->psa_call_code[3], p->psa_call_code[4], p->psa_call_code[5], p->psa_call_code[6], p->psa_call_code[7]); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n", + printk(KERN_DEBUG "psa_reserved[]: %02X:%02X\n", p->psa_reserved[0], - p->psa_reserved[1], p->psa_reserved[2], p->psa_reserved[3]); + p->psa_reserved[1]); #endif /* DEBUG_SHOW_UNUSED */ printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status); printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index baf74015751c..b584c0ecc62d 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -1074,11 +1074,9 @@ wv_psa_show(psa_t * p) p->psa_call_code[6], p->psa_call_code[7]); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n", + printk(KERN_DEBUG "psa_reserved[]: %02X:%02X\n", p->psa_reserved[0], - p->psa_reserved[1], - p->psa_reserved[2], - p->psa_reserved[3]); + p->psa_reserved[1]); #endif /* DEBUG_SHOW_UNUSED */ printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status); printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]); From 78520cad4b222d81fa18f2dcfa52394d8d1722b0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 3 May 2008 01:04:47 +0200 Subject: [PATCH 04/20] mac80211: fix debugfs default key oops Under certain circumstances (in AP mode) the debugfs function that is supposed to add the default key symlink can encounter a NULL default_key pointer. This patch makes it handle that situtation gracefully. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_key.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 879e7210458a..19efc3a6a932 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -255,14 +255,23 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key) void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) { char buf[50]; + struct ieee80211_key *key; if (!sdata->debugfsdir) return; - sprintf(buf, "../keys/%d", sdata->default_key->debugfs.cnt); - sdata->debugfs.default_key = - debugfs_create_symlink("default_key", sdata->debugfsdir, buf); + /* this is running under the key lock */ + + key = sdata->default_key; + if (key) { + sprintf(buf, "../keys/%d", key->debugfs.cnt); + sdata->debugfs.default_key = + debugfs_create_symlink("default_key", + sdata->debugfsdir, buf); + } else + ieee80211_debugfs_key_remove_default(sdata); } + void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) { if (!sdata) From 6243065d308ab566aa318a8adef853bc0418896d Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 5 May 2008 10:22:46 +0800 Subject: [PATCH 05/20] iwlwifi: fix compile error when CONFIG_MAC80211_DEBUGFS is not selected Make iwl4965_lq_sta->drv available even without CONFIG_MAC80211_DEBUGFS. Signed-off-by: Yi Zhu Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index b608e1ca8b40..c9847b1a67f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -163,8 +163,8 @@ struct iwl4965_lq_sta { struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; #endif struct iwl4965_rate dbg_fixed; - struct iwl_priv *drv; #endif + struct iwl_priv *drv; }; static void rs_rate_scale_perform(struct iwl_priv *priv, From 78720897459a0ed3843c80e9bd9ef1b2f7ae5c8f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 5 May 2008 17:23:31 +0200 Subject: [PATCH 06/20] rt2x00: Don't use pskb_expand_head() rt2x00pci allocates DMA for descriptor and data, rt61pci doesn't use this for the beacon, but it can use the descriptor part as temporary buffer instead of using pskb_expand_head(). Using this temporary buffer is obviously much better then reallocating the skb buffer... At the same time we can set the data length for the beacon queue at 0, to make sure no DMA is allocated for data (but just for the descriptor). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 31 ++++++++++----------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index ae12dcdd3c24..14bc7b281659 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2366,6 +2366,7 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(control->vif); + struct queue_entry_priv_pci_tx *priv_tx; struct skb_frame_desc *skbdesc; unsigned int beacon_base; u32 reg; @@ -2373,21 +2374,8 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, if (unlikely(!intf->beacon)) return -ENOBUFS; - /* - * We need to append the descriptor in front of the - * beacon frame. - */ - if (skb_headroom(skb) < intf->beacon->queue->desc_size) { - if (pskb_expand_head(skb, intf->beacon->queue->desc_size, - 0, GFP_ATOMIC)) - return -ENOMEM; - } - - /* - * Add the descriptor in front of the skb. - */ - skb_push(skb, intf->beacon->queue->desc_size); - memset(skb->data, 0, intf->beacon->queue->desc_size); + priv_tx = intf->beacon->priv_data; + memset(priv_tx->desc, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor @@ -2395,9 +2383,9 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - skbdesc->data = skb->data + intf->beacon->queue->desc_size; - skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; - skbdesc->desc = skb->data; + skbdesc->data = skb->data; + skbdesc->data_len = skb->len; + skbdesc->desc = priv_tx->desc; skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; @@ -2425,7 +2413,10 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, */ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, - skb->data, skb->len); + skbdesc->desc, skbdesc->desc_len); + rt2x00pci_register_multiwrite(rt2x00dev, + beacon_base + skbdesc->desc_len, + skbdesc->data, skbdesc->data_len); rt61pci_kick_tx_queue(rt2x00dev, control->queue); return 0; @@ -2490,7 +2481,7 @@ static const struct data_queue_desc rt61pci_queue_tx = { static const struct data_queue_desc rt61pci_queue_bcn = { .entry_num = 4 * BEACON_ENTRIES, - .data_size = MGMT_FRAME_SIZE, + .data_size = 0, /* No DMA required for beacons */ .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci_tx), }; From ed499983b88d138848ec9e4d104fd86a5ef0c183 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 5 May 2008 17:23:47 +0200 Subject: [PATCH 07/20] rt2x00: Fix broken recover-on-error path During initialization the initialize() callback function in rt2x00pci and rt2x00usb will cleanup the mess they made. rt2x00lib shouldn't call uninitialize because the callback function already cleaned up _and_ the DEVICE_INITIALIZED isn't set which causes the rt2x00lib_uninitialize() to halt directly anyway. All that is required to be cleaned up by rt2x00lib is the queue, and that can be done by calling rt2x00queue_uninitialize() directly. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 8d8657fb64dd..b22c02737185 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1032,8 +1032,10 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) * Initialize the device. */ status = rt2x00dev->ops->lib->initialize(rt2x00dev); - if (status) - goto exit; + if (status) { + rt2x00queue_uninitialize(rt2x00dev); + return status; + } __set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags); @@ -1043,11 +1045,6 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) rt2x00rfkill_register(rt2x00dev); return 0; - -exit: - rt2x00lib_uninitialize(rt2x00dev); - - return status; } int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) From b30cdfc517b06f5d3f7a5e90626931140b2caece Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 5 May 2008 17:24:03 +0200 Subject: [PATCH 08/20] rt2x00: Clean up error handling of PCI queue DMA allocation. When, for some reason, the rt2x00pci module fails to allocate DMA memory for the queues, it tries to undo the complete initialization of the PCI device, including freeing of the irq. This results in the following error in dmesg, as the irq hadn't been requested yet: [ 78.123456] Trying to free already-free IRQ 17 Fix this by implementing proper error handling code, instead of just using the full uninitialization function. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 7867ec64bd2c..971af2546b59 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -314,13 +314,14 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) if (status) { ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", pci_dev->irq, status); - return status; + goto exit; } return 0; exit: - rt2x00pci_uninitialize(rt2x00dev); + queue_for_each(rt2x00dev, queue) + rt2x00pci_free_queue_dma(rt2x00dev, queue); return status; } From df44205455773852a6af10a7c6ed768fe8a86b31 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 5 May 2008 20:40:35 +0200 Subject: [PATCH 09/20] mac80211: Don't encrypt beacons mac80211 should set the IEEE80211_TX_CTL_DO_NOT_ENCRYPT flag in tx_control structure to inform drivers not to encrypt the beacon. Drivers that only check for that flag before accessing the hw_key field, will otherwise cause a NULL pointer dereference since that field is not configured for beacons. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- net/mac80211/tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f35eaea98e73..28d8bd53bd3a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1898,6 +1898,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; control->flags |= IEEE80211_TXCTL_NO_ACK; + control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT; control->retry_limit = 1; control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; } From ef269254772a0d2253c85cafe160e3f6528eb292 Mon Sep 17 00:00:00 2001 From: Luis Carlos Cobo Date: Mon, 5 May 2008 12:02:35 -0700 Subject: [PATCH 10/20] mac80211: fix incorrect mesh header length This should have been updated at the same time we were transitioning from 3 byte to 4 byte mesh sequence number. Pointed out by Johannes Berg. Signed-off-by: Luis Carlos Cobo Signed-off-by: John W. Linville --- net/mac80211/mesh.c | 2 +- net/mac80211/util.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index f76bc26ae4d2..697ef67f96b6 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -397,7 +397,7 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum); sdata->u.sta.mesh_seqnum++; - return 5; + return 6; } void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index cc9f715c7bfc..24a465c4df09 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -153,15 +153,15 @@ int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) /* 7.1.3.5a.2 */ switch (ae) { case 0: - return 5; + return 6; case 1: - return 11; + return 12; case 2: - return 17; + return 18; case 3: - return 23; + return 24; default: - return 5; + return 6; } } From 69687a0b9934942e61bf8148c242adea87183a5b Mon Sep 17 00:00:00 2001 From: Luis Carlos Cobo Date: Mon, 5 May 2008 12:29:42 -0700 Subject: [PATCH 11/20] mac80211: fix access to null skb Without this patch, if xmit_skb is null but net_ratelimit() returns 0 we would go to the else branch and access the null xmit_skb. Pointed out by Johannes Berg. Signed-off-by: Luis Carlos Cobo Signed-off-by: John W. Linville --- net/mac80211/rx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 02f436a86061..9c57b3af0244 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1305,11 +1305,11 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(skb->data)) { if (*mesh_ttl > 0) { xmit_skb = skb_copy(skb, GFP_ATOMIC); - if (!xmit_skb && net_ratelimit()) + if (xmit_skb) + xmit_skb->pkt_type = PACKET_OTHERHOST; + else if (net_ratelimit()) printk(KERN_DEBUG "%s: failed to clone " "multicast frame\n", dev->name); - else - xmit_skb->pkt_type = PACKET_OTHERHOST; } else IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta, dropped_frames_ttl); From 812714d741750038004da505074c9158e9dee270 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 6 May 2008 12:52:07 +0200 Subject: [PATCH 12/20] mac80211: mesh hwmp: fix kfree(skb) Signed-off-by: Patrick McHardy Signed-off-by: John W. Linville --- net/mac80211/mesh_hwmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 3df809222d1c..af0cd1e3e213 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -120,7 +120,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, *pos++ = WLAN_EID_PREP; break; default: - kfree(skb); + kfree_skb(skb); return -ENOTSUPP; break; } From f84e71a94cb5f88d86ab50c251e09379925b80b9 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 6 May 2008 18:46:36 +0400 Subject: [PATCH 13/20] Fix GFP_KERNEL allocation under read lock. The mesh_path_add() read-locks the pathtbl_resize_lock and calls kmalloc with GFP_KERNEL mask. Fix it and move the endadd2 label lower. It should be _before_ the if() beyond, but it makes no sense for it being there, so I move it right after this if(). Signed-off-by: Pavel Emelyanov Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 5845dc21ce85..727aa528c831 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -158,14 +158,14 @@ int mesh_path_add(u8 *dst, struct net_device *dev) if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) return -ENOSPC; - read_lock(&pathtbl_resize_lock); - new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); if (!new_mpath) { atomic_dec(&sdata->u.sta.mpaths); err = -ENOMEM; goto endadd2; } + + read_lock(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); new_mpath->dev = dev; new_mpath->flags = 0; @@ -202,7 +202,6 @@ int mesh_path_add(u8 *dst, struct net_device *dev) endadd: spin_unlock(&mesh_paths->hashwlock[hash_idx]); -endadd2: read_unlock(&pathtbl_resize_lock); if (!err && grow) { struct mesh_table *oldtbl, *newtbl; @@ -219,6 +218,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) mesh_table_free(oldtbl, false); write_unlock(&pathtbl_resize_lock); } +endadd2: return err; } From 0eb03d5a14377eecf6ed0ebf3cc2c9f48c12c7c6 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 6 May 2008 18:49:02 +0400 Subject: [PATCH 14/20] Fix not checked kmalloc() result. The new_node kmallocation is not checked for success, so add this check. BTW, it also happens under the read_lock. Signed-off-by: Pavel Emelyanov Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 727aa528c831..1d2d051e5976 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -164,13 +164,19 @@ int mesh_path_add(u8 *dst, struct net_device *dev) err = -ENOMEM; goto endadd2; } + new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); + if (!new_node) { + kfree(new_mpath); + atomic_dec(&sdata->u.sta.mpaths); + err = -ENOMEM; + goto endadd2; + } read_lock(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); new_mpath->dev = dev; new_mpath->flags = 0; skb_queue_head_init(&new_mpath->frame_queue); - new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); new_node->mpath = new_mpath; new_mpath->timer.data = (unsigned long) new_mpath; new_mpath->timer.function = mesh_path_timer; From 6d6936e2ea82ebcbdd12d489b7b5ccf430de52f1 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 6 May 2008 18:51:31 +0400 Subject: [PATCH 15/20] Fix potential scheduling while atomic in mesh_path_add. Calling synchronize_rcu() under write-lock-ed pathtbl_resize_lock may result in this warning (and other side effects). It looks safe just dropping this lock before calling synchronize_rcu. Signed-off-by: Pavel Emelyanov Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 1d2d051e5976..99c2d360888e 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -220,9 +220,10 @@ int mesh_path_add(u8 *dst, struct net_device *dev) return -ENOMEM; } rcu_assign_pointer(mesh_paths, newtbl); + write_unlock(&pathtbl_resize_lock); + synchronize_rcu(); mesh_table_free(oldtbl, false); - write_unlock(&pathtbl_resize_lock); } endadd2: return err; From dbabad0c9c026dea3ba803cbd9d768cdffc68e32 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 8 May 2008 01:43:59 +0200 Subject: [PATCH 16/20] zd1211rw: fix potential use-after-free bug zd_mac_tx_to_dev() could potentially free the skb, or hand it off to mac80211 which might free it. Hence, this code needs to get the usb pointer out of skb->cb before handing it off to that function. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 5316074f39f0..12e24f04dddf 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -889,9 +889,13 @@ static void tx_urb_complete(struct urb *urb) } free_urb: skb = (struct sk_buff *)urb->context; - zd_mac_tx_to_dev(skb, urb->status); + /* + * grab 'usb' pointer before handing off the skb (since + * it might be freed by zd_mac_tx_to_dev or mac80211) + */ cb = (struct zd_tx_skb_control_block *)skb->cb; usb = &zd_hw_mac(cb->hw)->chip.usb; + zd_mac_tx_to_dev(skb, urb->status); free_tx_urb(usb, urb); tx_dec_submitted_urbs(usb); return; From c0186078b78839a8bdb385fa07a816c2f348a49d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 8 May 2008 11:34:05 +0800 Subject: [PATCH 17/20] iwlwifi: Fix frequency in rx_status fill This patch fixes a bug in RX path, the frequency was wrongly set in the ieee80211_rx_status. This bug led to an empty scan list in A band. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d3406830c8e3..62a3d8f8563e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -666,7 +666,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, rx_status.flag = 0; rx_status.mactime = le64_to_cpu(rx_end->timestamp); rx_status.freq = - ieee80211_frequency_to_channel(le16_to_cpu(rx_hdr->channel)); + ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel)); rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 17f629fb96ff..bf19eb8aafd0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3978,7 +3978,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, rx_status.mactime = le64_to_cpu(rx_start->timestamp); rx_status.freq = - ieee80211_frequency_to_channel(le16_to_cpu(rx_start->channel)); + ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel)); rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; rx_status.rate_idx = From 36d16ae73becc5978fe22866e9ab66b509211afe Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 8 May 2008 13:34:07 +0200 Subject: [PATCH 18/20] mac80211: fix association with some APs Some APs refuse association if the supported rates contained in the association request do not match its own supported rates. This patch introduces a new function which builds the intersection between the AP's supported rates and the client's supported rates to work around such problems. The same approach is already used in ipw2200 for example. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 68 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a5e5c31c23ab..4adba09e80ca 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -665,6 +665,26 @@ static void ieee80211_authenticate(struct net_device *dev, mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); } +static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, + struct ieee80211_supported_band *sband, + u64 *rates) +{ + int i, j, count; + *rates = 0; + count = 0; + for (i = 0; i < bss->supp_rates_len; i++) { + int rate = (bss->supp_rates[i] & 0x7F) * 5; + + for (j = 0; j < sband->n_bitrates; j++) + if (sband->bitrates[j].bitrate == rate) { + *rates |= BIT(j); + count++; + break; + } + } + + return count; +} static void ieee80211_send_assoc(struct net_device *dev, struct ieee80211_if_sta *ifsta) @@ -673,11 +693,12 @@ static void ieee80211_send_assoc(struct net_device *dev, struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, *ies; - int i, len; + int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_sta_bss *bss; int wmm = 0; struct ieee80211_supported_band *sband; + u64 rates = 0; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ifsta->extra_ie_len + @@ -740,24 +761,39 @@ static void ieee80211_send_assoc(struct net_device *dev, *pos++ = ifsta->ssid_len; memcpy(pos, ifsta->ssid, ifsta->ssid_len); - len = sband->n_bitrates; - if (len > 8) - len = 8; - pos = skb_put(skb, len + 2); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = len; - for (i = 0; i < len; i++) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - } + /* all supported rates should be added here but some APs + * (e.g. D-Link DAP 1353 in b-only mode) don't like that + * Therefore only add rates the AP supports */ + rates_len = ieee80211_compatible_rates(bss, sband, &rates); + supp_rates_len = rates_len; + if (supp_rates_len > 8) + supp_rates_len = 8; - if (sband->n_bitrates > len) { - pos = skb_put(skb, sband->n_bitrates - len + 2); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = sband->n_bitrates - len; - for (i = len; i < sband->n_bitrates; i++) { + len = sband->n_bitrates; + pos = skb_put(skb, supp_rates_len + 2); + *pos++ = WLAN_EID_SUPP_RATES; + *pos++ = supp_rates_len; + + count = 0; + for (i = 0; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { int rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); + if (++count == 8) + break; + } + } + + if (count == 8) { + pos = skb_put(skb, rates_len - count + 2); + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = rates_len - count; + + for (i++; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } } } From 6fc7431dc0775f21ad7a7a39c2ad0290291a56ea Mon Sep 17 00:00:00 2001 From: Masakazu Mokuno Date: Mon, 12 May 2008 13:50:28 +0900 Subject: [PATCH 19/20] PS3: gelic: fix memory leak This fixes the bug that the I/O buffer is not freed at the driver removal. Signed-off-by: Masakazu Mokuno Signed-off-by: John W. Linville --- drivers/net/ps3_gelic_wireless.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index 0d32123085e9..1dae1f2ed813 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -2474,6 +2474,8 @@ static void gelic_wl_free(struct gelic_wl_info *wl) pr_debug("%s: <-\n", __func__); + free_page((unsigned long)wl->buf); + pr_debug("%s: destroy queues\n", __func__); destroy_workqueue(wl->eurus_cmd_queue); destroy_workqueue(wl->event_queue); From a4278e18e7e497b76781492d010035c3c36f7403 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Mon, 12 May 2008 09:02:24 -0400 Subject: [PATCH 20/20] mac80211: add missing newlines in printk() Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- net/mac80211/rx.c | 6 +++--- net/mac80211/wme.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9c57b3af0244..1958bfb361c6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1395,7 +1395,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) padding = ((4 - subframe_len) & 0x3); /* the last MSDU has no padding */ if (subframe_len > remaining) { - printk(KERN_DEBUG "%s: wrong buffer size", dev->name); + printk(KERN_DEBUG "%s: wrong buffer size\n", dev->name); return RX_DROP_UNUSABLE; } @@ -1418,7 +1418,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) eth = (struct ethhdr *) skb_pull(skb, ntohs(len) + padding); if (!eth) { - printk(KERN_DEBUG "%s: wrong buffer size ", + printk(KERN_DEBUG "%s: wrong buffer size\n", dev->name); dev_kfree_skb(frame); return RX_DROP_UNUSABLE; @@ -1952,7 +1952,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (!skb_new) { if (net_ratelimit()) printk(KERN_DEBUG "%s: failed to copy " - "multicast frame for %s", + "multicast frame for %s\n", wiphy_name(local->hw.wiphy), prev->dev->name); continue; diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 64faa3dc488f..dc1598b86004 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -394,7 +394,8 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) qd->handle); if (!q->queues[i]) { q->queues[i] = &noop_qdisc; - printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i); + printk(KERN_ERR "%s child qdisc %i creation failed\n", + dev->name, i); } }