diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index d7691c482835888f80753b6be1fe70e72b4816f9..30ec235e6935505a13057f18617f12038e6051d6 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -531,6 +531,23 @@ config PRISM54
 	  say M here and read <file:Documentation/modules.txt>.  The module
 	  will be called prism54.ko.
 
+config USB_ZD1201
+	tristate "USB ZD1201 based Wireless device support"
+	depends on USB && NET_RADIO
+	select FW_LOADER
+	---help---
+	  Say Y if you want to use wireless LAN adapters based on the ZyDAS
+	  ZD1201 chip.
+
+	  This driver makes the adapter appear as a normal Ethernet interface,
+	  typically on wlan0.
+
+	  The zd1201 device requires external firmware to be loaded.
+	  This can be found at http://linux-lc100020.sourceforge.net/
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called zd1201.
+
 source "drivers/net/wireless/hostap/Kconfig"
 source "drivers/net/wireless/bcm43xx/Kconfig"
 
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index c86779879361881709f90b17abf470ea0667f5ec..512603de309a4301fa26cf81a2cfc33b6e402a5c 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -40,3 +40,5 @@ obj-$(CONFIG_BCM43XX)		+= bcm43xx/
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
 obj-$(CONFIG_PCMCIA_WL3501)	+= wl3501_cs.o
+
+obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index c0502905a9564e25f0a103378f24a68d782df3c8..736dde96c4a38d81762bcec317bebff1bfd0b17a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -3555,7 +3555,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
 	unsigned long flags;
 	int keyidx;
 	
-	dprintk(KERN_INFO PFX "set security called\n");
+	dprintk(KERN_INFO PFX "set security called");
 
 	bcm43xx_lock_mmio(bcm, flags);
 
@@ -3568,24 +3568,25 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
 	
 	if (sec->flags & SEC_ACTIVE_KEY) {
 		secinfo->active_key = sec->active_key;
-		dprintk(KERN_INFO PFX "   .active_key = %d\n", sec->active_key);
+		dprintk(", .active_key = %d", sec->active_key);
 	}
 	if (sec->flags & SEC_UNICAST_GROUP) {
 		secinfo->unicast_uses_group = sec->unicast_uses_group;
-		dprintk(KERN_INFO PFX "   .unicast_uses_group = %d\n", sec->unicast_uses_group);
+		dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group);
 	}
 	if (sec->flags & SEC_LEVEL) {
 		secinfo->level = sec->level;
-		dprintk(KERN_INFO PFX "   .level = %d\n", sec->level);
+		dprintk(", .level = %d", sec->level);
 	}
 	if (sec->flags & SEC_ENABLED) {
 		secinfo->enabled = sec->enabled;
-		dprintk(KERN_INFO PFX "   .enabled = %d\n", sec->enabled);
+		dprintk(", .enabled = %d", sec->enabled);
 	}
 	if (sec->flags & SEC_ENCRYPT) {
 		secinfo->encrypt = sec->encrypt;
-		dprintk(KERN_INFO PFX "   .encrypt = %d\n", sec->encrypt);
+		dprintk(", .encrypt = %d", sec->encrypt);
 	}
+	dprintk("\n");
 	if (bcm->initialized && !bcm->ieee->host_encrypt) {
 		if (secinfo->enabled) {
 			/* upload WEP keys to hardware */
diff --git a/drivers/usb/net/zd1201.c b/drivers/net/wireless/zd1201.c
similarity index 97%
rename from drivers/usb/net/zd1201.c
rename to drivers/net/wireless/zd1201.c
index 9b1e4ed1d07e7ab7afda3617406a846ef7fb6fc7..662ecc8a33ff9f6559a32c8dff38d25ff5b793ad 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -33,7 +33,7 @@ static struct usb_device_id zd1201_table[] = {
 	{}
 };
 
-static int ap = 0;	/* Are we an AP or a normal station? */
+static int ap;	/* Are we an AP or a normal station? */
 
 #define ZD1201_VERSION	"0.15"
 
@@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(usb, zd1201_table);
 static int zd1201_fw_upload(struct usb_device *dev, int apfw)
 {
 	const struct firmware *fw_entry;
-	char* data;
+	char *data;
 	unsigned long len;
 	int err;
 	unsigned char ret;
@@ -65,7 +65,7 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
 	if (err) {
 		dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
 		dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
-		dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n");
+		dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n");
 		return err;
 	}
 
@@ -94,12 +94,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
 	    USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
 	if (err < 0)
 		goto exit;
-                                                                                                                                                                
+
 	err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
 	    USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
 	if (err < 0)
 		goto exit;
-                                                                                                                                                                                                                                                                                        
+
 	if (ret & 0x80) {
 		err = -EIO;
 		goto exit;
@@ -166,13 +166,13 @@ static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0,
 		return -ENOMEM;
 	}
 	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
-	     command, 16, zd1201_usbfree, zd);
+			  command, 16, zd1201_usbfree, zd);
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
 		kfree(command);
 		usb_free_urb(urb);
 	}
-	
+
 	return ret;
 }
 
@@ -316,7 +316,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
 		fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
 		seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
 
-		if(zd->monitor) {
+		if (zd->monitor) {
 			if (datalen < 24)
 				goto resubmit;
 			if (!(skb = dev_alloc_skb(datalen+24)))
@@ -364,7 +364,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
 				goto resubmit;
 			}
 			hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
-				if(frag->seq == (seq&IEEE80211_SCTL_SEQ))
+				if (frag->seq == (seq&IEEE80211_SCTL_SEQ))
 					break;
 			if (!frag)
 				goto resubmit;
@@ -376,7 +376,6 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
 				goto resubmit;
 			hlist_del_init(&frag->fnode);
 			kfree(frag);
-			/* Fallthrough */
 		} else {
 			if (datalen<14)
 				goto resubmit;
@@ -422,7 +421,7 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
 	int rid_fid;
 	int length;
 	unsigned char *pdata;
-	
+
 	zd->rxdatas = 0;
 	err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
 	if (err)
@@ -471,11 +470,11 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
 	length = zd->rxlen;
 
 	do {
-		int  actual_length;
+		int actual_length;
 
 		actual_length = (length > 64) ? 64 : length;
 
-		if(pdata[0] != 0x3) {
+		if (pdata[0] != 0x3) {
 			dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
 			    pdata[0]);
 			return -EINVAL;
@@ -487,11 +486,10 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
 		}
 
 		/* Skip the 4 bytes header (RID length and RID) */
-		if(i == 0) {
+		if (i == 0) {
 			pdata += 8;
 			actual_length -= 8;
-		}
-		else {
+		} else {
 			pdata += 4;
 			actual_length -= 4;
 		}
@@ -620,7 +618,7 @@ static int zd1201_drvr_start(struct zd1201 *zd)
 	short max;
 	__le16 zdmax;
 	unsigned char *buffer;
-	
+
 	buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL);
 	if (!buffer)
 		return -ENOMEM;
@@ -632,7 +630,7 @@ static int zd1201_drvr_start(struct zd1201 *zd)
 	err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
 	if (err)
 		goto err_buffer;
-	
+
 	err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
 	if (err)
 		goto err_urb;
@@ -684,7 +682,7 @@ static int zd1201_enable(struct zd1201 *zd)
 static int zd1201_disable(struct zd1201 *zd)
 {
 	int err;
-	
+
 	if (!zd->mac_enabled)
 		return 0;
 	if (zd->monitor) {
@@ -764,7 +762,6 @@ static int zd1201_net_open(struct net_device *dev)
 static int zd1201_net_stop(struct net_device *dev)
 {
 	netif_stop_queue(dev);
-	
 	return 0;
 }
 
@@ -915,7 +912,6 @@ static int zd1201_get_name(struct net_device *dev,
     struct iw_request_info *info, char *name, char *extra)
 {
 	strcpy(name, "IEEE 802.11b");
-
 	return 0;
 }
 
@@ -1013,11 +1009,10 @@ static int zd1201_set_mode(struct net_device *dev,
 			if (err)
 				return err;
 	}
-	zd->monitor=monitor;
+	zd->monitor = monitor;
 	/* If monitor mode is set we don't actually turn it on here since it
 	 * is done during mac reset anyway (see zd1201_mac_enable).
 	 */
-
 	zd1201_mac_reset(zd);
 
 	return 0;
@@ -1117,7 +1112,7 @@ static int zd1201_get_wap(struct net_device *dev,
 		zd->iwstats.qual.updated = 2;
 	}
 
-	return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6);
+	return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6);
 }
 
 static int zd1201_set_scan(struct net_device *dev,
@@ -1275,7 +1270,7 @@ static int zd1201_set_rate(struct net_device *dev,
 	if (!rrq->fixed) { /* Also enable all lower bitrates */
 		rate |= rate-1;
 	}
-	
+
 	err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
 	if (err)
 		return err;
@@ -1486,7 +1481,7 @@ static int zd1201_get_encode(struct net_device *dev,
 		return -EINVAL;
 
 	erq->flags |= i+1;
-	
+
 	erq->length = zd->encode_keylen[i];
 	memcpy(key, zd->encode_keys[i], erq->length);
 
@@ -1529,11 +1524,7 @@ static int zd1201_set_power(struct net_device *dev,
 		return -EINVAL;
 	}
 out:
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
-	if (err)
-		return err;
-
-	return 0;
+	return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
 }
 
 static int zd1201_get_power(struct net_device *dev,
@@ -1627,15 +1618,11 @@ static int zd1201_set_hostauth(struct net_device *dev,
     struct iw_request_info *info, struct iw_param *rrq, char *extra)
 {
 	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	int err;
 
 	if (!zd->ap)
 		return -EOPNOTSUPP;
 
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
-	if (err)
-		return err;
-	return 0;
+	return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
 }
 
 static int zd1201_get_hostauth(struct net_device *dev,
@@ -1744,7 +1731,7 @@ static int zd1201_probe(struct usb_interface *interface,
 {
 	struct zd1201 *zd;
 	struct usb_device *usb;
-	int i, err;
+	int err;
 	short porttype;
 	char buf[IW_ESSID_MAX_SIZE+2];
 
@@ -1773,9 +1760,7 @@ static int zd1201_probe(struct usb_interface *interface,
 	if (!zd->rx_urb || !zd->tx_urb)
 		goto err_zd;
 
-	for(i = 0; i<100; i++)
-		udelay(1000);
-
+	mdelay(100);
 	err = zd1201_drvr_start(zd);
 	if (err)
 		goto err_zd;
@@ -1833,7 +1818,7 @@ static int zd1201_probe(struct usb_interface *interface,
 		goto err_net;
 	dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
 	    zd->dev->name);
-	
+
 	usb_set_intfdata(interface, zd);
 	return 0;
 
diff --git a/drivers/usb/net/zd1201.h b/drivers/net/wireless/zd1201.h
similarity index 100%
rename from drivers/usb/net/zd1201.h
rename to drivers/net/wireless/zd1201.h
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index efd6ca7e4ac55eecc6e82cf1e9acd26ed30d3ded..054059632a219e54d2217486df8da039a7a0bff9 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -301,21 +301,4 @@ config USB_NET_ZAURUS
 	  some cases CDC MDLM) protocol, not "g_ether".
 
 
-config USB_ZD1201
-	tristate "USB ZD1201 based Wireless device support"
-	depends on NET_RADIO
-	select FW_LOADER
-	---help---
-	  Say Y if you want to use wireless LAN adapters based on the ZyDAS
-	  ZD1201 chip.
-
-	  This driver makes the adapter appear as a normal Ethernet interface,
-	  typically on wlan0.
-	  
-	  The zd1201 device requires external firmware to be loaded.
-	  This can be found at http://linux-lc100020.sourceforge.net/
-	  
-	  To compile this driver as a module, choose M here: the
-	  module will be called zd1201.
-
 endmenu
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index a21e6eaabaf67f2f678404b48217741e8f453a8f..160f19dbdf121253ad360e8d64313aff8253d25d 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_NET_RNDIS_HOST)	+= rndis_host.o
 obj-$(CONFIG_USB_NET_CDC_SUBSET)	+= cdc_subset.o
 obj-$(CONFIG_USB_NET_ZAURUS)	+= zaurus.o
 obj-$(CONFIG_USB_USBNET)	+= usbnet.o
-obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 293e920ca59d7686cc2a591bdfa53dfe9d7995c9..d5147770ad474abbe290c20c1a7d97bdf9ab16e7 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -1247,7 +1247,8 @@ extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
 extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
-			      struct ieee80211_hdr *frame, int len);
+			      struct ieee80211_hdr *frame, int hdr_len,
+			      int total_len, int encrypt_mpdu);
 
 /* ieee80211_rx.c */
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index 703463a8828b2f8e5ba3a14f6214f968c4fd3c3e..7a483ab4022f98cd20d4946dc7f61054d08e30f0 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -310,7 +310,7 @@ extern void ieee80211softmac_stop(struct net_device *dev);
  *	- context set to the context data you want passed
  * The return value is 0, or an error.
  */
-typedef void (*notify_function_ptr)(struct net_device *dev, void *context);
+typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context);
 
 #define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
 #define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 233d527c69533c275dcc25363a750358ed8c5b7d..6a5de1b84459c147864406522e7c682a03e473ca 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -555,7 +555,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 /* Incoming 802.11 strucure is converted to a TXB
  * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_tx_frame(struct ieee80211_device *ieee,
-		       struct ieee80211_hdr *frame, int len)
+		       struct ieee80211_hdr *frame, int hdr_len, int total_len,
+		       int encrypt_mpdu)
 {
 	struct ieee80211_txb *txb = NULL;
 	unsigned long flags;
@@ -565,6 +566,9 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
 
 	spin_lock_irqsave(&ieee->lock, flags);
 
+	if (encrypt_mpdu && !ieee->sec.encrypt)
+		encrypt_mpdu = 0;
+
 	/* If there is no driver handler to take the TXB, dont' bother
 	 * creating it... */
 	if (!ieee->hard_start_xmit) {
@@ -572,32 +576,41 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
 		goto success;
 	}
 
-	if (unlikely(len < 24)) {
+	if (unlikely(total_len < 24)) {
 		printk(KERN_WARNING "%s: skb too small (%d).\n",
-		       ieee->dev->name, len);
+		       ieee->dev->name, total_len);
 		goto success;
 	}
 
+	if (encrypt_mpdu)
+		frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+
 	/* When we allocate the TXB we allocate enough space for the reserve
 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
 	 * postfix, header, FCS, etc.) */
-	txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC);
+	txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC);
 	if (unlikely(!txb)) {
 		printk(KERN_WARNING "%s: Could not allocate TXB\n",
 		       ieee->dev->name);
 		goto failed;
 	}
 	txb->encrypted = 0;
-	txb->payload_size = len;
+	txb->payload_size = total_len;
 
 	skb_frag = txb->fragments[0];
 
-	memcpy(skb_put(skb_frag, len), frame, len);
+	memcpy(skb_put(skb_frag, total_len), frame, total_len);
 
 	if (ieee->config &
 	    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 		skb_put(skb_frag, 4);
 
+	/* To avoid overcomplicating things, we do the corner-case frame
+	 * encryption in software. The only real situation where encryption is
+	 * needed here is during software-based shared key authentication. */
+	if (encrypt_mpdu)
+		ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
+
       success:
 	spin_unlock_irqrestore(&ieee->lock, flags);
 
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index f2a27cc6ecb1fc653fa7643e543cd1e7dfb4a3f8..2811651cb13404b114f09b23ea8a38124a18953e 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -2,6 +2,7 @@ config IEEE80211_SOFTMAC
 	tristate "Software MAC add-on to the IEEE 802.11 networking stack"
 	depends on IEEE80211 && EXPERIMENTAL
 	select WIRELESS_EXT
+	select IEEE80211_CRYPT_WEP
 	---help---
 	This option enables the hardware independent software MAC addon
 	for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 5d90b9a6ee50f5863027a1e957b1d918bbdfa0b7..5e9a90651d04f5433225357dad60ac5c396218d2 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -164,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
 }
 
 static void
-ieee80211softmac_assoc_notify(struct net_device *dev, void *context)
+ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 	ieee80211softmac_assoc_work((void*)mac);
 }
 
+static void
+ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
+{
+	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+
+	switch (event_type) {
+	case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
+		ieee80211softmac_assoc_work((void*)mac);
+		break;
+	case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
+	case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
+		ieee80211softmac_disassoc(mac);
+		break;
+	}
+}
+
 /* This function is called to handle userspace requests (asynchronously) */
 void
 ieee80211softmac_assoc_work(void *d)
@@ -249,7 +265,7 @@ ieee80211softmac_assoc_work(void *d)
 			 * Maybe we can hope to have more memory after scanning finishes ;)
 			 */
 			dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
-			ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL);
+			ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
 			if (ieee80211softmac_start_scan(mac))
 				dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
 			return;
@@ -284,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
 		 * otherwise adding the notification would be racy. */
 		if (!ieee80211softmac_auth_req(mac, found)) {
 			dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
-			ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL);
+			ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
 		} else {
 			printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
 			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 084b6211f293e30c0cbcf1505d918d02f4b9d0f0..90b8484e509b8505cae70e6e61357a52bc1fedda 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -107,6 +107,7 @@ ieee80211softmac_auth_queue(void *data)
 	printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
 	/* Remove this item from the queue */
 	spin_lock_irqsave(&mac->lock, flags);
+	net->authenticating = 0;
 	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
 	cancel_delayed_work(&auth->work); /* just to make sure... */
 	list_del(&auth->list);
@@ -212,13 +213,13 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
 			aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; 
 			spin_unlock_irqrestore(&mac->lock, flags);
 
-			/* Switch to correct channel for this network */
-			mac->set_channel(mac->dev, net->channel);
-			
-			/* Send our response (How to encrypt?) */
+			/* Send our response */
 			ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
-			break;
+			return 0;
 		case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
+			kfree(net->challenge);
+			net->challenge = NULL;
+			net->challenge_len = 0;
 			/* Check the status code of the response */
 			switch(auth->status) {
 			case WLAN_STATUS_SUCCESS:
@@ -229,6 +230,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
 				spin_unlock_irqrestore(&mac->lock, flags);
 				printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", 
 					MAC_ARG(net->bssid));
+				ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
 				break;
 			default:
 				printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", 
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 4b153f7cc96c7096f41515a15013882734d45197..f34fa2ef666b5fa56247f060bae06a2d94f7f06e 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -78,7 +78,7 @@ ieee80211softmac_notify_callback(void *d)
 	struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
 	kfree(d);
 	
-	event.fun(event.mac->dev, event.context);
+	event.fun(event.mac->dev, event.event_type, event.context);
 }
 
 int
@@ -167,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
 			if ((eventptr->event_type == event || eventptr->event_type == -1)
 				&& (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
 				list_del(&eventptr->list);
+				/* User may have subscribed to ANY event, so
+				 * we tell them which event triggered it. */
+				eventptr->event_type = event;
 				schedule_work(&eventptr->work);
 			}
 		}
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index cc6cd56c85b100af93a7216442c4a6d9ade20e36..09541611e48ceec609d8c66db1173f757676ccc7 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -149,6 +149,56 @@ ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
 	 * shouldn't the sequence number be in ieee80211? */
 }
 
+static u16
+ieee80211softmac_capabilities(struct ieee80211softmac_device *mac,
+	struct ieee80211softmac_network *net)
+{
+	u16 capability = 0;
+
+	/* ESS and IBSS bits are set according to the current mode */
+	switch (mac->ieee->iw_mode) {
+	case IW_MODE_INFRA:
+		capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+		break;
+	case IW_MODE_ADHOC:
+		capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+		break;
+	case IW_MODE_AUTO:
+		capability = net->capabilities &
+			(WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
+		break;
+	default:
+		/* bleh. we don't ever go to these modes */
+		printk(KERN_ERR PFX "invalid iw_mode!\n");
+		break;
+	}
+
+	/* CF Pollable / CF Poll Request */
+	/* Needs to be implemented, for now, the 0's == not supported */
+
+	/* Privacy Bit */
+	capability |= mac->ieee->sec.level ?
+		cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
+
+	/* Short Preamble */
+	/* Always supported: we probably won't ever be powering devices which
+	 * dont support this... */
+	capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+
+	/* PBCC */
+	/* Not widely used */
+
+	/* Channel Agility */
+	/* Not widely used */
+
+	/* Short Slot */
+	/* Will be implemented later */
+
+	/* DSSS-OFDM */
+	/* Not widely used */
+
+	return capability;
+}
 
 /*****************************************************************************
  * Create Management packets
@@ -179,27 +229,6 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
 
-	/* Fill in capability Info */
-	switch (mac->ieee->iw_mode) {
-	case IW_MODE_INFRA:
-		(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
-		break;
-	case IW_MODE_ADHOC:
-		(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
-		break;
-	case IW_MODE_AUTO:
-		(*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
-		break;
-	default:
-		/* bleh. we don't ever go to these modes */
-		printk(KERN_ERR PFX "invalid iw_mode!\n");
-		break;
-	}
-	/* Need to add this
-	(*pkt)->capability |= mac->ieee->short_slot ? 
-			cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
-	 */
-	(*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
 	/* Fill in Listen Interval (?) */
 	(*pkt)->listen_interval = cpu_to_le16(10);
 	
@@ -239,17 +268,9 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
 
-	/* Fill in capability Info */
-	(*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ? 
-				cpu_to_le16(WLAN_CAPABILITY_ESS) :
-				cpu_to_le16(WLAN_CAPABILITY_IBSS);
-	/*
-	(*pkt)->capability |= mac->ieee->short_slot ? 
-			cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
-	 */
-	(*pkt)->capability |= mac->ieee->sec.level ?
-			cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
-		
+	/* Fill in the capabilities */
+	(*pkt)->capability = ieee80211softmac_capabilities(mac, net);
+
 	/* Fill in Listen Interval (?) */
 	(*pkt)->listen_interval = cpu_to_le16(10);
 	/* Fill in the current AP MAC */
@@ -268,26 +289,27 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
 static u32
 ieee80211softmac_auth(struct ieee80211_auth **pkt, 
 	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
-	u16 transaction, u16 status)
+	u16 transaction, u16 status, int *encrypt_mpdu)
 {
 	u8 *data;
+	int auth_mode = mac->ieee->sec.auth_mode;
+	int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY
+		&& transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE);
+
 	/* Allocate Packet */
 	(*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
 		2 +		/* Auth Algorithm */
 		2 +		/* Auth Transaction Seq */
 		2 +		/* Status Code */
 		 /* Challenge Text IE */
-		mac->ieee->open_wep ? 0 : 
-		1 + 1 + WLAN_AUTH_CHALLENGE_LEN
-	);	
+		is_shared_response ? 0 : 1 + 1 + net->challenge_len
+	);
 	if (unlikely((*pkt) == NULL))
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
 		
 	/* Algorithm */
-	(*pkt)->algorithm = mac->ieee->open_wep ? 
-		cpu_to_le16(WLAN_AUTH_OPEN) :
-		cpu_to_le16(WLAN_AUTH_SHARED_KEY);
+	(*pkt)->algorithm = cpu_to_le16(auth_mode);
 	/* Transaction */
 	(*pkt)->transaction = cpu_to_le16(transaction);
 	/* Status */
@@ -295,18 +317,20 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt,
 	
 	data = (u8 *)(*pkt)->info_element;
 	/* Challenge Text */
-	if(!mac->ieee->open_wep){
+	if (is_shared_response) {
 		*data = MFIE_TYPE_CHALLENGE;
 		data++;
 		
 		/* Copy the challenge in */
-		// *data = challenge length
-		// data += sizeof(u16);
-		// memcpy(data, challenge, challenge length);
-		// data += challenge length;
-		
-		/* Add the full size to the packet length */
-	}
+		*data = net->challenge_len;
+		data++;
+		memcpy(data, net->challenge, net->challenge_len);
+		data += net->challenge_len;
+
+		/* Make sure this frame gets encrypted with the shared key */
+		*encrypt_mpdu = 1;
+	} else
+		*encrypt_mpdu = 0;
 
 	/* Return the packet size */
 	return (data - (u8 *)(*pkt));
@@ -396,6 +420,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
 {
 	void *pkt = NULL;
 	u32 pkt_size = 0;
+	int encrypt_mpdu = 0;
 
 	switch(type) {
 	case IEEE80211_STYPE_ASSOC_REQ:
@@ -405,7 +430,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
 		pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
 		break;
 	case IEEE80211_STYPE_AUTH:
-		pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16));
+		pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu);
 		break;
 	case IEEE80211_STYPE_DISASSOC:
 	case IEEE80211_STYPE_DEAUTH:
@@ -434,52 +459,8 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
 	 * or get rid of it alltogether?
 	 * Does this work for you now?
 	 */
-	ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size);
-
-	kfree(pkt);
-	return 0;
-}
-
-
-/* Create an rts/cts frame */
-static u32
-ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt,
-	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, 
-	u32 type)
-{
-	/* Allocate Packet */
-	(*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC);	
-	memset(*pkt, 0, IEEE80211_2ADDR_LEN);
-	if((*pkt) == NULL)
-		return 0;
-	ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid);
-	return IEEE80211_2ADDR_LEN;
-}
-
-
-/* Sends a control packet */
-static int
-ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac,
-	struct ieee80211softmac_network *net, u32 type, u32 arg)
-{
-	void *pkt = NULL;
-	u32 pkt_size = 0;
-	
-	switch(type) {
-	case IEEE80211_STYPE_RTS:
-	case IEEE80211_STYPE_CTS:
-		pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type);
-		break;
-	default:
-		printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type);
-		return -EINVAL;
-	}
-
-	if(pkt_size == 0)
-		return -ENOMEM;
-	
-	/* Send the packet to the ieee80211 layer for tx */
-	ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size);
+	ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt,
+		IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
 
 	kfree(pkt);
 	return 0;